240

コードベースで静的なネストされたインターフェースを見つけました。

class Foo {
    public static interface Bar {
        /* snip */
    }
    /* snip */
}

これは今まで見たことがありません。元の開発者は手の届かないところにあります。したがって、私はSOに尋ねなければなりません:

静的インターフェイスの背後にあるセマンティクスは何ですか? ? を削除すると、何が変わりstaticますか? なぜ誰かがこれをするのでしょうか?

4

11 に答える 11

303

上記の例の static キーワードは冗長であり (ネストされたインターフェイスは自動的に "静的" になります)、セマンティクスに影響を与えずに削除できます。削除することをお勧めします。同じことがインターフェイス メソッドの "public" とインターフェイス フィールドの "public final" にも当てはまります。修飾子は冗長で、ソース コードが煩雑になるだけです。

いずれにせよ、開発者は Foo.Bar という名前のインターフェイスを宣言しているだけです。Foo にアクセスできないコードは Foo.Bar にもアクセスできないことを除いて、囲んでいるクラスとのそれ以上の関連付けはありません。(ソース コードから - Foo がパッケージ プライベートであっても、バイトコードまたはリフレクションは Foo.Bar にアクセスできます!)

新しいトップレベルの名前を作成しないように、外側のクラスからのみ使用されることが予想される場合は、この方法でネストされたインターフェイスを作成するスタイルは許容されます。例えば:

public class Foo {
    public interface Bar {
        void callback();
    }
    public static void registerCallback(Bar bar) {...}
}
// ...elsewhere...
Foo.registerCallback(new Foo.Bar() {
    public void callback() {...}
});
于 2008-09-16T16:46:07.700 に答える
76

質問には答えられましたが、ネストされたインターフェイスを使用する正当な理由の 1 つは、その関数がそれが含まれるクラスに直接関連している場合です。この良い例はListener. クラスがFooあり、他のクラスがそのクラスのイベントをリッスンできるようにしたい場合は、 という名前のインターフェイスを宣言できますがFooListener、これは問題ありませんが、ネストされたインターフェイスを宣言し、それらの他のクラスを実装する方がおそらくより明確ですFoo.Listener(ネストされたクラスFoo.Eventはこれと一緒に悪くありません)。

于 2008-10-16T15:53:35.483 に答える
14

メンバー インターフェイスは暗黙的に静的です。コードのセマンティクスを変更せずに、例の static 修飾子を削除できます。Java 言語仕様8.5.1 も参照してください。静的メンバー型の宣言

于 2008-09-17T09:51:15.333 に答える
9

内部インターフェースは、アクセスできるように静的でなければなりません。インターフェイスはクラスのインスタンスに関連付けられているのではなく、クラス自体に関連付けられているFoo.Barため、次のように でアクセスできます。

public class Baz implements Foo.Bar {
   ...
}

ほとんどの点で、これは静的内部クラスと変わりません。

于 2008-09-16T12:20:51.067 に答える
6

Jesse の答えは近いですが、内部インターフェイスが役立つ理由を示すためのより良いコードがあると思います。読み進める前に、以下のコードを見てください。内部インターフェースが役立つ理由がわかりますか? 答えは、クラス DoSomethingAlready は、A と C を実装する任意のクラスでインスタンス化できるということです。具象クラス Zoo だけではありません。もちろん、これは AC が内部でない場合でも実現できますが、長い名前 (A と C だけでなく) を連結し、他の組み合わせ (たとえば、A と B、C と B など) に対してこれを行うことを想像してみてください。物事がどのように制御不能になるかを見てください。言うまでもなく、ソース ツリーをレビューする人は、1 つのクラスでのみ意味のあるインターフェイスに圧倒されます。要約すると、内部インターフェイスにより、カスタム タイプの構築が可能になり、カプセル化が改善されます

class ConcreteA implements A {
 :
}

class ConcreteB implements B {
 :
}

class ConcreteC implements C {
 :
}

