7

それで、私はジェネリックスを読んで、概念を再理解しました。特に、ワイルドカードを使用したり、遭遇したりすることがほとんどないため、ワイルドカードが関係している場合はそうです。私が行った読書から、なぜ彼らがワイルドカードを使用するのか理解できません。私が出くわす例の1つは次のとおりです。

void printCollection( Collection<?> c ) {
  for (Object o : c){
    System.out.println(o);
  }
}

なぜあなたはこれを次のように書かないのですか?

<T> void printCollection( Collection<T> c ) {
    for(T o : c) {
        System.out.println(o);
    }
}

オラクルのウェブサイトからの別の例:

public static double sumOfList(List<? extends Number> list) {
    double s = 0.0;
    for (Number n : list)
        s += n.doubleValue();
    return s;
}

なぜこれは次のように書かれていないのですか

public static <T extends Number> double sumOfList(List<T> list) {
    double s = 0.0;
    for (Number n : list)
        s += n.doubleValue();
    return s;
}

私は何かが足りないのですか?

4

3 に答える 3

3

なぜ物事を必要以上に複雑にするのですか?これらの例は、おそらく機能する可能性のある最も単純なことを示しています。これらの例は、一般的な方法を説明しようとしているのではありません。

なぜあなたはこれを次のように書かないのですか?

<T> void printCollection( Collection<T> c ) {
    for(T o : c) {
        System.out.println(o);
    }
}

System.out.println()オブジェクトを受け入れることができるので、これ以上具体的なものは必要ありません。

なぜこれは次のように書かれていないのですか

public static <T extends Number> double sumOfList(List<T> list) {
    double s = 0.0;
    for (Number n : list)
        s += n.doubleValue();
    return s;
}

繰り返しますが、異なるごとに異なるパラメータ化は必要ないためですT extends Number。aを受け入れる非ジェネリックメソッドでList<? extends Number>十分です。

于 2013-02-28T01:09:27.313 に答える
3

メソッドパラメータタイプに上限のある第1レベルのワイルドカードがある場合、それをタイプパラメータに置き換えることができるのは事実です。

カウンターの例(ワイルドカードはタイプパラメーターで置き換えることはできません)

    List<?> foo()  // wildcard in return type  

    void foo(List<List<?>> arg)   // deeper level of wildcard

    void foo(List<? super Number> arg)   // wildcard with lower bound

ワイルドカードまたはタイプパラメータのいずれかで解決できる場合

        void foo1(List<?> arg)

    <T> void foo2(List<T> arg)

一般的に、foo1() よりスタイリッシュだと考えられていfoo2()ます。それはおそらく少し主観的です。foo1()個人的には署名の方がわかりやすいと思います。そしてfoo1()、業界で圧倒的に採用されているので、慣習に従う方が良いです。

foo1()また、でarg簡単に行うことはできないため、もう少し抽象的に扱います。もちろん、これは簡単に回避できます(つまり、argを!に渡します)。パブリックメソッドがのように見えることも一般的な方法であり、これは内部的にプライベートに転送されます。arg.add(something)foo1()foo2()foo1()foo2()

ワイルドカードが機能せず、タイプパラメータが必要な場合もあります。

    <T> void foo(List<T> foo1, List<T> foo2);  // can't use 2 wildcards.

これまでのこの議論は、メソッドのシグネチャについてです。他の場所では、タイプパラメータを導入できない場合にワイルドカードが不可欠になることがあります。

于 2013-02-28T01:20:20.190 に答える
3

Oracleから:

発生する質問の1つは、ジェネリックメソッドをいつ使用する必要があるのか​​、ワイルドカードタイプをいつ使用する必要があるのか​​ということです。答えを理解するために、コレクションライブラリのいくつかのメソッドを調べてみましょう。

interface Collection<E> {
     public boolean containsAll(Collection<?> c);
     public boolean addAll(Collection<? extends E> c);
 }

代わりに、ここで一般的なメソッドを使用することもできます。

interface Collection<E> {
     public <T> boolean containsAll(Collection<T> c);
     public <T extends E> boolean addAll(Collection<T> c);
     // Hey, type variables can have bounds too!
 }

ただし、containsAllとaddAllの両方で、型パラメーターTは1回だけ使用されます。戻り型は型パラメーターに依存せず、メソッドに対する他の引数にも依存しません(この場合、引数は1つだけです)。これは、type引数がポリモーフィズムに使用されていることを示しています。その唯一の効果は、さまざまな実際の引数タイプをさまざまな呼び出しサイトで使用できるようにすることです。その場合は、ワイルドカードを使用する必要があります。ワイルドカードは、柔軟なサブタイピングをサポートするように設計されています。これは、ここで表現しようとしていることです。

したがって、最初の例では、操作がタイプに依存しないためです。

2つ目は、Numberクラスのみに依存するためです。

于 2013-02-28T02:16:02.330 に答える