The following code is from Effective Java book :
Set<Integer> integers = ... ;
Set<Double> doubles = ... ;
Set<Number> numbers = union(integers, doubles);
This code didn't compile and the author suggests to get around this problem by telling the compiler the exact type like the following :
Set<Number> numbers = Union.<Number>union(integers, doubles)
If the signature of the union is as follows why would the earlier program not compile ?Also what is this particular workaround idiom called ?
public static <E> Set<E> union(Set<? extends E> s1,
Set<? extends E> s2)
Notice that Double and Integer not only extends Number but also implements Comparable. So return type guessed by compiler would be Set<Number&Comparable> which cannot be cast to Set<Number>. You need to tell compiler which one of follow type to use. With follow code you do not need a exact type.
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;
}
But if you change it a bit you will get origin error.
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;
}