インターフェース変数がデフォルトで静的で最終的なのはなぜですか?


274

インターフェース変数がデフォルトでJavaの静的で最終的なのはなぜですか?


41
インターフェイス内に変数を配置しないでください。
cherouvim

34
インターフェイスは、さまざまな方法で実装できるコントラクトを定義するためです。変数の値は実装です。
cherouvim

10
インターフェイスを実装するすべてのクラスに定数変数(たとえば、フィールド名)があることがわかっている場合は、確かにそれを行うことができます。
Aniket Thakur 2013

クラス内の変数を、クラスが実装するインターフェースのインスタンスにするのは良い考えですか?これは以前聞いたことがあります。
Doug Hauf、2014年

Javaのインターフェースは、ACIDの原則に従います。Cでの正規化により最終的になります。@ cherouvim変数のタイプは実装であり、変数は値の有無にかかわらず宣言する必要があり、変数の定義は値です。変数の値を変更すると、再実装されない場合、その再定義になります。
グリム

回答:


264

Philip ShawによるJavaインターフェース設計FAQから:

Javaインターフェースはそれ自体ではインスタンス化できないため、インターフェース変数は静的です。変数の値は、インスタンスが存在しない静的コンテキストで割り当てる必要があります。最後の修飾子は、インターフェイス変数に割り当てられた値が、プログラムコードによって再割り当てできない真の定数であることを保証します。

ソース


39
抽象クラスも「それ自体」ではインスタンス化できず、インスタンス変数を持つこともできないことに注意してください。
macias

18
static修飾子のこの説明は完全に偽です。クラスのパブリックインスタンス変数はそのインターフェースの一部であり、interfaceインスタンスメソッドのようにJava で抽象化されるべきではない理由はありません。Java interfaceを直接インスタンス化できないことは問題ではありません。それでも、を実装するクラスのインスタンスを持つことができinterface、特定のパブリックインスタンス変数があることを要求するのが賢明です。についての部分に関してはfinal、それはまったく説明を提供しません-それは何がfinal意味するのかを説明するだけです。
火砕物

3
上記の引用は、状況に応じて優れています。それが与える理由は、「インターフェース変数はJava定数であることを意図している」ということです。引用は、そのような定数がなぜ静的で最終的なものになるのかを詳しく説明したものです。それは真実ですが、実際の問題は、実際のインターフェースの一部として変数が許可されない理由です(つまり、実装クラスで発生する必要がある非プライベートメンバーの名前と型を指定すること)。特別な「インターフェース定数」が必要な場合は、新しい構文を使用するか、インターフェースで実際に定義されている変数がインターフェース定数であると判断した可能性があります。
火星破壊

6
状態の問題の多重継承を回避するために、インターフェイスにインスタンス変数を含めることはできません。docs.oracle.com/javase/tutorial/java/IandI/…を参照してください。同じ理由により、クラスは複数のクラスを拡張できません。
denis 2017

1
デフォルトのメソッドはどのように導入され、インスタンスはありますが、インスタンス変数はサポートされていません...
M.kazem Akhgary 2018年

41

インターフェースには直接オブジェクトがないため、クラス/インターフェースを使用する方法しかありません。そのため、インターフェース変数が存在する場合は静的でなければならず、それ以外の場合は外部からまったくアクセスできません。これは静的なので、1つの値しか保持できず、それを実装するクラスはそれを変更できるため、すべて混乱します。

したがって、インターフェース変数があったとしても、それは暗黙的に静的で、最終的なものであり、明らかにパブリックです!!!


もちろん、インスタンス変数は、Javaで許可されていればアクセスできますinterface。クラスはインターフェースを実装し、インスタンス変数を宣言します(インターフェースの必要に応じて)。そのコンストラクター(または他のメソッド)がインスタンス変数を設定します。クラスのインスタンスがインスタンス化されると、そのインスタンス変数にアクセスできるようになります。
火星破壊

Javaでは、ボディを持つ静的メソッドをインターフェイスに存在させることができます。それらは静的変数にアクセスできます。それらは単にそれらを変更することはできません。つまり、静的関数はデータを格納できません
simpleuser

36

public:インターフェースに存在するメソッドと同様に、すべてのクラスにわたるアクセシビリティのため

