HOWTO · Java

Java インターフェイスで静的メソッドを定義する

このチュートリアルでは、Java インターフェイスで静的メソッドを定義する方法、そのルールとは何か、およびこれらの静的メソッドをオーバーライドできない理由を示します。

このページの内容

このチュートリアルでは、Java interface で static メソッドを使用するための規則をリストし、それらを定義する方法と、それらをオーバーライドできない理由を示します。 また、Java 8 より前のインターフェースに static メソッドがない理由についても調べます。

Java interface の static メソッド

Java インターフェイスの static メソッドに入る前に、この interface を implements するクラスで定義された 1つまたは複数の abstract メソッド (本体のないメソッド) を含む interface について知っておくことが重要です。 .

これらの abstract メソッドは public 修飾子を記述してもしなくても public メソッドであることに注意してください。

コード例:

public interface Messages {
  // public & abstract
  public void display();
}

public class Test implements Messages {
  // implementation of abstract method
  public void display() {
    System.out.println("Hi! Welcome to the DelftStack");
  }

  public static void main(String[] args) {
    Test test = new Test();
    test.display();
  }
}

出力:

Hi! Welcome to the DelftStack

display() という名前の abstract メソッドは public メソッドであることを思い出してください。display() メソッドを実行するには、Test クラスをインスタンス化する必要があります。

一方、static メソッドは、それらが定義されているクラス自体に関連付けられており、これらの static メソッドを使用するためにクラスをインスタンス化する必要はありません。 Java 8 の時点で、static インターフェイス メソッドを使用できるようになりました。

これで、完全な本体と、その特定の static メソッドに必要なすべての命令が interface に用意されました。 static メソッドは、インスタンス レベルではなく、クラス レベルでのみアクセスできることに注意してください。

したがって、次のように static メソッドにアクセスできます。

コード例:

public interface Messages {
  // static method
  static void display() {
    System.out.println("Hello! Nice to meet you");
  }
}

public class Test {
  public static void main(String[] args) {
    Messages.display();
  }
}

出力:

Hello! Nice to meet you

問題は、static メソッドをオーバーライドできるかどうかです。 いいえ、static メソッドをオーバーライドすることはできません。 そうしないと、コンパイル エラーが発生します。

さらに、static メソッドは隠されているため、実装クラスのインスタンスを介してそれらを呼び出すことはできません。 コンパイル エラーを生成する次の例を参照してください。

コード例:

public interface Messages {
  static void display() {
    System.out.println("Hello! Nice to meet you");
  }
}

public class Test implements Messages {
  @Override
  public void display() {
    System.out.println("Override");
  }
  public static void main(String[] args) {
    Test test = new Test();
    test.display();
  }
}

以下は、上記のコード フェンスによって生成されるエラーの説明です。

出力:

Test.java:25: error: method does not override or implement a method from a supertype
  @Override
  ^
1 error

interface で static メソッドを使用することの重要性

Java インターフェイスで static メソッドを使用すると、次の利点が得られます。

  1. interface の static メソッドは、サブクラスまたはサブインターフェースに継承またはオーバーライドさせたくない動作をカプセル化します。
  2. Java interface のこれらの static メソッドは、特定の実装タイプのクラスに限定されない再利用可能なユーティリティの開発に役立ちます。

interface における static メソッドの規則

次のセクションでは、static メソッドを使用する場合の上記の利点のルールを示します。

インターフェイスのデフォルト メソッド はデフォルト動作の命令を保持し、実装クラスはそれをオーバーライドするか、そのまま継承することにより、より具体的な命令を提供することを選択できます。 デフォルトのメソッドと同様に、static メソッドにはその動作の本体 (一連の命令) が含まれていますが、以前に学んだように、実装クラスはその interface の static メソッドを継承またはオーバーライドすることはできません。

Java interface で static メソッドを使用する場合は、次の規則を覚えておく必要があります。

  1. これらのメソッドには本体が必要です。
  2. interface 名を使用してこれらの static メソッドのみを実行できます。
  3. これらのメソッドには、メソッドの宣言に static 修飾子が必要です。 指定しない場合、デフォルトで public になります。 必要に応じて、それらを private にすることもできます。
  4. 他の abstract またはデフォルトのメソッドを呼び出すことはできません。
  5. サブクラスまたはサブインターフェースは、これらの static メソッドをオーバーライドまたは継承することはできません。

さて、この時点で、頭の中に 2つの質問があるかもしれません。

  1. 昔 (Java 8 のリリース前) に static メソッドを使用できなかったのはなぜですか?
  2. static メソッドをオーバーライドできないのはなぜですか?

これらの両方の質問に対する答えを見つけてみましょう。

Java 8 より前のインターフェースに static メソッドがない理由

Java インターフェースが Java 8 のリリース前に static メソッドを持たなかった理由として、強力で主要な技術的原因はありませんでした。これらの static メソッドは、小さな言語の更新または変更と見なされ、Java に追加するという公式の提案がありました。 7 でしたが、その後、いくつかの合併症のために削除されました。

最後に、Java 8 では、インターフェースで static メソッドが導入されました。 Java 8 の時点で、デフォルトの実装でオーバーライド可能なインスタンス関数/メソッドについても学びました。

まだインスタンス フィールドが含まれていないことを思い出してください。 これらの機能は、ここ (JSR 335 パート H) で読むことができる lambda 式サポートの一部です。

static メソッドをオーバーライドできない理由

static メソッドはコンパイル時に解決されます。 動的ディスパッチは、コンパイラがオブジェクトの具体的な型を判断できないインスタンス メソッドについて意味があります。 したがって、呼び出すメソッドを解決できません。

しかし、static メソッドを実行するにはクラスが必要です。 その特定のクラスはコンパイル時に 静的に 知られているため、動的ディスパッチは不要です。

すべてのクラスに、メソッドのシグネチャ (名前とパラメーターの型) を実際のコードにマップしてメソッドを実装する HashTable があるとします。 VM がインスタンスでメソッドを実行しようとすると、そのクラスのオブジェクトをクエリし、クラスのテーブルで要求された署名を探します。

メソッド本体が見つかった場合に呼び出されます。 それ以外の場合は、ルックアップが繰り返されるクラスの親クラスが取得されます。 このプロセスは、メソッドが見つかるか、親クラスがなくなるまで続きます (これにより、NoSuchMethodError が生成されます)。

それぞれのテーブルに同じメソッド シグネチャのサブクラスとスーパークラスのエントリがある場合、サブクラスのバージョンが最初に検出され、スーパークラスのバージョンは決して使用されません。これはオーバーライドです。

オブジェクト インスタンスをスキップしてサブクラスから開始すると仮定すると、解決は上記のように進み、一種の オーバーライド可能 静的 メソッドを提供できます。 この解決は、コンパイル時にのみ発生することに注意してください。

ただし、コンパイラは、未指定の型のオブジェクトにそのクラスのクエリを実行するまで待機するのではなく、既知のクラスから開始することがわかっています。 したがって、static メソッドをオーバーライドしても意味がありません。