92

インターフェース内で静的メソッドを定義できない理由について、ここでいくつかの質問がありましたが、基本的な矛盾に対処するものはありません: インターフェース内で静的フィールドと静的内部型を定義できるのに、静的メソッドを定義できないのはなぜですか?

静的な内部型は、新しいクラスを生成する構文糖衣にすぎないため、おそらく公正な比較ではありませんが、なぜメソッドではなくフィールドなのですか?

インターフェース内の静的メソッドに対する議論は、JVM が使用する仮想テーブル解決戦略を壊すというものですが、それは静的フィールドにも同様に適用されるべきではありません。つまり、コンパイラはそれをインライン化できますか?

一貫性は私が望んでいるものであり、Java はインターフェース内でいかなる形式の静的もサポートしないか、一貫してそれらを許可する必要があります。

4

15 に答える 15

49

Java 7のインターフェースで静的メソッドを許可するという公式の提案がなされました。この提案は、ProjectCoinの下で行われています。

私の個人的な意見は、それは素晴らしいアイデアだということです。実装に技術的な問題はなく、非常に論理的で合理的な方法です。Project Coinには、Java言語の一部にならないことを願ういくつかの提案がありますが、これは多くのAPIをクリーンアップできる提案です。たとえば、クラスには、実装を操作するためのCollections静的メソッドがあります。ListそれらはListインターフェースに含まれる可能性があります。


更新:Java Posse Podcast#234で、 Joe D'arcyはこの提案について簡単に言及し、「複雑」であり、おそらくProjectCoinの下では実現しないだろうと述べました。


更新: Java7用のProjectCoinには組み込まれていませんが、Java8はインターフェイスで静的関数をサポートしています。

于 2009-03-14T18:20:17.090 に答える
40

この場合の一貫性の欠如は、設計や必要性ではなく利便性の問題であるという私の得意な理論を使用します。 .

静的フィールドが存在するのは、(a) JDK 1.0 に存在し、JDK 1.0 で多くの危険な決定が行われたためであり、(b) インターフェイスの static final フィールドは、当時の Java が定数に最も近いものでした。

インターフェイスの静的な内部クラスは、純粋な構文糖衣であるため許可されていました。内部クラスは、実際には親クラスとは何の関係もありません。

そのため、やむを得ない理由がないという理由だけで、静的メソッドは許可されません。一貫性は、現状を変えるほど説得力がありません。

もちろん、これは将来の JLS バージョンでは何も壊すことなく許可される可能性があります。

于 2008-09-25T20:11:09.650 に答える
15

インターフェイスで静的メソッドを宣言する意味はありません。通常の呼び出し MyInterface.staticMethod() では実行できません。(編集: 最後の文が一部の人々を混乱させたため、MyClass.staticMethod() を呼び出すと、MyClass で staticMethod の実装が正確に実行されます。MyClass がインターフェイスである場合、これは存在できません!) 実装クラス MyImplementor.staticMethod() を指定してそれらを呼び出す場合次に、実際のクラスを知っている必要があるため、インターフェイスにそれが含まれているかどうかは関係ありません。

さらに重要なことに、静的メソッドは決してオーバーライドされません。

MyInterface var = new MyImplementingClass();
var.staticMethod();

static の規則では、var の宣言された型で定義されたメソッドを実行する必要があるとされています。これはインターフェイスなので、これは不可能です。

もちろん、静的キーワードはいつでもメソッドから削除できます。すべてがうまくいきます。インスタンス メソッドから呼び出された場合、いくつかの警告を抑制する必要がある場合があります。

以下のコメントのいくつかに答えるために、「result=MyInterface.staticMethod()」を実行できない理由は、MyInterface で定義されたメソッドのバージョンを実行する必要があるためです。ただし、MyInterface はインターフェイスであるため、バージョンを定義することはできません。定義上、コードはありません。

于 2008-09-24T20:58:35.287 に答える
6

インターフェイスの目的は、実装を提供せずにコントラクトを定義することです。したがって、静的メソッドをオーバーライドすることはできないため、静的メソッドをインターフェイスに既に実装する必要があるため、静的メソッドを使用することはできません。フィールドに関してfinal fieldsは、基本的に定数である static のみが許可されます (1.5 以降では、インターフェイスに列挙型を含めることもできます)。定数は、マジック ナンバーなしでインターフェイスを定義するのに役立ちます。

static finalところで、静的な最終フィールドのみが許可されるため、インターフェイスのフィールドの修飾子を明示的に指定する必要はありません。

于 2008-09-24T21:31:43.863 に答える
3

Java 5より前は、静的フィールドの一般的な使用法は次のとおりでした。

interface HtmlConstants {
    static String OPEN = "<";
    static String SLASH_OPEN = "</";
    static String CLOSE = ">";
    static String SLASH_CLOSE = " />";
    static String HTML = "html";
    static String BODY = "body";
    ...
}

