回答:
実装の詳細ではなく、相互作用コントラクトのみを指定することを目的としているため、インターフェイスに動作や状態を含めることはできません。「動作なし」は、メソッド/コンストラクター本体または静的/インスタンス初期化ブロックを許可しないことによって強制されます。静的な最終フィールドのみを許可することにより、「状態なし」が強制されます。したがって、クラスは状態(静的状態)を持つことができますが、インスタンスの状態はインターフェースによって推測されません。
ところで、Javaの定数は静的な最終フィールドによって定義されます(慣例により、名前にはUPPER_CASE_AND_UNDERSCORESが使用されます)。
static final
。これはconst
、Javaで取得できるのと同じくらい実数(実数はC / C ++)に近いです。残念ながら、これは暗黙的であり、非専門家にとって混乱を招く可能性があります。(static
意図しない動作を観察したことが原因であることに気づきました。これらはfinal
この回答からのみであることを学びました。)
存在する理由 final
finalとして定義されていない場合、実装はフィールドの値を変更できます。その後、それらは実装の一部になります。インターフェースは、実装のない純粋な仕様です。
存在する理由 static
それらが静的である場合、それらはオブジェクトではなく、オブジェクトの実行時タイプではなく、インターフェースに属します。
ここにはいくつかのポイントがあります。
インターフェースのフィールドが暗黙的にstatic finalであるからといって、それらがコンパイル時の定数または不変である必要があることを意味するだけではありません。たとえば、次のように定義できます。
interface I { String TOKEN = SomeOtherClass.heavyComputation(); JButton BAD_IDEA = new JButton("hello"); }
(アノテーション定義内でこれを行うと、上記が実際に静的初期化子にコンパイルされるという事実に関連して、javacを混乱させる可能性があることに注意してください。)
また、この制限の理由は、技術的なものよりも文体的なものであり、多くの人々はそれが緩和されることを望んでいます。
フィールドは(メソッドのように)抽象化できないため、静的でなければなりません。それらは抽象的ではないので、実装者はフィールドの異なる実装を論理的に提供することができません。
フィールドは最終的なものでなければならない、と私は思います。フィールドは多くの異なる実装者によってアクセスされる可能性があるので、それらを変更可能にすることは(同期として)問題になるかもしれません。また、再実装(非表示)されるのを防ぐためにも。
ちょうど私の考え。
public static
ではないフィールドをfinal
、FindBugsのは(当然!)文句を言うでしょう。
フィールドが最終的なものであるという要件は、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インターフェースフィールドに同じオフセットを設定する方法はありません。したがって、フィールドアクセスの別のメカニズムを実装する必要があります。1つではなく2つのメモリアクセス(フィールドオフセットの取得、フィールド値の取得)に加えて、一種の仮想フィールドテーブル(仮想メソッドテーブルのアナログ)を維持します。既存のもの(メソッド)を介して簡単にシミュレートできる機能のためにjvmを複雑にしたくなかったと思います。
内部的には(メソッドとして)上で説明したように実装されていますが、scalaではインターフェースにフィールドを含めることができます。