Generic types : wildcards vs variables of raw type

2019-02-15 15:13发布

问题:

Consider following methods:

public static void listAll(LinkedList list) {

    for(Object obj : list)
        System.out.println(obj);

}

and

public static void listAll(LinkedList<?> list) {

    for(Object obj : list)
        System.out.println(obj);

}

What is the difference between these two methods? If there is no difference, why we should use the second one?

回答1:

<?> doesn't allow you to add objects in list. See the program below. It is specific type of list we have passed to method <?>.
Specific means, list was created with specific type and passed to <?> method listAll. Don't confuse with word specific.
Specific can be any normal object, like, Dog, Tiger, String, Object, HashMap, File, Integer, Long.... and the list is endless.
JLS forces <?> method for not to perform add any irrelevant objects in called <?> method once you have defined (defined in calling method not in called-listAll ) list containing specific type of object.
It is like <?> saying "don't touch me".

public static void listAll(LinkedList list) 
{
    list.add(new String());  //works fine
    for(Object obj : list)
            System.out.println(obj);

}
public static void listAll(LinkedList<?> list) 
{
     list.add(new String());  //compile time error. Only 'null' is allowed.
     for(Object obj : list)
          System.out.println(obj);
}

Now let's look at the different scenario. What will happen when we declare specific type like, Dog, Tiger, Object, String ..... anything. Let's change the method to specific type.

public static void listAll(LinkedList<String> list)// It is now specific type, 'String'
{
    list.add(new String());//works fine. Compile time it knows that 'list' has 'String'
    for(Object obj : list)
         System.out.println(obj);
}


回答2:

List is a raw type, List<?> is a generic type with wildcard argument.

Suppose that we have the following variables:

List<?> a;
List<String> b;
List c;

The assignment b=a gives a compile-time error (a List<String> is not assignable to List<?), but c=a compiles fine (List<String> is assignable to the raw type List for compatibility with legacy code not using generics).

The assignment b=c gives a compile-time warning (List<?> is not assignable to List<String>), but a=c compiles fine (List<String> is assignable to List<?>)