この内容は古いバージョンです。最新バージョンを表示するには、戻るボタンを押してください。
バージョン:7
ページ更新者:T
更新日時:2026-06-11 07:10:02

タイトル: クラスとメソッド
SEOタイトル: Java クラスとメソッド完全ガイド — フィールド・修飾子・継承

この記事の要点
  • クラスは「設計図」、オブジェクトはその「実体」。new ClassName() でインスタンス化
  • クラスは フィールド (状態)メソッド (振る舞い) + コンストラクタ を持つ
  • アクセス修飾子: public / protected / package-private / private の 4 段階
  • static はインスタンス不要 (クラス共有)、final は変更/継承禁止、abstract は実装なし
  • Java 14+ record でデータクラスを 1 行で。Java 17+ sealed で継承先を限定

クラスの基本構造

public class User {
    // フィールド (インスタンス変数)
    private String name;
    private int age;

    // クラス変数 (static)
    private static int totalCount = 0;

    // 定数
    public static final int MAX_AGE = 150;

    // コンストラクタ
    public User(String name, int age) {
        this.name = name;
        this.age = age;
        totalCount++;
    }

    // インスタンスメソッド
    public String greet() {
        return "Hello, I'm " + this.name;
    }

    // static メソッド (インスタンス不要)
    public static int getTotalCount() {
        return totalCount;
    }

    // getter / setter
    public String getName()           { return name; }
    public void setName(String name)  { this.name = name; }
}

// 使用
User u = new User("Taro", 25);
System.out.println(u.greet());            // インスタンスメソッド
System.out.println(User.getTotalCount()); // static メソッド
System.out.println(User.MAX_AGE);          // 定数

アクセス修飾子

修飾子同一クラス同一パッケージ子クラス他パッケージ
public
protected
(なし) package-private
private

原則:

  • フィールドは private (カプセル化) → getter/setter で公開
  • メソッドは最小限の公開 (内部実装は private)
  • クラスは public または package-private (1 ファイル 1 public クラス)

static (クラス変数 / クラスメソッド)

public class Counter {
    private static int count = 0;  // クラス全体で 1 つ

    public static void increment() {  // インスタンス不要
        count++;
    }

    public static int get() {
        return count;
    }
}

Counter.increment();
Counter.increment();
System.out.println(Counter.get());  // 2

// static メソッドからインスタンス変数 / メソッドにアクセスは ★ 不可
public class Bad {
    private int x;            // インスタンス変数

    public static void f() {
        // System.out.println(x);  // ★ コンパイルエラー
    }
}

final (変更禁止 / 継承禁止)

// final 変数: 再代入不可
public final int MAX = 100;

// final メソッド: オーバーライド不可
public final void critical() { ... }

// final クラス: 継承不可
public final class String { ... }   // String, Integer, LocalDate 等

// 引数 final
public void process(final List<String> list) {
    // list = new ArrayList<>();  // ★ NG
    list.add("a");                 // OK (参照先の中身は変えられる)
}

abstract クラス / インターフェース

// abstract クラス: インスタンス化不可、子で実装させる
public abstract class Shape {
    public abstract double area();           // 実装なし
    public void describe() {                 // 実装あり
        System.out.println("Area = " + area());
    }
}

class Circle extends Shape {
    private double r;
    public Circle(double r) { this.r = r; }
    @Override
    public double area() { return Math.PI * r * r; }
}

// interface (Java 8+ default メソッドあり)
public interface Greetable {
    void greet();                                        // 抽象メソッド
    default void hello() { System.out.println("Hi"); }   // default 実装
    static void info() { System.out.println("v1"); }     // static
}

class Hello implements Greetable {
    @Override
    public void greet() { System.out.println("Hello!"); }
}

インナークラス (内部クラス)

public class Outer {
    private int x = 10;

    // 1. インスタンス内部クラス
    public class Inner {
        public int sum() { return x + 1; }   // Outer の x にアクセス可
    }

    // 2. static ネストクラス
    public static class StaticNested {
        public int val = 5;
    }

    // 3. ローカルクラス (メソッド内)
    public void method() {
        class Local {
            public void hi() { System.out.println(x); }
        }
        new Local().hi();
    }

    // 4. 匿名クラス
    public Runnable task = new Runnable() {
        @Override
        public void run() { System.out.println("run"); }
    };
}

// 利用
Outer o = new Outer();
Outer.Inner i = o.new Inner();
Outer.StaticNested s = new Outer.StaticNested();

record (Java 14+) — データクラスを 1 行で

// 旧来 (50 行ぐらいの boilerplate が必要)
public final class Point {
    private final int x;
    private final int y;
    public Point(int x, int y) { this.x = x; this.y = y; }
    public int x() { return x; }
    public int y() { return y; }
    @Override public boolean equals(Object o) { ... }
    @Override public int hashCode() { ... }
    @Override public String toString() { ... }
}

// ✅ record で 1 行
public record Point(int x, int y) {}

// 自動生成されるもの:
//   - private final フィールド x, y
//   - public Point(int x, int y) コンストラクタ
//   - x(), y() アクセサ
//   - equals / hashCode / toString

Point p = new Point(1, 2);
System.out.println(p.x());        // 1
System.out.println(p);            // Point[x=1, y=2]

// メソッド追加も可
public record Money(long amount, String currency) {
    public Money plus(Money other) {
        return new Money(amount + other.amount, currency);
    }
}

sealed クラス (Java 17+)

// 「これらの子のみ許可」と明示
public sealed interface Shape permits Circle, Square, Triangle {}

public final class Circle   implements Shape { ... }
public final class Square   implements Shape { ... }
public final class Triangle implements Shape { ... }
// public class Pentagon implements Shape {} // ★ コンパイルエラー (permits に無い)

// switch でも網羅性チェック可
double area(Shape s) {
    return switch (s) {
        case Circle c   -> Math.PI * c.r() * c.r();
        case Square sq  -> sq.a() * sq.a();
        case Triangle t -> 0.5 * t.base() * t.height();
        // default 不要 (Java が網羅性を保証)
    };
}

メソッドの細部

要素説明
戻り値の型void なら値を返さない
メソッド名lowerCamelCase 動詞で始める (calculateTotal)
引数0 個以上。final 可、varargs 可
throws 句検査例外を呼び出し側に通知
本体波括弧 + 文の並び
戻り値return 文 (void 以外は必須)
public int calculateTotal(int price, int quantity, double discount) throws IllegalArgumentException {
    if (quantity < 0) throw new IllegalArgumentException("quantity must be >= 0");
    double total = price * quantity * (1 - discount);
    return (int) total;
}

FAQ

Q: 1 つの .java ファイルに複数クラスを書ける?
A: 書けるが、public クラスは 1 つだけ でファイル名と一致が必須。残りは package-private。

Q: getter/setter は必須?
A: 慣習的に必須だが、record や DTO では不要 (自動生成 or public final で十分)。

Q: classinterface どちらを使う?
A: 「実装の共有」=>abstract class、「契約の定義」=>interface。Java 8+ では interface も default 実装を持てるので、迷ったら interface 優先。