2

私は現在、いくつかの古いコードのリファクタリングに取り組んでおり、Swing Application Framework クラスの Generics を適切に使用する方法を理解していないスニペットを見つけましたTaskListener.Adapter

これは関連するコード スニペットです。

public void executeTask(Task<?, ?> task, boolean handleException) {
    task.addTaskListener(new TaskListener.Adapter() { /* <-- Two warnings here */
        @Override
        public void failed(TaskEvent event) { /* ... */ }
    });
    getContext().getTaskService().execute(task);
}

1. まず、警告を取り除きたい。「チェックされていない変換」「生の型が見つかりました」。コードを に変更しようとしましたが、 「特定の型には適用できません」new TaskListener.Adapter<Object, Object>というエラーが表示されます。宣言のため、ここで使用できるのは生の型だけですか?(Task<?, ?>

failed2. のメソッドの宣言はorg.jdesktop.application.TaskListener.Adapterですpublic void failed(TaskEvent<Throwable> event)が、コードを次のように変更しようとすると:

@Override
public void failed(TaskEvent<Throwable> event) { /* ... */ }

「メソッドはスーパータイプのメソッドをオーバーライドしません」というメッセージが表示されます。ここでも raw を使用する必要がありTaskEventます。何故ですか?

ご協力ありがとうございました。

編集: Jarvana のTaskListenerの Javadoc 。

4

3 に答える 3

2

ワイルドカードが何であるかを誰が知っているので<Object, Object>、一般化されたアダプターを適用することはできませんか? Task<?, ?>そのTask<String, Integer>場合、アダプターの境界が一致しないため、適用できない可能性があります。

(まあ、この場合、それらは消費者であるため問題ないかもしれませんが、コンパイラはそれ自体でそれを推測することはできません。この場合、コンパイラを満足させるためにTask.addTaskListenera を取るように宣言する必要がありますTaskListener<? super T, ? super V>.)

の宣言方法のためaddTaskListener、まったく同じ汎用境界を持つリスナーを渡す必要があります。後でそれらを参照する方法がないため、ワイルドカードとして宣言する場合、これは不可能です。代わりに行う必要があるのは、メソッドをジェネリックにすることです。これは、?ワイルドカードを使用するのと似ていますが、後でメソッドで参照できるように名前を付けている点が異なります。

public <T, V> void executeTask(Task<T, V> task, boolean handleException) {
    task.addTaskListener(new TaskListener.Adapter<T, V>() {
        @Override
        public void failed(TaskEvent event) { /* ... */ }
    });
    getContext().getTaskService().execute(task);
}

2番目の部分については、私にはわかりません-私にも問題ないようです。おそらく、これは未加工の型に起因する誤解を招くエラーですが、どちらのジェネリック パラメーターも宣言にまったく関与していないため、その可能性は低いと思われます。上記の変更後もコンパイラがオーバーライドを気に入らない場合は、おそらく別の場所に問題がある可能性があります (間違ったクラスのスコープに誤ってメソッドを配置したなど)。

于 2011-08-11T08:39:37.540 に答える
1
  1. 試しましたnew TaskListener.Adapter<?, ?>か?

  2. <Throwable>型パラメーターを追加しようとしたときnew TaskListener.Adapter、生の型として作成されましたか、それともジェネリック型パラメーターがありましたか?

    最初のケースでは、コンパイラはクラス全体(およびそのスーパークラスも) を生の型として扱います (後方互換性のため)。つまり、クラス固有であるかメソッド固有であるかに関係なく、クラス内のすべてのジェネリック型パラメーターは省略されます。そのため、ジェネリック パラメーターを持つメソッド宣言が見つかると、生のパラメーターを持つスーパークラス メソッドと比較されます。したがって、一致しません。

于 2011-08-11T08:34:17.837 に答える
1

ライブラリとソースコードがわからないので、私の推測は次のとおりです。

public <K, V> void executeTask(final Task<K, V> task, boolean handleException) {
    task.addTaskListener(new TaskListener.Adapter<K, V>() {
        @Override
        public void failed(final TaskEvent<Throwable> event) {
            super.failed(event);
        }
    });
    getContext().getTaskService().execute(task);
}

(編集:libをダウンロードしましたが、上記のコードは警告なしでコンパイルされます)

于 2011-08-11T08:39:13.870 に答える