2

ジェネリックメソッドのチュートリアルには、次の便利な例があります。

 public <T extends E> boolean addAll(Collection<T> c); 

ただし、[...]タイプパラメータTは1回だけ使用されます。戻り型は型パラメーターに依存せず、メソッドに対する他の引数にも依存しません(この場合、引数は1つだけです)。[...]その場合は、ワイルドカードを使用する必要があります。

私が取り組んでいるプロジェクトのコードベースには、次のようないくつかのメソッドがあります。

public <T extends Something> T getThing();

および(同じインターフェースではありません)

public <D> void storeData(int id, D data);

Somethingバウンド(上、Object下)を直接使用する代わりに、メソッドタイプパラメータを使用することに意味はありますか?

(前者の場合、いくつかの実装にはすべて注釈が付けられて@SuppressWarnings("unchecked")おり、メソッドのユーザーからこの警告を隠すことがポイントになる可能性がありますが、これが称賛に値する成果であるかどうかはわかりません。後者の場合、一部の実装はリフレクションを使用して、異なるクラスのインスタンスを異なる方法で格納しますが、typeパラメーターによってこれがどのように促進されるかはわかりません。)

4

2 に答える 2

4

型パラメーターが 1 回だけ出現する 5 つの異なるケースを考慮する必要があります。

1) リターンタイプの位置にある場合:

1.a) 戻り値の型は型変数です

public <T extends Something> T getThing();

これは危険信号である必要があります。呼び出し元は予想される戻り値の型を任意に選択でき、呼び出し先は選択された型を知る方法がありません。つまり、実装は、(a) 決して返さない、(b) 常に例外をスローする、または (c) 常に null を返す場合を除き、返される値が指定された戻り値の型になることを保証できません。これらすべてのケースで、戻り値の型はたまたま無関係です。

(個人的には、コードが非常に「動的」である場合、これらのようなメソッドは気にしません。つまり、とにかくクラスキャスト例外のリスクを実行しており、メソッド境界はまだ例外が発生するのに十分早いです。良い例ただし、メソッドを呼び出すすべての関係者は、これを知って理解する必要があります..)

1.b) 型変数は戻り値の型に含まれていますが、戻り値の型自体は含まれていません

非常に一般的で有効です。例は、 のようなグアバのさまざまなファクトリーメソッドLists.newArrayList()です。

2) パラメーター型の位置になったら:

2.a) 単純型パラメーター

public static <E> void shuffle(List<E> list);

要素をシャッフルするために、実装には実際には型パラメーターが必要であることに注意してください。とはいえ、発信者はそれを気にする必要はありません。ワイルドカードを「キャプチャ」する内部ヘルパー メソッドを作成できます。

public static void shuffle(List<?> list) {
  shuffleWithCapture(list);
}

private static <E> void shuffleWithCapture(List<E> list) {
  // implementation
}

2.b) 複数の境界を持つ型パラメーター

public static <T extends Foo & Bar> void foo(T);
public static <E extends Foo & Bar> void foo(List<E>);

Java では、型パラメーターの境界以外では交差型が許可されないため、これがこれらのシグネチャを表現する唯一の方法です。

2.c) バインドされた型パラメーターには型パラメーター変数が含まれます

public static <T extends Comparable<? super T>> void sort(List<T> list);

リストの要素が互いに比較可能でなければならないことを表現するには、それらの型の名前が必要です。そのような型パラメーターを排除する方法はありません。

于 2012-06-13T12:15:02.720 に答える
1

最初の1つ -

public <T extends Something> T getThing();

戻り値の型を割り当てられた型にキャストし、通常は安全ではありません (コンパイラーはそれについて警告します) ClassCastException。しかし、パラメーターを取らないので、常に返さSomeThingれ、そこにあるジェネリック型は役に立たないと思います。

私が思う2番目のものも、任意の型を許可するので役に立たないので、Object代わりに使用
することをお勧めしますそのような宣言はコードを読みにくくし、利点もありません.

public Something getThing();

public static void storeData(int id, Object data);
于 2012-06-13T11:21:07.777 に答える