static:インターフェースはオブジェクトを持つことができないため、interfaceName.variableNameを使用してそれを参照したり、それを実装するクラスのvariableNameを直接使用したりできます。

final:それらを定数にする。2つのクラスが同じインターフェースを実装し、両方に値を変更する権利を与えると、varの現在の値で競合が発生するため、初期化は1回しか許可されません。

また、これらの修飾子はすべてインターフェースに対して暗黙的であり、実際にそれらを指定する必要はありません。


15

これは哲学的な答えではなく、実際的な答えです)。static修飾子の要件は明白であり、他の人から回答されています。基本的に、インターフェースはインスタンス化できないため、そのフィールドにアクセスする唯一の方法は、それらをクラスフィールドにすることです-static

interfaceフィールドが自動的にfinal(定数)になる理由は、別の実装が誤って他の実装の動作に影響を与える可能性があるインターフェース変数の値を変更するのを防ぐためです。interfaceプロパティがfinalJavaによって明示的になされなかった以下のシナリオを想像してください。

public interface Actionable {
    public static boolean isActionable = false;

    public void performAction();
}

public NuclearAction implements Actionable {

    public void performAction() {
        // Code that depends on isActionable variable
        if (isActionable) {
            // Launch nuclear weapon!!!
        }
    }
}

ここで、実装Actionableする別のクラスがインターフェース変数の状態を変更するとどうなるか考えてみてください。

public CleanAction implements Actionable  {

    public void performAction() {
        // Code that can alter isActionable state since it is not constant
        isActionable = true;
    }
}

これらのクラスがクラスローダーによって単一のJVM内にロードされている場合、の呼び出しは、NuclearAction別のクラスによって影響を受ける可能性があります。CleanActionperformAction()CleanAction実行(同じスレッドで)可能性があります。 (意味的にはそうです)。

の各実装がinterfaceこれらの変数をどのように使用するかはわからないため、暗黙的にでなければなりませんfinal


9

他のものは実装の一部であり、インターフェースは実装を含むことができないからです。


1
次に、最終的な理由は何ですか。
Jothi

7
その定数であることを示します。Javaにはconstキーワードがありません。static finalは、定数を宣言する方法です。
Amir Afghani 2010年

5
Java 8以降は実装を含めることができますが、バックワートの互換性が必要ない場合は使用しないことを強くお勧めします。:)
codepleb

6
public interface A{
    int x=65;
}
public interface B{
    int x=66;
}
public class D implements A,B {
    public static void main(String[] a){
        System.out.println(x); // which x?
    }
}

これが解決策です。

System.out.println(A.x); // done

それが、インターフェース変数が静的である理由の1つだと思います。

インターフェイス内で変数を宣言しないでください。


3
実際には、指定のない「アックス」、実際にインタフェースで(暗黙のうち最終のpublic staticです)変数を使用しても安全であるので、それも、「コンパイルされないでしょう。
マルコ

@Marcoはコンパイルすらできないと言ったので、私は答えに同意しません。今のところ、他の欠点は見つかりませんでした。たぶんstatic final、実際には静的で最終的な変数の前に書かれているのを見たことがないかもしれません。
マイサー

5

static-インターフェイスはインスタンスを持つことができないため。そして最後-変更する必要がないため。


15
「必要ありません」==「許可されていません」、意味を混同しないでください。
peterh-モニカを2016年

3

なぜなら:

Static :インターフェイスのオブジェクトを持つことができないので、オブジェクトレベルのメンバー変数の使用を避け、クラスレベルの変数(つまり静的)を使用する必要があります。

Final :変数の値があいまいにならないようにしてください(ダイヤモンド問題-多重継承)。

そして、ドキュメントのインターフェイスごとに、契約ではなく実装です。

参照:quoraに関するAbhishek Jainの回答


2

Javaでは、インターフェイスで抽象変数やコンストラクター定義を許可していません。解決策:インターフェイスと実装の間に抽象クラスを掛けるだけで、抽象クラスを拡張するだけです。

 public interface IMyClass {

     void methodA();
     String methodB();
     Integer methodC();

 }

 public abstract class myAbstractClass implements IMyClass {
     protected String varA, varB;

     //Constructor
     myAbstractClass(String varA, String varB) {
         this.varA = varA;
         this.varB = VarB;
     }

     //Implement (some) interface methods here or leave them for the concrete class
     protected void methodA() {
         //Do something
     }

     //Add additional methods here which must be implemented in the concrete class
     protected abstract Long methodD();

     //Write some completely new methods which can be used by all subclasses
     protected Float methodE() {
         return 42.0;
     }

 }

 public class myConcreteClass extends myAbstractClass {

     //Constructor must now be implemented!
     myClass(String varA, String varB) {
         super(varA, varB);
     }

     //All non-private variables from the abstract class are available here
     //All methods not implemented in the abstract class must be implemented here

 }

