Java 8は静的インターフェイスメソッドを許可します
Java 8では、インターフェースに静的メソッドを含めることができます。また、具体的なインスタンスメソッドを持つこともできますが、インスタンスフィールドを持つことはできません。
ここには本当に2つの質問があります。
- 悪い時代に、インターフェースに静的メソッドを含めることができなかったのはなぜですか?
- 静的メソッドをオーバーライドできないのはなぜですか?
インターフェースの静的メソッド
以前のバージョンではインターフェイスに静的メソッドがなかったという強力な技術的理由はありませんでした。これは、重複した質問の投稿者によってうまくまとめられています。静的インターフェースメソッドは、当初は小さな言語変更と見なされていましたが、Java 7に追加するという公式の提案がありましたが、予期しない複雑さのために後で削除されました。
最後に、Java 8は静的インターフェースメソッドを導入し、デフォルトの実装でオーバーライド可能なインスタンスメソッドを導入しました。ただし、インスタンスフィールドを含めることはできません。これらの機能はラムダ式サポートの一部であり、JSR 335のパートHで詳細を読むことができます。
静的メソッドのオーバーライド
2番目の質問に対する答えはもう少し複雑です。
静的メソッドはコンパイル時に解決できます。動的なディスパッチは、インスタンスメソッドの場合に意味があります。コンパイラーはオブジェクトの具体的なタイプを判別できないため、呼び出すメソッドを解決できません。ただし、静的メソッドを呼び出すにはクラスが必要です。そのクラスはコンパイル時に静的に認識されるため、動的ディスパッチは不要です。
ここで何が行われているのかを理解するには、インスタンスメソッドがどのように機能するかについて、少し背景が必要です。実際の実装はかなり異なると思いますが、観察された動作を正確にモデル化するメソッドディスパッチの概念について説明します。
各クラスに、メソッドシグネチャ(名前とパラメーターの型)を実際のコードチャンクにマップしてメソッドを実装するハッシュテーブルがあるとします。仮想マシンは、インスタンスのメソッドを呼び出そうとすると、オブジェクトにクラスを照会し、要求された署名をクラスのテーブルで検索します。メソッド本体が見つかると、それが呼び出されます。それ以外の場合は、クラスの親クラスが取得され、そこで検索が繰り返されます。これは、メソッドが見つかるまで、または親クラスがなくなるまで続行され、結果としてになりNoSuchMethodError
ます。
スーパークラスとサブクラスの両方に同じメソッドシグネチャのテーブル内のエントリがある場合、サブクラスのバージョンが最初に検出され、スーパークラスのバージョンは使用されません。これは「オーバーライド」です。
ここで、オブジェクトインスタンスをスキップして、サブクラスで開始するとします。解決は上記のように進行し、一種の「オーバーライド可能な」静的メソッドを提供します。ただし、コンパイラは既知のクラスから開始するので、実行時にクラスの指定されていない型のオブジェクトをクエリするのを待つのではなく、解決はすべてコンパイル時に行われます。必要なバージョンを含むクラスを常に指定できるため、静的メソッドを「オーバーライド」する意味はありません。
コンストラクター「インターフェース」
質問に対する最近の編集に対処するためのもう少し資料があります。
の各実装に対してコンストラクタのようなメソッドを効果的に義務付けたいように思えますIXMLizable
。インターフェースを使ってこれを1分間実行することを忘れて、この要件を満たすクラスがあるとします。どのように使用しますか?
class Foo implements IXMLizable<Foo> {
public static Foo newInstanceFromXML(Element e) { ... }
}
Foo obj = Foo.newInstanceFromXML(e);
Foo
新しいオブジェクトを「構築」するときは具体的な型に明示的に名前を付ける必要があるため、コンパイラーは、実際に必要なファクトリーメソッドがあることを確認できます。そうでない場合は、何ですか?私が実装することができた場合はIXMLizable
、「コンストラクタ」を欠いている、と私はインスタンスを作成し、あなたのコードにそれを渡すことを、それがあるIXMLizable
すべての必要なインタフェースを持ちます。
構築は実装の一部であり、インターフェースではありません。インターフェイスで正常に機能するコードは、コンストラクターを気にしません。コンストラクタを気にするコードはとにかく具体的な型を知る必要があり、インターフェースは無視できます。