1

次のコードは、Effective Java book からのものです。

Set<Integer> integers = ... ;
Set<Double> doubles = ... ;
Set<Number> numbers = union(integers, doubles);

このコードはコンパイルされませんでした。著者は、次のようにコンパイラに正確な型を伝えることで、この問題を回避することを提案しています。

Set<Number> numbers = Union.<Number>union(integers, doubles)

共用体の署名が次のような場合、以前のプログラムがコンパイルされないのはなぜですか?また、この特定の回避策のイディオムは何と呼ばれていますか?

public static <E> Set<E> union(Set<? extends E> s1,
Set<? extends E> s2)
4

6 に答える 6

5

Double と Integer は Number を拡張するだけでなく、Comparable も実装することに注意してください。したがって、コンパイラによって推測される戻り値の型は、Set<Number> にキャストできない Set<Number&Comparable> になります。次のタイプのどれを使用するかをコンパイラに伝える必要があります。次のコードでは、正確な型は必要ありません。

interface X {}
class U implements X {}
class V implements X {}

public static void main(String[] args) {
    Set<U> integers = new HashSet<U>();
    Set<V> doubles = new HashSet<V>();
    Set<X> numbers = union(integers, doubles);
}
public static <E> Set<E> union(Set<? extends E> s1,   Set<? extends E> s2) {
    return null;

}

ただし、少し変更すると、原点エラーが発生します。

   interface X {}
interface Y {}
class U implements X, Y {}
class V implements X, Y {}

public static void main(String[] args) {
    Set<U> integers = new HashSet<U>();
    Set<V> doubles = new HashSet<V>();
    Set<X> numbers = union(integers, doubles);
}
public static <E> Set<E> union(Set<? extends E> s1,   Set<? extends E> s2) {
    return null;

}
于 2013-02-26T18:05:10.927 に答える
1

唯一の問題は、コンパイラがどの型を置き換えるかを判断するほどスマートではないためE、明示的に指定する必要があることです。そのイディオムには名前がありません。ジェネリック型パラメーターを明示的に指定する方法です。

于 2013-02-26T17:55:10.690 に答える
1

Java コンパイラは、戻り値の型をできる限り絞り込もうとします。この例のモックアップを試みた後、指定せずに次のコンパイラ エラー メッセージが表示されます.<Number>union

EffectiveJava.java:19: incompatible types
found   : java.util.Set<java.lang.Number&java.lang.Comparable<? extends java.lang.Number&java.lang.Comparable<?>>>
required: java.util.Set<java.lang.Number>
      Set<Number> numbers = union(integers, doubles);

ComparableIntegers と Doubles の両方も であるため、「E」に含めようとしますComparable。そのため、コンパイラに、いいえ、私Number.<Number>union.

私の知る限り、慣用句に名前があるかどうかはわかりません。

于 2013-02-26T18:02:48.540 に答える
1

ユニオン メソッドが として定義されている場合<E> Set<E> union(Set<? extends E> s1, Set<? extends E> s2)、古い Java コンパイラは、戻り値の型を正しく推測できるほど賢くありません。したがって、型の安全性を確保するために、メソッドから返される型をコンパイラに通知する必要があります。(Java 7 コンパイラーはこれを正しく推論できると思いますが、よくわかりません)。

また、この「イディオム」の名前もわかりません。単にジェネリック関数と呼ばれています。

于 2013-02-26T17:59:42.147 に答える