基礎LESSON 13
この教材で学ぶこと JVM、record、collection、interfaceからJavaの設計を学びます。Java入門
対象読者: 基本文法を学び、静的型付けとobject-oriented designへ進みたい人。
この教材でできるようになること
- source、compiler、bytecode、JVMの関係を説明できる
- class、record、interfaceを用途から選べる
- collectionと例外を扱える
- mutableな状態を小さく保つ設計を説明できる
1. Javaが動くまで
Main.java → javac → Main.class(bytecode)→ JVMで実行
public class Main {
public static void main(String[] args) {
System.out.println("Hello, Java");
}
}
javac Main.java
java Main
Javaはlanguageであると同時に、JVMを中心とするplatformでもあります。
2. recordで値を表す
public record Lesson(String id, String title, Level level) {
public Lesson {
if (id == null || id.isBlank()) {
throw new IllegalArgumentException("id must not be blank");
}
if (title == null || title.isBlank()) {
throw new IllegalArgumentException("title must not be blank");
}
}
}
enum Level {
BEGINNER, INTERMEDIATE, ADVANCED
}
recordは値を保持するdata carrierに向いています。検証をcompact constructorへ集めれば、不正状態の生成を防げます。
3. collectionを扱う
import java.util.List;
public final class Curriculum {
public static long countBeginnerLessons(List<Lesson> lessons) {
return lessons.stream()
.filter(lesson -> lesson.level() == Level.BEGINNER)
.count();
}
}
引数で受け取ったcollectionを不要に変更せず、結果を返す関数として書くと予測しやすくなります。
4. interfaceで境界を作る
import java.util.List;
public interface LessonRepository {
List<Lesson> findAll();
void save(Lesson lesson);
}
domain logicがdatabaseやHTTP clientへ直接依存せずinterfaceへ依存すれば、保存方法を差し替えやすくなります。ただし、実装が一つで変更理由もない段階から何でもinterface化する必要はありません。
5. 例外を意味で選ぶ
public Lesson requireLesson(String id, LessonRepository repository) {
return repository.findAll().stream()
.filter(lesson -> lesson.id().equals(id))
.findFirst()
.orElseThrow(() -> new IllegalArgumentException("unknown lesson: " + id));
}
catchする側が回復できる粒度で例外を選び、秘密情報や内部構成を利用者向けmessageへ出さないようにします。
6. packageで責務を分ける
src/main/java/example/study/
├── domain/
│ ├── Lesson.java
│ └── Curriculum.java
├── application/
│ └── CompleteLesson.java
└── infrastructure/
└── FileLessonRepository.java
名前はframeworkではなく、扱うdomainや責務を表すようにします。
演習: 学習計画domain
次を実装してください。
Lesson: id、title、estimatedMinutesStudyPlan: lesson一覧を持つ- 合計時間を返すmethod
- id重複を拒否する処理
- 空titleと0以下の時間を拒否
正常系だけでなく、空一覧、重複id、境界値をテストします。
理解チェック
- source、bytecode、JVMを区別できる
- class、record、interfaceを使う理由を説明できる
- collection操作を副作用の小さい関数へ分けられる
- 不正状態を生成時に拒否できる
公式資料
次に読む
設計とリファクタリングで、責務と依存関係を整理します。