3

インターフェイスの正しいメソッド シグネチャとは何か、またその理由について質問があります。私のイベントは型でパラメータ化されていますが、インターフェイスにも<T>メソッド署名でそれを使用する必要がありますか? もしそうなら、なぜ、なぜですか?

public interface MyListener {
    void beforeAction(final MyEvent event);
}

public class MyEvent<T> extends EventObject {

    // code
}
4

2 に答える 2

5

MyEventタイプでパラメーター化されている場合は、次のMyListenerいずれかとして指定する必要があります

public interface MyListener<T> {
    void beforeAction(final MyEvent<T> event);
}

またはMyEvents、囲んでいる に固有ではないさまざまなタイプの がある場合は、次のようMyListenerになります。

public interface MyListener {
    <T> void beforeAction(final MyEvent<T> event);
}

または、Thomas が言ったように、T の型を完全に無視することもできます。

public interface MyListener {
    void beforeAction(final MyEvent<?> event);
}

上記のいずれかを実行する必要があります。そうしないと、生の型の使用に関するコンパイラの警告が表示されます。

于 2013-03-26T16:11:08.490 に答える
2

リスナーでのタイプが問題にならない場合は、警告を取り除き、ジェネリックを有効に保つためにT、少なくともメソッドを as として定義する必要があります。void beforeAction(final MyEvent<?> event);型がない場合、コンパイラはそのメソッドのすべての型チェックを無効にします。

さまざまなタイプのイベントにさまざまなリスナーが必要な場合は、TAndrew が既に指摘したように、インターフェイスにも追加する必要があります。

このようにして、手動キャスト (したがってバグ) を必要とせずに、いくつかのリスナー実装を作成できます。たとえば、次のようになります。

public class StringListener implements MyListener<String> {
   void beforeAction(final MyEvent<String> event) {
     ...
   }
}

public class NumberListener implements MyListener<Number> {
   void beforeAction(final MyEvent<Number> event) {
     ...
   }
}

このような実装がある場合はT、型情報がリフレクション データに格納されるため、実行時に の値をクエリすることもできます。

これは、匿名クラスまたはローカル変数には当てはまらないことに注意してください。これらの場合、型の消去が行われます。

于 2013-03-26T16:17:22.017 に答える