クラス: OOP の基礎
フィールド + メソッド = オブジェクト。カプセル化が大事。
なぜクラスが必要か?
クラスは「データ」と「操作」を一つにまとめる仕組みです。例えば、ユーザー情報(名前、年齢)とその操作(年齢を増やす、名前を取得する)を別々に管理すると、データと操作が不一致になるリスクがあります。クラスを使うと、データと操作をセットにして管理できるため、コードが読みやすく、保守しやすくなります。
いつ使うか?
クラスは、以下のような場面で使います: 1. **データと操作をセットにしたいとき**: ユーザー、商品、注文など、データとそれを操作するメソッドを一つにまとめたいとき。 2. **再利用性を高めたいとき**: クラスを定義すれば、同じ設計図から複数のオブジェクト(インスタンス)を作成できる。 3. **カプセル化が必要なとき**: データを直接触らせず、メソッドを通して操作させたいとき。
実践テクニック
不変性を活用する
オブジェクトを不変(immutable)にすると、スレッドセーフでバグが少なくなります。Java 16以降は `record` を使うと、不変クラスを簡潔に書けます。不変オブジェクトは、作成後に状態が変わらないため、予測可能でテストしやすいコードになります。
null安全性を考慮する
Javaでは `null` が原因で `NullPointerException` が発生することがよくあります。これを防ぐために、フィールドやメソッドの戻り値に `@Nullable` や `@NonNull` アノテーションを付けて、null許容を明示することをお勧めします。また、`Optional` クラスを使うと、nullチェックを強制できるため、より安全なコードになります。
Lombokでボイラープレートを削減する
Javaのクラスでは、getter、setter、`toString`、`equals`、`hashCode` などのボイラープレートコードが多くなりがちです。Lombokライブラリを使うと、`@Data` アノテーションを付けるだけでこれらのメソッドを自動生成できるため、コードが簡潔になります。ただし、チームの規約に従って使用してください。
クラス
public class Person { // フィールド private String name; private int age;
// コンストラクタ public Person(String name, int age) { this.name = name; this.age = age; }
// ゲッター public String getName() { return name; }
// セッター public void setAge(int age) { if (age >= 0) { this.age = age; } }
// メソッド public void greet() { System.out.println("Hello, I'm " + name); }}
// 使用Person p = new Person("Alice", 30);p.greet();Hello, I'm Alice
// ❌ Bad: public フィールドpublic class User { public String name; // 直接アクセス可能 public int age;}// ✅ Good: カプセル化public class User { private String name; private int age;
public String getName() { return name; }}パターン
// static メンバーpublic class Counter { private static int count = 0; // クラス変数
public Counter() { count++; }
public static int getCount() { // クラスメソッド return count; }}
// レコード (Java 16+)public record Point(int x, int y) {}// equals, hashCode, toString 自動生成
// toString, equals, hashCode@Overridepublic String toString() { return "Person{name='" + name + "', age=" + age + "}";}
@Overridepublic boolean equals(Object o) { if (this == o) return true; if (!(o instanceof Person)) return false; Person other = (Person) o; return age == other.age && name.equals(other.name);}