HOWTO · Java

Java の静的クラス

この記事では、Java 静的クラスを紹介します。

このページの内容

Javaでは、トップレベルクラスを static として宣言できません。一方、別のクラスの内部に宣言するクラスには static を付けられます。これを静的ネストクラスと呼びます。静的ネストクラスは、外側のクラスのインスタンスがなくてもインスタンス化でき、外側のクラスの静的メンバーを使用できます。呼び出し側からインスタンスを作れないユーティリティクラスが必要なら、代わりにコンストラクターを private にします。これは別の設計パターンです。

Javaの静的ネストクラスとは

静的ネストクラスは、別のクラスの内部に static キーワードを付けて宣言するメンバー型です。static 修飾子が付いているため、静的ネストクラスのインスタンスには、外側のクラスのオブジェクトへの暗黙的な参照がありません。これは、静的ネストクラス自体をインスタンス化できないという意味ではありません。型は Container.Entry のように外側の型を通じて参照し、そのインスタンスメソッドは静的ネストクラスのインスタンスに対して呼び出します。

静的ネストクラスからは、外側のクラスの private なメンバーも含め、静的メンバーにアクセスできます。外側のクラスのインスタンス変数やインスタンスメソッドは、外側のオブジェクトがあるかのように参照できません。ただし、外側のオブジェクトを明示的に渡せばアクセスできます。

静的ネストクラスの宣言と使用方法

メンバークラスに static を付けて宣言し、外側の型名を使ってインスタンスを作成します。次の一通りの例では、外側のクラスの静的フィールドへのアクセスも示します。

この例を実行します。

このセクションのコードと表示されるラベルや出力は英語のままです。

public class Container {
    private static int count = 3;

    public static class Entry {
        public int value() {
            return count;
        }
    }

    public static void main(String[] args) {
        Container.Entry entry = new Container.Entry();
        System.out.println(entry.value());
    }
}
3

この例を実行すると 3 が出力されます。例を変更するときは、ネストクラスを外側のクラス内に置き、Container の外部では型を Container.Entry と修飾してください。Entry オブジェクトは通常のインスタンスですが、count は外側のクラス自体に属します。

静的ネストクラスと内部クラスの違い

static ではないメンバークラスは、一般に内部クラスと呼ばれます。内部クラスの作成には外側のインスタンスが必要です。まず Container オブジェクトを作り、次に container.new Inner() を使います。内部クラスのインスタンスは外側のオブジェクトとの関連を保持するため、そのインスタンスメンバーを直接使用できます。

静的ネストクラスには、そのような暗黙の関連付けはありません。外側のクラスのインスタンスフィールドを読むには、Container オブジェクトを渡すか、別の方法で取得し、その参照を通じてフィールドにアクセスします。どちらの種類のネストクラスも、Javaのネスト型に関するアクセス規則で許可されたメンバーにアクセスできます。主な違いは、外側のインスタンスを自動的に利用できるかどうかです。

インスタンス化できないユーティリティクラスの作成

ユーティリティクラスは、オブジェクトごとの状態を必要としない処理や定数をまとめるクラスです。通常のトップレベルクラスに該当するメンバーを置き、適切なメンバーに static を付けます。さらにコンストラクターを private にすると、通常の呼び出し側がクラスの外から new を呼び出せなくなります。たとえば、次のように記述します。public final class TextTools { private TextTools() {} public static String join(String first, String second) { return first + second; } }。呼び出し方は TextTools.join("static ", "utility") です。

private コンストラクターは、通常の外部からのインスタンス作成を防ぎますが、TextTools を静的クラスに変えるわけではありません。Javaにはトップレベルの静的クラスはありません。クラスを final にするのは任意で、サブクラス化を禁止するだけです。ユーティリティメソッドに必須の指定ではなく、その制約が設計上必要な場合に使います。

静的クラスに関するよくある誤解

静的ネストクラスはインスタンス化できます。static が取り除くのは、外側のインスタンスを暗黙に必要とする条件です。静的ネストクラスのインスタンスメソッドは、そのクラス自身のインスタンスフィールドを使用できます。外側のクラス名でネスト型を修飾しますが、そのインスタンスメソッドを呼び出すにはネスト型のオブジェクトが必要です。

静的コンテキストでは、外側のオブジェクトが自動的に利用できないため、修飾なしで外側のインスタンスメンバーにアクセスすることはできません。明示的なオブジェクト参照を通じてならアクセスできます。同様に、ユーティリティクラスの private コンストラクターが防ぐのはクラス外からの通常の呼び出しであり、あらゆる状況でインスタンス作成を不可能にするわけではありません。こうした違いを理解すると、Javaのネストクラス構文とユーティリティクラスの設計パターンを区別できます。