public class HtmlBuilder implements HtmlConstants { // implements ?!?
    public String buildHtml() {
       StringBuffer sb = new StringBuffer();
       sb.append(OPEN).append(HTML).append(CLOSE);
       sb.append(OPEN).append(BODY).append(CLOSE);
       ...
       sb.append(SLASH_OPEN).append(BODY).append(CLOSE);
       sb.append(SLASH_OPEN).append(HTML).append(CLOSE);
       return sb.toString();
    }
}

つまり、HtmlBuilderは各定数を修飾する必要がないため、 HtmlConstants.OPENの代わりにOPENを使用できます。

このように道具を使用することは、最終的に混乱を招きます。

Java 5では、同じ効果を実現するための静的構文のインポートがあります。

private final class HtmlConstants {
    ...
    private HtmlConstants() { /* empty */ }
}

import static HtmlConstants.*;
public class HtmlBuilder { // no longer uses implements
    ...
}
于 2008-09-24T21:12:35.797 に答える
3

インターフェイスに静的メソッドがない本当の理由はありませんが、Java言語の設計者はそのようにしたくありませんでした。技術的な観点から、それらを許可することは理にかなっています。結局のところ、抽象クラスもそれらを持つことができます。インターフェイスに静的メソッドがあり、メソッドを呼び出したり、通常どおりにインターフェイスを使用したりしても問題なく動作するはずのバイトコードを「手作り」できると思いますが、テストはしていません。

于 2011-05-13T12:01:54.940 に答える
3

実際、静的メソッドの恩恵を受けることができる理由が時々あります。これらは、インターフェイスを実装するクラスのファクトリ メソッドとして使用できます。たとえば、今 openjdk に Collection インターフェイスと Collections クラスがあるのはそのためです。したがって、常に回避策があります。静的メソッドの「名前空間」として機能するプライベートコンストラクターを別のクラスに提供します。

于 2008-09-28T19:43:21.740 に答える
2

なぜ静的メソッドなのか、よく疑問に思います。それらには用途がありますが、パッケージ/名前空間レベルのメソッドは、おそらく静的メソッドが使用されるものの 80 をカバーします。

于 2009-03-19T17:02:43.147 に答える
1

2つの主な理由が思い浮かびます。

  1. Javaの静的メソッドはサブクラスでオーバーライドできません。これは、静的フィールドよりもメソッドにとってはるかに大きな問題です。実際には、サブクラスのフィールドをオーバーライドしたくはありませんでしたが、常にメソッドをオーバーライドしています。したがって、静的メソッドがあると、インターフェイスを実装するクラスがそのメソッドの独自の実装を提供できなくなり、インターフェイスを使用する目的が大幅に損なわれます。

  2. インターフェイスにはコードが含まれているとは限りません。それが抽象クラスの目的です。インターフェイスの要点は、すべてに特定のメソッドのセットがある、おそらく無関係なオブジェクトについて話せるようにすることです。これらのメソッドの実装を実際に提供することは、インターフェースが意図されている範囲の外にあります。

于 2008-09-24T19:25:51.030 に答える
1

静的メソッドはクラスに関連付けられています。Java では、インターフェースは技術的にはクラスではなく、型ですが、クラスではありません (したがって、キーワードは実装し、インターフェースはオブジェクトを拡張しません)。インターフェイスはクラスではないため、アタッチする実際のクラスがないため、静的メソッドを持つことはできません。

インターフェイスに対応する Class オブジェクトを取得するために InterfaceName.class を呼び出すことができますが、Class クラスは、Java アプリケーションのクラスとインターフェイスを表すことを明確に示しています。ただし、インターフェイス自体はクラスとして扱われないため、静的メソッドをアタッチすることはできません。

于 2008-10-01T17:30:52.330 に答える
0

インターフェイスで宣言できるのは静的finalフィールドのみです(「public」キーワードを含めなくてもパブリックであるメソッドと同様に、静的フィールドはキーワードの有無にかかわらず「final」です)。

これらは単なる値であり、コンパイル時に使用される場所に文字通りコピーされるため、実行時に静的フィールドを実際に「呼び出す」ことはありません。静的メソッドを持つことは、Javaが許可しない実装なしでインターフェースを呼び出すことを伴うため、同じセマンティクスを持ちません。

于 2008-09-24T19:26:04.493 に答える
0

その理由は、その修飾子を明示的に宣言するかどうかに関係なく、インターフェイスで定義されたすべてのメソッドが抽象であるためです。静的メソッドはオーバーライドできないため、抽象静的メソッドは許可された修飾子の組み合わせではありません。

インターフェイスが静的フィールドを許可する理由について。「機能」と考えるべきだと感じています。私が考えることができる唯一の可能性は、インターフェイスの実装が関心を持つ定数をグループ化することです。

一貫性がより良いアプローチであったことに同意します。インターフェイスでは静的メンバーを許可しないでください。

于 2008-09-30T04:39:23.630 に答える