後で他のインターフェイスと一緒に実装したくない場合は、インターフェイスなしの抽象クラス使用することもできます。抽象クラスのインスタンスを作成することはできません。最初に拡張する必要があります。

(「保護された」キーワードは、拡張クラスだけがこれらのメソッドと変数にアクセスできることを意味します。)

スパイロ


1

インターフェースは、不変の2つのパーティ間の契約であり、石に刻まれているため、最終的なものです。契約による設計を参照してください。


1

インターフェイス:システム要件サービス。

インターフェイスでは、変数はデフォルトでpublic、static、finalアクセス修飾子によって割り当てられます。なぜなら:

public:インターフェースが他のパッケージに配置される場合があります。したがって、プロジェクトのどこからでも変数にアクセスする必要があります。

static:そのような不完全なクラスはオブジェクトを作成できません。プロジェクトでは、オブジェクトなしで変数にアクセスする必要があるので、interface_filename.variable_name

final: 1つのインターフェースが多くのクラスによって実装されており、すべてのクラスがインターフェース変数にアクセスして更新しようとしているとします。そのため、データの変更に一貫性がなくなり、他のすべてのクラスに影響します。したがって、finalでアクセス修飾子を宣言する必要があります。


0

ではJava、インターフェイスではインスタンス変数を宣言できません。インターフェイスで宣言された変数をインスタンス変数として使用すると、コンパイル時エラーが返されます。

static finalインスタンス変数とは異なる定数変数を宣言できます。


これは明らかに間違っています。コンパイラーをプライベートまたは保護しない限り、文句を言うことはありません。内部的には、他の人がすでに述べたように、それらはpublic static finalに変換されます。そして、その理由はかなり明白だと思います。インターフェースは、状態ではなく、動作を指示することを目的としているためです。
Mikayil Abdullayev

0

インターフェイスは任意のクラスで実装でき、その値が実装クラスの1つによって変更された場合、他の実装クラスに誤解を招く可能性があります。インターフェイスは基本的に、2つの相互に関連しているが異なるエンティティを組み合わせるための参照です。そのため、インターフェイスをインスタンス化できないため、インターフェイス内の宣言変数は暗黙的に最終的であり、静的でもあります。


0

インターフェースが定義されていて、他のクラスがそれを実装しているWebアプリケーションを考えてみてください。変数にアクセスするためのインターフェースのインスタンスを作成することはできないため、静的キーワードが必要です。静的なので、値の変更はそれを実装した他のインスタンスに反映されます。それを防ぐために、それらを最終的なものとして定義します。


0

Eclipseで試したところ、インターフェースの変数はデフォルトでfinalになっているため、変更できません。親クラスと比較して、変数は確実に変更可能です。どうして?ちなみに、クラスの変数は子に継承される属性で、実際の必要に応じて変更することができます。逆に、インターフェイスは属性ではなく動作のみを定義します。変数をインターフェースに入れる唯一の理由は、それらをそのインターフェースに関連する定数として使用することです。ただし、次の抜粋によると、これは良い方法ではありません。

「インターフェイスに定数を配置することは、Javaの初期の頃には一般的な手法でしたが、今では多くの人がインターフェイスの不愉快な使い方だと考えています。インターフェイスはデータではなくオブジェクトによって提供されるサービスを処理する必要があるためです。また、使用される定数通常、クラスごとは実装の詳細ですが、インターフェースに配置すると、クラスのパブリックAPIに昇格します。」

私はまた、静的に置くか、まったく差をつけないかを試みました。コードは次のとおりです。

public interface Addable {
    static int count = 6;

    public int add(int i);

}

public class Impl implements Addable {

    @Override
    public int add(int i) {
        return i+count;
    }
}

public class Test {

    public static void main(String... args) {
        Impl impl = new Impl();

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