java Generics Wildcard - java

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?

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.

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.

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;
}

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.

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>.

Related

Difference between Bounded Type parameter (T extends) and Upper Bound Wildcard (? extends)

I know that there was a similar question already posted, although I think mine is somewhat different...
Suppose you have two methods:
// Bounded type parameter
private static <T extends Number> void processList(List<T> someList) {
}
// Upper bound wildcard
private static void processList2(List<? extends Number> someList) {
// ...
}
As far as I know, both methods accepts arguments, that are List of type Number or List of subtype of Number.
But what's the difference between the two methods after all?
There are several differences between the two syntaxes during compile time :
With the first syntax, you can add elements to someList but with the second, you can't. This is commonly known as PECS and less commonly known as the PUT and GET prinicple.
With the first syntax, you have a handle to the type parameter T so you can use it to do things such as define local variables within the method of type T, cast a reference to the type T, call methods that are available in the class represented by T, etc. But with the second syntax, you don't have a handle to the type so you can't do any of this.
The first method can actually be called from the second method to
capture the wildcard. This is the most common way to capture a
wildcard via a helper method.
private static <T extends Number> void processList(List<T> someList) {
T n = someList.get(0);
someList.add(1,n); //addition allowed.
}
private static void processList2(List<? extends Number> someList) {
Number n = someList.get(0);
//someList.add(1,n);//Compilation error. Addition not allowed.
processList(someList);//Helper method for capturing the wildcard
}
Note that since generics are compile time sugar, these differences at a broader level are only limited to the compilation.
I can think of the below differences :
a) Modifying your list inside the method, consider the below code :
// Bounded type parameter
private static <T extends Number> void processList(List<T> someList)
{
T t = someList.get(0);
if ( t.getClass() == Integer.class )
{
Integer myNum = new Integer(4);
someList.add((T) myNum);
}
}
// Upper bound wildcard
private static void processList2(List<? extends Number> someList)
{
Object o = someList.get(0);
if ( o instanceof Integer )
{
Integer myNum = new Integer(4);
someList.add(myNum); // Compile time error !!
}
}
With wildcard, you cannot add elements to the list! The compiler tells you that it doesn't know what is myNum. But in the first method, you could add an Integer by first checking if T is Integer, with no compile time error.
b) The first method is called generic method. It follows the syntax that is defined for a generic method.
The upper bounds specified in the method definition are used to restrict the parameter types.
The second one is NOT necessarily called a generic method, it is a normal method that happens to accept a generic parameter.
The wildcard ? with extends keyword is used as a means of relaxing the types that the method can accept.
The difference is on the compiler side.
On the first one you can use the type (to cast something or use it as a bound to call another method for example) while on the second one, you cannot use it.
If you want to use the type information then go with bounded. With the wildcard, the argument will appear as a generic Object and you won't be able to call methods based on that type.
public static <T extends Object> ListIterator<T> createListIterator(ListIterator<T> o)
{
return new ListIteratorAdaptor<T>(o);
}
https://docs.oracle.com/javase/tutorial/java/generics/bounded.html
There are following three types of Wildcard usually used with Generic in JAVA. Each one is explained as below with example.
Upper-bounded Wildcard:
? extends T : In Upper bounded wildcard only T or its subtypes will be supported.
For example we have an Animal class and have Dog , Cat as its subtypes. So following generic methods will only
accept parameters of type Data<Animal>, Data<Dog> and Data<Cat>
public static void add(Data<? extends Animal> animalData) {
}
Lower-bounded Wildcard:
? super T : In Lower-bounded wildcard only T or its super types will be supported.
Same example we used for defining Lower-bounded Wildcard. Lets say we have Animal class as super or parent class
and Dog as its child class. Now below method use Lower-bounded Wildcard and will only accept parameters of type
Data<Animal>, Data<Dog> and Data<Object>
public static void add(Data<? super Dog> animalData) {
}
Unbounded Wildcard:
? : Unbounded wildcard supports all types. So our above example method can take parameters of type
Data<Animal>, Data<Dog> , Data<Object> and Data<Cat>
public static void add(Data<?> animalData) {
}

Benefits of using ? instead of T for type parameter in Java generics? [duplicate]

