回答:
上記の例のstaticキーワードは冗長であり(ネストされたインターフェースは自動的に「静的」)、セマンティクスに影響を与えることなく削除できます。削除することをお勧めします。同じことは、インターフェースメソッドの「パブリック」およびインターフェースフィールドの「パブリックファイナル」にも当てはまります。修飾子は冗長であり、ソースコードに混乱を与えるだけです。
どちらの方法でも、開発者は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() {...}
});
質問への回答はありますが、ネストされたインターフェースを使用する1つの理由は、その関数がそれが含まれるクラスに直接関連している場合です。これの良い例はListener
です。クラスがFoo
あり、他のクラスがそのイベントをリッスンできるようにしたい場合は、という名前のインターフェイスを宣言できますがFooListener
、これは問題ありませんが、ネストされたインターフェイスを宣言して、他のクラスに実装させると、より明確になりますFoo.Listener
(ネストされたクラスFoo.Event
はこれと一緒に悪くありません)。
java.util.Map.Entry
(別のインターフェースにネストされたインターフェースです)です。
Map.Entry
)またはクラスをそのパッケージ内に含めることをお勧めします。これは、クラスを短く簡潔にしたいからです。また、リーダーは、パッケージ内のクラスを確認することで、クラスに関連する他のエンティティを確認できます。おそらくjava.collections.map
地図用のパッケージがあるでしょう。これはオブジェクト指向とモジュール性についてです。java.util
それが多すぎます。util
のようなものcommon
-においIMO
java.util
確かに多すぎます。そうは言っても、あなたが提案しているような細かいパッケージに分解するのも理想的だとは思いません。
java.util.MapEntry
独自のパッケージの外部で呼び出すとします。最初の反射:このクラスに関連するインターフェースは何ですか?私はクラスを調べます。javadocがこのインターフェースにリンクしていない限り、私はそれらの関係の手がかりを知りません。さらに、人々はインポートパッケージを見ません。誰もが自分の意見を持っています。だれも正しくない、だれも間違っていない
メンバーインターフェイスは暗黙的に静的です。例の静的修飾子は、コードのセマンティクスを変更せずに削除できます。Java言語仕様8.5.1も参照してください。静的メンバー型宣言
内部インターフェイスにアクセスするには、静的である必要があります。インターフェースはクラスのインスタンスに関連付けられていませんが、クラス自体に関連付けられてFoo.Bar
いるため、次のようにでアクセスされます。
public class Baz implements Foo.Bar {
...
}
ほとんどの点で、これは静的内部クラスと同じです。
The interface isn't associated with instances of the class, but with the class itself
さらに意味を説明できますか、理解できませんでした
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;
}
}
Zoo
はインターフェースを実装していないAC
ため、のインスタンスを期待するZoo
コンストラクターに渡すことはできません。実際に両方を拡張し、そして、クラスが実装することを意味するものではありませんし、実装も魔法のように。DoSomethingAlready
AC
AC
A
C
A
C
AC
通常、静的内部クラスが表示されます。静的内部クラスは、非静的クラスが参照できる包含クラスを参照できません。あなたがいくつかのパッケージの衝突に遭遇していない限り(Fooと同じパッケージにBarと呼ばれるインターフェースがすでにあります)、私はそれをそれ自身のファイルにすると思います。また、FooとBarの間の論理的な接続を強制する設計上の決定となる場合もあります。おそらく、作成者はBarをFooでのみ使用することを意図していました(ただし、静的内部インターフェースはこれを強制せず、論理接続のみです)。
クラスFooをインターフェースFooに変更する場合、上記の例の「public」キーワードも冗長になります。
別のインターフェース内で定義されたインターフェースは、暗黙的にpublic staticになります。
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では実現しませんでした。したがって、他のすべての答えは正しいです。静的および非静的な入れ子になったインターフェイスに違いはありません。
Javaでは、静的インターフェース/クラスにより、インターフェース/クラスをトップレベルのクラスのように使用できます。つまり、他のクラスで宣言できます。したがって、次のことができます。
class Bob
{
void FuncA ()
{
Foo.Bar foobar;
}
}
staticがない場合、上記はコンパイルに失敗します。これの利点は、インターフェイスを宣言するためだけに新しいソースファイルを必要としないことです。また、Foo.Barを記述する必要があるため、インターフェイスBarをクラスFooに視覚的に関連付け、FooクラスがFoo.Barのインスタンスで何かを行うことを意味します。
静的とは、パッケージ(プロジェクト)のクラス部分がポインタを使用せずにアクセスできることを意味します。これは状況に応じて役立ちます。
「静的」メソッドの便利な例は、Mathクラスです。Mathのすべてのメソッドは静的です。つまり、邪魔にならないで新しいインスタンスを作成し、変数を宣言してさらに多くの変数に格納する必要がなく、データを入力して結果を取得するだけで済みます。
Staticは常に便利であるとは限りません。たとえば、大文字と小文字を比較する場合は、いくつかの方法でデータを保存することができます。同じシグネチャを持つ3つの静的メソッドを作成することはできません。静的でない3つのインスタンスが必要です。静的な場合は、データが入力とともに変化しないため、比較して比較できます。
静的メソッドは、1回限りのリターンと迅速な計算または簡単に取得できるデータに適しています。