java Generics Wildcard

六月ゝ 毕业季﹏ 提交于 2020-01-14 07:40:09

问题


I have a question on the use of wildcards in Java's generic types: what is the basic difference between List<? extends Set> and List<T extends Set>? When would I use either?


回答1:


Two reasons:

To avoid unnecessary casts:

You have to use the T variant for cases like this:

public <T extends Set> T firstOf(List<T> l) {
    return l.get(0);
}

With ? this would become:

public Set firstOf2(List<? extends Set> l) {
    return l.get(0);
}

...which doesn't give the same amount of information to the caller of the firstOf method. The first version allows the caller to do this:

SubSet first = firstOf(listOfSubSet);

while with the second version, you are forced to use a cast to make it compile:

SubSet first = (SubSet)firstOf(listOfSubSet);

To enforce matching argument types:

public <T extends Set> boolean compareSets(List<T> a, List<T> b) {
    boolean same = true;
    for(T at : a) {
        for (T bt: b) {
             same &= at.equals(bt);
        }
    }
    return same;
}

There is no direct equivalent using ? instead of T for this. Note that due to Java's single-dispatch, in the above version, the compiler will call at's equals(T) method which may well differ from at's equals(Set) or equals(Object) method.




回答2:


The difference here is that in the second version, you have a type variable T that refers to the specific subtype of Set that the List contains. You need this in cases where you need to ensure that something else is the same type as the type contained in the list. A couple simple examples:

// want to ensure that the method returns the same type contained in the list
public <T extends Set> T something(List<T> list) {
  ...
}

// want to ensure both lists contain the exact same type
public <T extends Set> List<T> somethingElse(List<T> first, List<T> second) {
  ...
}

Simple rule: Use a type variable T extends Foo in your method signature if the same type is necessary in two places. Method parameters are each one place and the method return type is another place. Use the wildcard ? extends Foo if you just need to ensure you're dealing with "something that is a Foo" in one place.

Aside: don't use the raw type Set.




回答3:


You use List<? extends Set> when you declare a varlable. For example:

List<? extends Number> l = new ArrayList<Integer>();

List<T extends Number> can be used in class or methode declaration. This will allow you to write T instead of <? extends Number> later on in the function.

public <T extends Number> int addAll(List<T> list) {
    int result = 0;
    for (T t : list) {
        result += t.intValue();
    }
    return result;
}



回答4:


We use wildcards to specify that the type element matches anything. The ? stands for unknown type.

List<? extends Set> is an example of a bounded wildcard and that states that the list can accept any subtype of a Set (e.g. HashSet) List<T extends Set>, on the other hand is, allows T to be bounded to a type that extends Set.

I use wildcards when I need a collection of data irrespective pf it's exact type.




回答5:


A wildcard type G<? extends A> is a super type of any G<Ai> where Ai is a subtype of A

In another word, G<? extends A> is the union type of G<A0>, ..., G<An>.



来源:https://stackoverflow.com/questions/6279516/java-generics-wildcard

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