I am reading about generic methods from OracleDocGenericMethod. I am pretty confused about the comparison when it says when to use wild-card and when to use generic methods.
Quoting from the document.
interface Collection<E> {
public boolean containsAll(Collection<?> c);
public boolean addAll(Collection<? extends E> c);
}
We could have used generic methods here instead:
interface Collection<E> {
public <T> boolean containsAll(Collection<T> c);
public <T extends E> boolean addAll(Collection<T> c);
// Hey, type variables can have bounds too!
}
[…]
This tells us that the type argument is being used for polymorphism;
its only effect is to allow a variety of actual argument types to be
used at different invocation sites. If that is the case, one should
use wildcards. Wildcards are designed to support flexible subtyping,
which is what we're trying to express here.
Don't we think wild card like (Collection<? extends E> c); is also supporting kind of
polymorphism? Then why generic method usage is considered not good in this?
Continuing ahead, it states,
Generic methods allow type parameters to be used to express
dependencies among the types of one or more arguments to a method
and/or its return type. If there isn't such a dependency, a generic
method should not be used.
What does this mean?
They have presented the example
class Collections {
public static <T> void copy(List<T> dest, List<? extends T> src) {
...
}
[…]
We could have written the signature for this method another way,
without using wildcards at all:
class Collections {
public static <T, S extends T> void copy(List<T> dest, List<S> src) {
...
}
The document discourages the second declaration and promotes usage of first syntax? What's the difference between the first and second declaration? Both seems to be doing the same thing?
Can someone put light on this area.
There are certain places, where wildcards, and type parameters do the same thing. But there are also certain places, where you have to use type parameters.
If you want to enforce some relationship on the different types of method arguments, you can't do that with wildcards, you have to use type parameters.
Taking your method as example, suppose you want to ensure that the src and dest list passed to copy() method should be of same parameterized type, you can do it with type parameters like so:
public static <T extends Number> void copy(List<T> dest, List<T> src)
Here, you are ensured that both dest and src have same parameterized type for List. So, it's safe to copy elements from src to dest.
But, if you go on to change the method to use wildcard:
public static void copy(List<? extends Number> dest, List<? extends Number> src)
it won't work as expected. In 2nd case, you can pass List<Integer> and List<Float> as dest and src. So, moving elements from src to dest wouldn't be type safe anymore.
If you don't need such kind of relation, then you are free not to use type parameters at all.
Some other difference between using wildcards and type parameters are:
If you have only one parameterized type argument, then you can use wildcard, although type parameter will also work.
Type parameters support multiple bounds, wildcards don't.
Wildcards support both upper and lower bounds, type parameters just support upper bounds. So, if you want to define a method that takes a List of type Integer or it's super class, you can do:
public void print(List<? super Integer> list) // OK
but you can't use type parameter:
public <T super Integer> void print(List<T> list) // Won't compile
References:
Angelika Langer's Java Generics FAQs
Consider following example from The Java Programming by James Gosling 4th edition below where we want to merge 2 SinglyLinkQueue:
public static <T1, T2 extends T1> void merge(SinglyLinkQueue<T1> d, SinglyLinkQueue<T2> s){
// merge s element into d
}
public static <T> void merge(SinglyLinkQueue<T> d, SinglyLinkQueue<? extends T> s){
// merge s element into d
}
Both of the above methods have the same functionality. So which is preferable? Answer is 2nd one. In the author's own words :
"The general rule is to use wildcards when you can because code with wildcards
is generally more readable than code with multiple type parameters. When deciding if you need a type
variable, ask yourself if that type variable is used to relate two or more parameters, or to relate a parameter
type with the return type. If the answer is no, then a wildcard should suffice."
Note: In book only second method is given and type parameter name is S instead of 'T'. First method is not there in the book.
In your first question: It means that if there is a relation between the parameter's type and the method's return type then use a generic.
For example:
public <T> T giveMeMaximum(Collection<T> items);
public <T> Collection<T> applyFilter(Collection<T> items);
Here you are extracting some of the T following a certain criteria. If T is Long your methods will return Long and Collection<Long>; the actual return type is dependent on the parameter type, thus it is useful, and advised, to use generic types.
When this is not the case you can use wild card types:
public int count(Collection<?> items);
public boolean containsDuplicate(Collection<?> items);
In this two example whatever the type of the items in the collections the return types will be int and boolean.
In your examples:
interface Collection<E> {
public boolean containsAll(Collection<?> c);
public boolean addAll(Collection<? extends E> c);
}
those two functions will return a boolean whatever is the types of the items in the collections. In the second case it is limited to instances of a subclass of E.
Second question:
class Collections {
public static <T> void copy(List<T> dest, List<? extends T> src) {
...
}
This first code allow you to pass an heterogeneous List<? extends T> src as a parameter. This list can contain multiple elements of different classes as long as they all extends the base class T.
if you had:
interface Fruit{}
and
class Apple implements Fruit{}
class Pear implements Fruit{}
class Tomato implements Fruit{}
you could do
List<? extends Fruit> basket = new ArrayList<? extends Fruit>();
basket.add(new Apple());
basket.add(new Pear());
basket.add(new Tomato());
List<Fruit> fridge = new ArrayList<Fruit>();
Collections.copy(fridge, basket);// works
On the other hand
class Collections {
public static <T, S extends T> void copy(List<T> dest, List<S> src) {
...
}
constrain List<S> src to be of one particular class S that is a subclass of T. The list can only contain elements of one class (in this instance S) and no other class, even if they implement T too. You wouldn't be able to use my previous example but you could do:
List<Apple> basket = new ArrayList<Apple>();
basket.add(new Apple());
basket.add(new Apple());
basket.add(new Apple());
List<Fruit> fridge = new ArrayList<Fruit>();
Collections.copy(fridge, basket); /* works since the basket is defined as a List of apples and not a list of some fruits. */
Wildcard method is also generic - you could call it with some range of types.
The <T> syntax defines a type variable name. If a type variable has any use (e.g. in method implementation or as a constraint for other type), then it makes sense to name it, otherwise you could use ?, as anonymous variable. So, looks like just a short-cut.
Moreover, the ? syntax is not avoidable when you declare a field:
class NumberContainer
{
Set<? extends Number> numbers;
}
I will try and answer your question, one by one.
Don't we think wild card like (Collection<? extends E> c); is also
supporting kind of polymorphism?
No. The reason is that the bounded wildcard has no defined parameter type. It is an unknown. All it "knows" is that the "containment" is of a type E (whatever defined). So, it cannot verify and justify whether the value provided matches the bounded type.
So, it's no sensible to have polymorphic behaviours on wildcards.
The document discourages the second declaration and promotes usage of
first syntax? What's the difference between the first and second
declaration? Both seems to be doing the same thing?
The first option is better in this case as T is always bounded, and source will definitely have values (of unknowns) that subclasses T.
So, suppose that you want to copy all list of numbers, the first option will be
Collections.copy(List<Number> dest, List<? extends Number> src);
src, essentially, can accept List<Double>, List<Float>, etc. as there is an upper bound to the parameterized type found in dest.
The 2nd option will force you to bind S for every type you want to copy, like so
//For double
Collections.copy(List<Number> dest, List<Double> src); //Double extends Number.
//For int
Collections.copy(List<Number> dest, List<Integer> src); //Integer extends Number.
As S is a parameterized type that needs binding.
I hope this helps.
One other difference which is not listed here.
static <T> void fromArrayToCollection(T[] a, Collection<T> c) {
for (T o : a) {
c.add(o); // correct
}
}
But the following will result in compile time error.
static <T> void fromArrayToCollection(T[] a, Collection<?> c) {
for (T o : a) {
c.add(o); // compile time error
}
}
? means unknown
The general rule applies:
You can read from it, but not write
given simple pojo Car
class Car {
void display(){
}
}
This will compile
private static <T extends Car> void addExtractedAgain1(List<T> cars) {
T t = cars.get(1);
t.display();
cars.add(t);
}
This method won't compile
private static void addExtractedAgain2(List<? extends Car> cars) {
Car car = cars.get(1);
car.display();
cars.add(car); // will not compile
}
Another example
List<?> hi = Arrays.asList("Hi", new Exception(), 0);
hi.forEach(o -> {
o.toString() // it's ok to call Object methods and methods that don't need the contained type
});
hi.add(...) // nothing can be add here won't compile, we need to tell compiler what the data type is but we do not know
As far as I understand, there is only one use case when wildcard is strictly needed (i.e. can express something that you can not express using explicit type parameters). This is when you need to specify a lower bound.
Apart from that however wildcards serve to write more concise code, as described by the following statements in the document you mention:
Generic methods allow type parameters to be used to express
dependencies among the types of one or more arguments to a method
and/or its return type. If there isn't such a dependency, a generic
method should not be used.
[...]
Using wildcards is clearer and more concise than declaring explicit
type parameters, and should therefore be preferred whenever possible.
[...]
Wildcards also have the advantage that they can be used outside of
method signatures, as the types of fields, local variables and arrays.
Mainly -> Wildcards enforce generics at the parameter/argument level of a Non-Generic method.
Note. It can also be performed in genericMethod by default, but here instead of ? we can use T itself.
package generics;
public class DemoWildCard {
public static void main(String[] args) {
DemoWildCard obj = new DemoWildCard();
obj.display(new Person<Integer>());
obj.display(new Person<String>());
}
void display(Person<?> person) {
//allows person of Integer,String or anything
//This cannnot be done if we use T, because in that case we have to make this method itself generic
System.out.println(person);
}
}
class Person<T>{
}
SO wildcard has its specific usecases like this.

Generic vs wildcard unknown types

When is it recommended to do:
public <E> boolean hasPropertyX(List<E extends User> alist);
versus
public boolean hasPropertyX(List<? extends User> alist);
It would appear they both work just as well.
Without typed return value, the only difference I can think of is explicit typing of the first way of declaration during method call.
So for example you are using it inside typed class C<K extends String>
List<V extends String> input = ...;
boolean var = obj.hasProperty<K>(input);
will raise the compiler error. But why would any one want to do so...
Nice question even if most likely the answer is both are the same.
I suppose in that particular example they both do work effectively the same way in terms of type checking. However, if you extend the generic type to require a base or superclass of some class it can be useful. e.g.
public <E extends User> boolean hasPropertyX(List<E> alist);
This at least enforces that you're receiving some subclass of User.
EDIT
You can use a wildcard to achieve the same thing:
public boolean hasPropertyX(List<? extends User> alist);
But this won't work if, for example, you want to use the generic for multiple parameters:
public <E extends Automobile> void crashAutos(List<E> list1, List<E> list2);
This enforces the generic type on both arguments, whereas the following code does not force the two lists to contain the same type:
public void crashAutos(List<? extends Automobile> list1, List<? extends Automobile> list2);
I could call that method with two different subclasses of the Automobile class:
List<Car> cars = ...
List<Truck> trucks = ...
crashAutos(cars, trucks);
Whereas using generics enforces the same type for both arguments.
Explicitly naming the generic type as E and not ? has these uses (as far as I can think of):
0) To tie the return type to some part of the argument type - for example:
public <E> E getSomeElement(List<E> lst) { ... }
// ^ If we don't name the argument type as having E,
// then we can't specify the return type as being E
1) To tie some part of the argument type to some part of the enclosing type:
class Storage<E> {
E item;
public void replace(Storage<E> st) { item = st.item; }
// ^ This wouldn't work if we wrote Storage<?> instead
}
2) To tie some combination of the argument types, return type, and enclosing type (see #0 and #1).
We can get away with the anonymous type name ? if we don't care about the actual type. Here is a basic example:
boolean allEqual(List<?> lst, Object y) {
for (Object x : lst) { // Any reference can be stored as Object
if (!y.equals(x)) // equals takes an Object
return false;
}
return true;
}
// ^ We could also rewrite this example with List<E> and "E x".
Another example:
int intSum(List<? extends Number> lst) {
int sum = 0;
for (Number x : lst) // We only care that the list element is a Number
sum += x.intValue();
return sum;
}
// ^ We could also rewrite with List<E extends Number> and "E x".
Alternate reading: http://docs.oracle.com/javase/tutorial/extra/generics/wildcards.html
Differences between generics and wildcard unknown types:
Enforcing a relationship on the types of method arguments (Use Generics)
Supporting multiple bounds (Use Generics)
Supporting both upper and lower bounds (Use Wildcard)
The related question:
When to use generic methods and when to use wild-card?
Use ? extends when you only need to retrieve from the List:
User getElement(List<? extends User> list, int i) {
return list.get(i);
}
Use ? super when you only need to add to the List:
void addElement(List<? super User> list, User u) {
list.add(u);
}
Use E extends when you both need to retrieve and add:
<E extends User> void swapElements(List<E> list, int i, int j) {
E temp = list.get(i);
list.set(i, list.get(j));
list.set(j, temp);
}
? extends User: We don't know the exact type of the List, but we can retrieve a User from it.
? super User: We don't know the exact type of the List, but we can put a User in it.
E extends User: We don't necessarily know the exact type of the List but it conforms to constraints such that:
We give its actual type the name E.
We know E is at least User.
We can both retrieve E from the List and put E in the List.
See also:
What is PECS (Producer Extends Consumer Super)?

When to use wildcards in Java Generics?

this is from HeadFirst Java: ( page 575 )
This:
public <T extends Animal> void takeThing(ArrayList<T> list)
Does the same thing as this:
public void takeThing(ArrayList<? extends Animal> list)
So here is my question: if they are exactly same, why don't we write
public <? extends Animal> void takeThing(ArrayList<?> list)
or
public void takeThing(ArrayList<T extends Animal> list)
Also, when would it be useful to use a ? instead of a T in a method declaration ( as above ) with Generics, or for a Class declaration? What are the benefits?
The big difference between
public <T extends Animal> void takeThing(ArrayList<T> list)
and
public void takeThing(ArrayList<? extends Animal> list)
is that in the former method you can refer to "T" within the method as the concrete class that was given. In the second method you cannot do this.
Here a more complex example to illustrate this:
// here i can return the concrete type that was passed in
public <T extends Animal> Map<T, String> getNamesMap(ArrayList<T> list) {
Map<T, String> names = new HashMap<T, String>();
for (T animal : list) {
names.put(animal, animal.getName()); // I assume there is a getName() method
}
return names;
}
// here i have to use general Animal
public Map<Animal, String> getNamesMap(ArrayList<? extends Animal> list) {
Map<Animal, String> names = new HashMap<Animal, String>();
for (Animal animal : list) {
names.put(animal, animal.getName()); // I assume there is a getName() method
}
return names;
}
With the first method if you pass in an List of Cats you get a Map with Cat as key. The second method would always return a Map with general Animal key.
By the way this is not valid java syntax:
public <? extends Animal> void takeThing(ArrayList<?> list)
Using this form of generic method declaration you have to use a valid java identifier and not "?".
Edit:
The form "? extends Type" only applies to variable or parameter type declaration. Within a generic method declration it has to be "Identifier extends Type" as you are able to refer to the "Identifier" from within your method.
Wild cards are about co/contra variance of generics. I will try to make clear what this means by providing some examples.
Basically it is related to the fact that for types S and T, where S is a subtype of T, a generic type G<S> is not a valid subtype of G<T>
List<Number> someNumbers = new ArrayList<Long>(); // compile error
You can remedy this with wild cards
List<? extends Number> someNumbers = new ArrayList<Long>(); // this works
Please note, that you can not put anything into such a list
someNumbers.add(2L); //compile error
even (and more surprising for many developers):
List<? extends Long> someLongs = new ArrayList<Long>();
someLongs.add(2L); // compile error !!!
I think SO is not the right place to discuss that in detail. I will try to find some of the articles and papers that explain this in more detail.
Binding the type to a type parameter can be more powerful, depending on what the method is supposed to do. I'm not sure what takeThing is supposed to do, but imagine in general we have a method with one of these type signatures:
public <T extends Animal> void foo(ArrayList<T> list);
//or
public void foo(ArrayList<? extends Animal> list);
Here's a concrete example of something you can only do with the first type signature:
public <T extends Animal> void foo(ArrayList<T> list) {
list.add(list.remove(0)); // (cycle front element to the back)
}
In this case T is required to inform the type checker that the element being removed from the list is an OK element to add to the list.
You could not do this with a wildcard because, as the wildcard has not been bound to a type parameter, its context is not tracked (well, it is tracked, through "captures", but it's not available to leverage). You can get more information on this in another answer I've given: How do generics of generics work?
If you write ? extends T you say "anything that is a T or more specific". For example: a List<Shape> can have only Shapes in it, while a List<? extends Shape> can have Shapes, Circles, Rectangles, etc.
If you write ? super T you say "anything that is a T or more general". This is less often used, but has it's use cases. A typical example would be a callback: if you want to pass a Rectangle back to a callback, you can use Callback<? super Rectangle>, since a Callback<Shape> will be able to handle Rectangles as well.
Here's the relevant Wikipedia article.
If your takeThing method needs to add elements to the list parameter, the wildcard version will not compile.
The interesting case is when you are not adding to the list and both versions seem to compile and work.
In this case, you would write the wildcard version when you want to allow different type of animals in the list (more flexibility) and the parameter version when you require a fixed type of animal in the list: the T type.
For example the java.util.Collection declares:
interface Collection<E> {
...
public boolean containsAll(Collection<?> c);
...
}
And suppose you have the following code:
Collection<Object> c = Arrays.<Object>asList(1, 2);
Collection<Integer> i = Arrays.<Integer>asList(1, 2, 3);
i.containsAll(c); //compiles and return true as expected
If the java.util.Collection would be:
interface Collection<E> {
...
public boolean containsAll(Collection<E> c);
...
}
The above test code would not compile and the flexibility of the Collection API would be reduced.
It worth noting that the latter definition of containsAll has the advantage of catching more errors at compile time, for example:
Collection<String> c = Arrays.asList("1", "2");
Collection<Integer> i = Arrays.asList(1, 2, 3);
i.containsAll(c); //does not compile, the integer collection can't contain strings
But misses the valid test with a Collection<Object> c = Arrays.<Object>asList(1, 2);
Java Generics Wildcards usage is governed by the GET-PUT Principle (Which is also known as the IN-OUT principle). This states that:
Use an "extends" wildcard when you only get values out of a structure, Use a "super" wildcard when you only put values into a structure, and do not use wildcards when you do both. This does not apply to a method's return type. Do not use a wildcard as a return type. See example below:
public static<T> void copyContainerDataValues(Container<? extends T> source, Container<? super T> destinationtion){
destination.put(source.get());
}

Can all wildcards in Java be replaced by non-wildcard types?

I can't find any example where wildcards can't be replaced by a generic.
For example:
public void dummy(List<? extends MyObject> list);
is equivalent to
public <T> void dummy(List<T extends MyObject> list);
or
public <T> List<? extends T> dummy2(List<? extends T> list);
is equivalent to
public <T, U> List<U extends T> dummy(List<U extends T> list);
So I don't undertand why wildcard was created as generics is already doing the job. Any ideas or comments?
Nope, it is not always replaceable.
List<? extends Reader> foo();
is not equivalent to
<T> List<T extends Reader> foo();
because you don't know the T when calling foo() (and you cannot know what List<T> will foo() return. The same thing happens in your second example, too.
The demonstration of using wildcards can be found in this (my) answer.
An easy answer is that, deeper level wildcards can't be replaced by a type variable
void foo( List<List<?>> arg )
is very different from
<T>
void foo( List<List<T>> arg)
This is because wildcard capture conversion is only applied to 1st level wildcards. Let's talk about these.
Due to extensive capture conversion, in most places, compiler treats wildcards as if they are type variables. Therefore indeed programmer can replace wildcard with type variables in such places, a sort of manual capture conversion.
Since a type variable created by compiler for capture conversion is not accessible to programmer, this has the restricting effect mentioned by #josefx. For example, compiler treats a List<?> object as a List<W> object; since W is internal to compiler, although it has a method add(W item), there's no way for programmer to invoke it, because he has no item of type W. However, if programmer "manually" converts the wildcard to a type variable T, he can have an item with type T and invoke add(T item) on it.
Another rather random case where wildcard can't be replaced type variable:
class Base
List<? extends Number> foo()
class Derived extends Base
List<Integer> foo()
Here, foo() is overriden with a covariant return type, since List<Integer> is a subtype of List<? extends Number. This won't work if the wildcard is replaced with type variable.
There is a usage difference for your examples.
public <T> List<? extends T> dummy2(List<? extends T> list);
returns a list that can contain an unknown subtype of T so you can get objects of type T out of it but can't add to it.
Example T = Number
List<? extends Number> l = new ArrayList<Integer>(Arrays.asList(new Integer(1)));
//Valid since the values are guaranteed to be a subtype of Number
Number o = l.get(0);
//Invalid since we don't know that the valuetype of the list is Integer
l.add(new Integer(1));
So the wildcard can be used to make some operations invalid, this can be used by an API to restrict an interface.
Example:
//Use to remove unliked numbers, thanks to the wildcard
//it is impossible to add a Number
#Override public void removeNumberCallback(List<? extends Number> list){
list.remove(13);
}

Categories

Resources