Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between generic type and wildcard type

I'm a newbie in Generic and my question is: what difference between two functions:

function 1:

public static <E> void funct1  (List<E> list1) {

}

function 2:

public static void funct2(List<?> list) {

}
like image 231
Fio Avatar asked Jun 08 '12 04:06

Fio


4 Answers

The first signature says: list1 is a List of Es.

The second signature says: list is a List of instances of some type, but we don't know the type.

The difference becomes obvious when we try to change the method so it takes a second argument, which should be added to the list inside the method:

import java.util.List;

public class Experiment {
    public static <E> void funct1(final List<E> list1, final E something) {
        list1.add(something);
    }

    public static void funct2(final List<?> list, final Object something) {
        list.add(something); // does not compile
    }
}

The first one works nicely. And you can't change the second argument into anything that will actually compile.

Actually I just found an even nicer demonstration of the difference:

public class Experiment {
    public static <E> void funct1(final List<E> list) {
        list.add(list.get(0));
    }

    public static void funct2(final List<?> list) {
        list.add(list.get(0)); // !!!!!!!!!!!!!! won't compile !!!!!!!!!
    }
}

One might as why do we need <?> when it only restricts what we can do with it (as @Babu_Reddy_H did in the comments). I see the following benefits of the wildcard version:

  • The caller has to know less about the object he passes in. For example if I have a Map of Lists: Map<String, List<?>> I can pass its values to your function without specifying the type of the list elements. So

  • If I hand out objects parameterized like this I actively limit what people know about these objects and what they can do with it (as long as they stay away from unsafe casting).

These two make sense when I combine them: List<? extends T>. For example consider a method List<T> merge(List<? extends T>, List<? extends T>), which merges the two input lists to a new result list. Sure you could introduce two more type parameters, but why would you want to? It would be over specifying things.

  • finally wildcards can have lower bounds, so with lists you can make the add method work, while get doesn't give you anything useful. Of course that triggers the next question: why don't generics have lower bounds?

For a more in depth answer see: When to use generic methods and when to use wild-card? and http://www.angelikalanger.com/GenericsFAQ/FAQSections/TypeArguments.html#FAQ203

like image 163
Jens Schauder Avatar answered Oct 17 '22 17:10

Jens Schauder


Generics makes the collection more type safe.

List<E> : E here is the Type Parameter, which can be used to determine the content type of the list, but there was No way to check what was the content during the runtime.

Generics are checked only during compilation time.

<? extends String> : This was specially build into java, to handle the problem which was with the Type Parameter. "? extends String" means this List can have

objects which IS-A String.

For eg:

Animal class
        Dog class extends Animal
        Tiger class extends Animal

So using "public void go(ArrayList<Animal> a)" will NOT accept Dog or Tiger as its content but Animal.

"public void go(ArrayList<? extends Animal> a)" is whats needed to make the ArrayList take in Dog and Tiger type.

Check for references in Head First Java.

like image 32
Kumar Vivek Mitra Avatar answered Oct 17 '22 17:10

Kumar Vivek Mitra


List<E> as a parameter type says that the parameter must be a list of items with any object type. Moreover, you can bind the E parameter to declare references to list items inside the function body or as other parameter types.

The List<?> as a parameter type has the same semantics, except that there is no way to declare references to the items in the list other than to use Object. Other posts give additional subtle differences.

like image 2
Gene Avatar answered Oct 17 '22 17:10

Gene


The first is a function that accepts a parameter that must be a list of items of E type.

the second example type is not defined

List<?> list

so you can pass list of any type of objects.

like image 1
Pramod Kumar Avatar answered Oct 17 '22 17:10

Pramod Kumar