class Zoo implements A, C {
 :
}

class DoSomethingAlready {
  interface AC extends A, C { }

  private final AC ac;

  DoSomethingAlready(AC ac) {
    this.ac = ac;
  }
}
于 2013-01-16T08:23:48.067 に答える
3

あなたの質問に直接答えるには、Map.Entry を見てください。

Map.Entry

これも役に立つかもしれません

Static Nested Inerfaces ブログエントリ

于 2008-09-16T12:21:31.907 に答える
0

通常、静的内部クラスが表示されます。非静的クラスは可能ですが、静的内部クラスはそれを含むクラスを参照できません。パッケージの競合が発生していない限り (Foo と同じパッケージに Bar というインターフェイスが既に存在します)、それを独自のファイルにすると思います。Foo と Bar の間の論理的な接続を強制することは、設計上の決定である場合もあります。おそらく、作成者は Bar を Foo でのみ使用することを意図していたのでしょう (ただし、静的な内部インターフェイスはこれを強制せず、単なる論理接続です)。

于 2008-09-16T12:23:20.110 に答える
0

1998 年、Philip Wadler は、静的インターフェースと非静的インターフェースの違いを提案しました。

私が見る限り、インターフェイスを非静的にすることの唯一の違いは、非静的内部クラスを含めることができるようになったことです。そのため、この変更によって既存の Java プログラムが無効になることはありません。

たとえば、彼は「表現の問題」に対する解決策を提案しました。これは、一方では「あなたの言語はどれだけ表現できるか」という表現と、他方では「あなたの言語で表現しようとしている用語」としての表現との不一致です。 .

ネストされた静的インターフェイスと非静的インターフェイスの違いの例は、彼のサンプル コードで確認できます。

// This code does NOT compile
class LangF<This extends LangF<This>> {
    interface Visitor<R> {
        public R forNum(int n);
    }

    interface Exp {
        // since Exp is non-static, it can refer to the type bound to This
        public <R> R visit(This.Visitor<R> v);
    }
}

彼の提案は、Java 1.5.0 では実現しませんでした。したがって、他のすべての答えは正しいです。静的および非静的のネストされたインターフェースに違いはありません。

于 2015-08-11T21:45:38.730 に答える
-1

Java では、静的インターフェース/クラスにより、インターフェース/クラスを最上位クラスのように使用できます。つまり、他のクラスで宣言できます。したがって、次のことができます。

class Bob
{
  void FuncA ()
  {
    Foo.Bar foobar;
  }
}

static がないと、上記はコンパイルに失敗します。これの利点は、インターフェイスを宣言するためだけに新しいソース ファイルが必要ないことです。また、Foo.Bar を記述する必要があり、Foo クラスが Foo.Bar のインスタンスで何かを行うことを意味するため、インターフェース Bar をクラス Foo に視覚的に関連付けます。

Java のクラス型の説明

于 2008-09-16T12:28:00.253 に答える
-6

静的とは、パッケージ (プロジェクト) の任意のクラス部分がポインターを使用せずにアクセスできることを意味します。これは、状況に応じて便利にも邪魔にもなります。

「静的」メソッドの有用性の完璧な例は、Math クラスです。Math のすべてのメソッドは静的です。これは、わざわざ新しいインスタンスを作成したり、変数を宣言したり、さらに多くの変数に格納したりする必要がなく、データを入力するだけで結果を取得できることを意味します。

静的は必ずしも有用ではありません。たとえば、大文字と小文字の比較を行う場合、いくつかの異なる方法でデータを保存したい場合があります。同一のシグネチャを持つ 3 つの静的メソッドを作成することはできません。非静的の 3 つの異なるインスタンスが必要です。その後、比較することができます。静的な場合、データは入力と共に変化しません。

静的メソッドは、1 回限りのリターンと迅速な計算、または簡単に取得できるデータに適しています。

于 2008-09-16T12:26:41.083 に答える