インターフェースのすべてのフィールドが暗黙的に静的で最終的なのはなぜですか?


100

インターフェイスで定義されているすべてのフィールドが暗黙的である理由を理解しようstaticとしていfinalます。フィールドを保持staticするという考えは、インターフェイスのオブジェクトを保持できないので私には理にかなっていますが、なぜそれがfinal(暗黙的に)あるのでしょうか。

Javaの設計者がインタフェースのフィールドを作るといった理由いずれかが知っているstaticfinal


私自身への注意:インターフェイスのフィールドはそれを実装するオブジェクトの一部にはならないので、静的です。

回答:


126

実装の詳細ではなく、相互作用コントラクトのみを指定することを目的としているため、インターフェイスに動作や状態を含めることはできません。「動作なし」は、メソッド/コンストラクター本体または静的/インスタンス初期化ブロックを許可しないことによって強制されます。静的な最終フィールドのみを許可することにより、「状態なし」が強制されます。したがって、クラスは状態(静的状態)を持つことができますが、インスタンスの状態はインターフェースによって推測されません。

ところで、Javaの定数は静的な最終フィールドによって定義されます(慣例により、名前にはUPPER_CASE_AND_UNDERSCORESが使用されます)。


54
最終フィールドが定数であるとは限りません。これはプリミティブ型に対してのみ保証されています。一般に、最後のキーワードは単にメモリの場所が変更されないことを意味します。
ポップ

8
最終フィールドが定数であるとは言いませんでしたが、定数は最終フィールドです。非プリミティブな静的最終フィールドをインターフェースに置くことが許可されていることに注意してください。そのフィールドの内容は変更される可能性がありますが、その参照は一定です。
Adriaan Koster

1
@AdriaanKoster最終的なフィールドは定数であると正確に述べました。定数を許可するだけでは、どの状態も強制されません。-この文は、すべての最終フィールドが一定であることを意味します。使用した単語についてさらに議論しようとするかもしれませんが、明らかにあなたの発言は誤解を招く恐れがあります。
トマーシュZato -復活モニカ

2
それは私の衰えた知性であるに違いありませんが、たまたま私の得点の高い答えであるこの答えを6年間見てみても、私はまだ発言を理解していません。私は何も間違って見ることができないので、別の表現を提案してください。
Adriaan Koster、2015年

Javaデザイナーはインターフェイスをステートレスにすることを意図していた可能性がありますが、インスタンスフィールドは変更可能なクラスになる可能性があるため、失敗しました。彼らは失敗したことを認める代わりに、インスタンスフィールドをに強制することを選択しますstatic final。これはconst、Javaで取得できるのと同じくらい実数(実数はC / C ++)に近いです。残念ながら、これは暗黙的であり、非専門家にとって混乱を招く可能性があります。(static意図しない動作を観察したことが原因であることに気づきました。これらはfinalこの回答からのみであることを学びました。)
not-a-user

27

存在する理由 final

finalとして定義されていない場合、実装はフィールドの値を変更できます。その後、それらは実装の一部になります。インターフェースは、実装のない純粋な仕様です。

存在する理由 static

それらが静的である場合、それらはオブジェクトではなく、オブジェクトの実行時タイプではなく、インターフェースに属します。


18

ここにはいくつかのポイントがあります。

インターフェースのフィールドが暗黙的にstatic finalであるからといって、それらがコンパイル時の定数または不変である必要があることを意味するだけではありません。たとえば、次のように定義できます。

interface I {
  String TOKEN = SomeOtherClass.heavyComputation();
  JButton BAD_IDEA = new JButton("hello");
}

(アノテーション定義内でこれを行うと、上記が実際に静的初期化子にコンパイルされるという事実に関連して、javac混乱させる可能性があることに注意してください。)

また、この制限の理由は、技術的なものよりも文体的なものであり、多くの人々はそれが緩和されることを望んでいます


9

フィールドは(メソッドのように)抽象化できないため、静的でなければなりません。それらは抽象的ではないので、実装者はフィールドの異なる実装を論理的に提供することができません。

フィールドは最終的なものでなければならない、と私は思います。フィールドは多くの異なる実装者によってアクセスされる可能性があるので、それらを変更可能にすることは(同期として)問題になるかもしれません。また、再実装(非表示)されるのを防ぐためにも。

ちょうど私の考え。


NawMan、「フィールドは静的でなければならない...」についてのあなたの説明はあまり意味がありません。しかし、あなたは「フィールドは最終でなければならない」という非常に正しかった
ピーク2009年

1
フィールドが最終でなければならない理由について、彼は正しくないと思います。別の実装者がフィールドを変更できるようにしても問題はありません。そうしないと継承が問題になるからです。Adriaanが言ったように、インターフェースはステートレスであり、ステートレスである必要があるため、フィールドはfinalでなければなりません。状態を持つインターフェースは、基本的に抽象クラスでなければなりません。
Axelle Ziegler、

あなたが持っている場合public staticではないフィールドをfinal、FindBugsのは(当然!)文句を言うでしょう。
トムホーティン-2009年

2

フィールドが最終的なものであるという要件は、Java言語設計者による過度の制限と誤りであると考えています。インターフェースタイプのオブジェクトで操作を実行するために必要な実装で定数を設定する必要がある場合(ツリー処理など)があります。実装クラスでコードパスを選択するのは簡単ではありません。私が使用する回避策は、インターフェイス関数を定義し、リテラルを返すことによってそれを実装することです:

public interface iMine {
    String __ImplementationConstant();
    ...
}

public class AClass implements iMine {
    public String __ImplementationConstant(){
        return "AClass value for the Implementation Constant";
    }
    ...
}

public class BClass implements iMine {
    public String __ImplementationConstant(){
        return "BClass value for the Implementation Constant";
    }
    ...
}

ただし、次の構文を使用するほうが簡単で明確で、異常な実装が発生しにくくなります。

public interface iMine {
    String __ImplementationConstant;
    ...
}

public class AClass implements iMine {
    public static String __ImplementationConstant =
        "AClass value for the Implementation Constant";
    ...
}

public class BClass implements iMine {
    public static String __ImplementationConstant =
        "BClass value for the Implementation Constant";
    ...
}

フィールドがfinalであるよりもstaticであることに不満を持っているようです。
Daniel Yankowsky 14年

0

仕様、契約...フィールドアクセスの機械命令は、オブジェクトアドレスとフィールドオフセットを使用します。クラスは多くのインターフェースを実装できるため、このインターフェースを拡張するすべてのクラスで、非finalインターフェースフィールドに同じオフセットを設定する方法はありません。したがって、フィールドアクセスの別のメカニズムを実装する必要があります。1つではなく2つのメモリアクセス(フィールドオフセットの取得、フィールド値の取得)に加えて、一種の仮想フィールドテーブル(仮想メソッドテーブルのアナログ)を維持します。既存のもの(メソッド)を介して簡単にシミュレートできる機能のためにjvmを複雑にしたくなかったと思います。

内部的には(メソッドとして)上で説明したように実装されていますが、scalaではインターフェースにフィールドを含めることができます。


-1

static

staticJavaにあるもの(変数またはメソッド)は、またはとしてClassname.variablenameClassname.methodnameまたは直接呼び出すことができます。オブジェクト名のみを使用して呼び出す必要はありません。

インターフェースでは、オブジェクトを宣言staticすることはできず、オブジェクト名を必要とせずにクラス名だけで変数を呼び出すことができます。

final

変数はそのサブクラスでオーバーライドできないため、変数の定数値を維持するのに役立ちます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.