Search code examples
javagenericseffective-java

Why this generic method call is not working?


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)

Solution

  • 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;
    
    }