Generic lower unbound vs upper bounded wildcards

2019-02-25 06:29发布

import java.util.List;
import java.util.ArrayList;

interface Canine {}
class Dog implements Canine {}
public class Collie extends Dog {
    public static void main(String[] args){
        List<Dog> d = new ArrayList<Dog>();
        List<Collie> c = new ArrayList<Collie>();
        d.add(new Collie());
        c.add(new Collie());
        do1(d); do1(c);
        do2(d); do2(c);
    }
    static void do1(List<? extends Dog> d2){
        d2.add(new Collie());
        System.out.print(d2.size());
    }
    static void do2(List<? super Collie> c2){
        c2.add(new Collie());
        System.out.print(c2.size());
    }
}

The answer for this question tell that when a method takes a wildcard generic typ, the collection can be accessed or modified, but not both. (Kathy and Bert)

What does it mean 'when a method takes a wildcard generic typ, the collection can be accessed or modified, but not both' ?

As far as I know, The method do1 has List<? extends Dog> d2 so d2 only can be accessed but not modified. The method d2 has List<? super Collie> c2 so c2 can be accessed and modified and there is no compilation error.

Generic guidelines

5条回答
可以哭但决不认输i
2楼-- · 2019-02-25 06:32

You simply cannot add a Collie to a List<? extends Dog> because this reference may hold for example a List<Spaniel>.

查看更多
来,给爷笑一个
3楼-- · 2019-02-25 06:40

You cannot add a Cat to a List<? extends Animal> because you don't know what kind of list that is. That could be a List<Dog> also. So you don't want to throw your Cat into a Black Hole. That is why modification of List declared that way is not allowed.

Similarly when you fetch something out of a List<? super Animal>, you don't know what you will get out of it. You can even get an Object, or an Animal. But, you can add an Animal safely in this List.

查看更多
Root(大扎)
4楼-- · 2019-02-25 06:41

The answer for this question tell that when a method takes a wildcard generic typ, the collection can be accessed or modified, but not both. (Kathy and Bert)

That's a fair first approximation, but not quite correct. More correct would be:

You can only add null to a Collection<? extends Dog> because its add method takes an argument of ? extends Dog. Whenever you invoke a method, you must pass parameters that are of a subtype of the declared parameter type; but for the parameter type ? extends Dog, the compiler can only be sure that the argument is of compatible type if the expression is null. However, you can of course modify the collection by calling clear() or remove(Object).

On the other hand, if you read from a Collection<? super Dog>, its iterator has return type ? super Dog. That is, it will return objects that are a subtype of some unknown supertype of Dog. But differently, the Collection could be a Collection<Object> containing only instances of String. Therefore

for (Dog d : collection) { ... } // does not compile

so the only thing we know is that instances of Object are returned, i.e. the only type-correct way of iterating such a Collection is

for (Object o : collection) { ... }

but it is possible to read from a collection, you just don't know what types of objects you will get.

We can easily generalize that observation to: Given

class G<T> { ... }

and

G<? extends Something> g;

we can only pass null to method parameters with declared type T, but we can invoke methods with return type T, and assign the result a variable of type Something.

On the other hand, for

G<? super Something> g;

we can pass any expression of type Something to method parameters with declared type T, and we can invoke methods with return type T, but only assign the result to a variable of type Object.

To summarize, the restrictions on the use of wildcard types only depend on the form of the method declarations, not on what the methods do.

查看更多
再贱就再见
5楼-- · 2019-02-25 06:42

I pasted your code into my IDE. The following error was signalled inside do1:

The method add(capture#1-of ? extends Dog) in the type List is not applicable for the arguments (Collie)

This is, of course, as expected.

查看更多
贼婆χ
6楼-- · 2019-02-25 06:45

I pasted your code into IDEONE http://ideone.com/msMcQ. It did not compile for me - which is what I expected. Are you sure you did not have any compilation errors?

查看更多
登录 后发表回答