Generic upper bounded wildcard instantiation known at run time

烂漫一生 提交于 2019-12-11 20:22:11

问题


class Aliphatic<F> extends Organic<F>{}
class Hexane<G> extends Aliphatic<G>{}
public class Organic<E>{
    void react(E e){}
    static void main(String[] args){
        Organic<? extends Organic> compound = new Aliphatic<Organic>();
        compound.react(new Organic());
    }
}

Why can't I call react method with Organic argument? The generic type ot the reference <? extends Organic> says that the generic type of the instantiation canb either a Organic, or a subtype of Organic.

Is because the compiler doesn't know this instantiation generic type until runtime type an so, it does not bind any value to its generic criteria?

Why is this case working? Is this case the same?

public class WildcardCollection {
    public static void main (String[] args){
        WildcardCollection w = new WildcardCollection();
        w.myMethod(new Items("hola",1));     //Compile
        w.myMethod(new SubItems("nuevo",3)); //Compile
    }
    public <T extends Items> void myMethod(T a){ //Same as above
        System.out.println("hi: "+a);
    }
}
class SubItems extends Items {
    SubItems(){};
    SubItems(String s, int i){ super(s,i);}
}
class Items implements Comparable<Items> {
    private String name;
    private int value;

    public Items() {}

    public Items(String n, int i){ this.name = n; this.value = i;}
    public String getName(){ return this.name;}
    public int getValue(){ return this.value;}

    public String toString(){ return "(" + this.name + "-" + this.value + ")";}

    public int compareTo(Items i){
        return this.value - i.getValue();
    }
}

回答1:


Quite simply, if you have an object of some generic type with a type parameter T instantiated with a ? extends X wildcard then you can't call methods on the object that take parameters of type T because the compiler can't guarantee type safety. However you can call methods that return T (and assign the return value to a variable of type X). In your specific example it looks like this should be safe

Organic<? extends Organic> compound = new Aliphatic<Organic>();
compound.react(new Organic());

but remember that the compiler has to match the react call based on the declaration type (? extends Organic), it can't rely on what you've assigned on the RHS. If the compiler allowed this then it would also have to allow

Organic<? extends Organic> compound = new Aliphatic<Hexane<?>>();
compound.react(new Organic());

which is clearly not correct - it's exactly the same situation as

Collection<? extends Number> nums = new ArrayList<Float>();
nums.add(Integer.valueOf(1));

(all this is aside from the fact that since Organic is generic you need to say Organic<? extends Organic<?>> or similar rather than just Organic<? extends Organic>)



来源:https://stackoverflow.com/questions/12898264/generic-upper-bounded-wildcard-instantiation-known-at-run-time

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!