Domanda

I read a little about generics, wildcards and inheritence. But still can not figure out why there an error at line getFoo().doit(this); Can someone please explain why this is happening, and what is the proper way to do it?

public class A<T> {
    private Foo<T, ? extends A<T>> foo;
    public Foo<T, ? extends A<T>> getFoo() {
        return foo;
    }
    public void setFoo(Foo<T, ? extends A<T>> foo) {
        this.foo = foo;
    }
}

public class B extends A<Integer>{
    public B() {
        setFoo(new Bar());
        getFoo().doit(this);
    }
}

public class Bar implements Foo<Integer, B> {
@Override
    public void doit(B a) {
        System.out.println("some process");
    }

}

public interface Foo<T, V extends A<T>> {
    public void doit(V a);
}
È stato utile?

Soluzione

You are not allowed to supply non-null value as a wildcard extends argument in a method call (getFoo().doit(<? extends A<Integer> a) in your case). The reason is that the compiler can not know what was the original generic definition, so it will refuse to compile the code.

Your problem can be illustrated with a simle List<?>:

public static List<Integer> myList = new ArrayList<Integer>();

public static List<? extends Number> getList() {
    return myList;
}

public static void main() {
    getList().add(Integer.valueOf(1000)); // Can not substitute wildcard by Integer 
}

The code above looks completely fine (apart from the compilation error :)), but imagine this:

public static void main() {
    getList().add(Long.valueOf(1000)); // This would definitely cause ClassCastException later when someone calls myList.get(0)
}

UPDATE To workaround your problem you need to get rid of the wildcard, for example by adding another type parameter to your class definition:

public class A<T, V extends A<T, V>> {
    private Foo<T, V> foo;
    public Foo<T, V> getFoo() {
        return foo;
    }
    public void setFoo(Foo<T, V> foo) {
        this.foo = foo;
    }
}

public class B extends A<Integer, B>{
    public B() {
        setFoo(new Bar());
        getFoo().doit(this);
    }
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top