As far as I know, using an upper bounded generic and using a superclass as a method parameter both accept the same possible arguments. Which is preferred, and what's the difference between the two, if any?
Upper bounded generic as parameter:
public <T extends Foo> void doSomething(T foo) {}
Superclass as parameter:
public void doSomething(Foo foo) {}
That's an upper bounded type parameter. Lower bounds are created using super, which you can't really do for a type parameter. You can't have a lower bounded type parameter.
And that would make a difference, if you, for example want to pass a List<T>. So, for the below two methods:
public <T extends Foo> void doSomething(List<T> foos) {}
public void doSomething(List<Foo> foo) {}
And for the given class:
class Bar extends Foo { }
The following method invocation:
List<Bar> list = new ArrayList<Bar>();
doSomething(list);
is valid for 1st method, but not for 2nd method. 2nd method fails because a List<Foo> is not a super type of List<Bar>, although Foo is super type of Bar. However, 1st method passes, because there the type parameter T will be inferred as Bar.
Generally, you only need a type variable when it's used in more than one place in class/method/field declarations. When you declare one on a method (rather than a class), the only places to use it are on the parameters and return value of that method.
For example, you can use it on multiple parameters to ensure their types match:
public static <T> void addToList(List<T> list, T element) {
list.add(element);
}
This is a trivial example, but you can see that it prevents you from giving it an element that doesn't match the list's generic type:
List<Integer> list = new ArrayList<>();
addToList(list, 7);
//addToList(list, 0.7); // doesn't compile
//addToList(list, "a"); // doesn't compile
You can also declare a parameter and the return type to be the same type:
public static <T> T nullCheck(T value, T defValue) {
return value != null ? value : defValue;
}
Since this method is returning one of the two T objects it's given, we can safely say that the returned object is also of type T.
Integer iN = null;
Integer i = nullCheck(iN, 7);
System.out.println(i); // "7"
Double dN = null;
Double d = nullCheck(dN, 0.7);
System.out.println(d); // "0.7"
Number n = nullCheck(i, d); // T = superclass of Integer and Double
System.out.println(n); // "7"
As for the example in the question, the type variable is only being used once, so it's equivalent to using the superclass. In this case you should avoid declaring a type variable, it's just unnecessary clutter.
Also I should note that the other answer changes the example to use List<T> and List<Foo>, but as mentioned in the comments, the superclass is really List<? extends Foo>, so no type variable is needed there, either.
Related
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) {
}
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) {
}
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
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.
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.
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.
I usually explain the difference between <E> and <?> by a comparison with logical quantifications, that is, universal quantification and existential quantification.
corresponds to "forall E, ..."
corresponds to "there exists something(denoted by ) such that ...."
Therefore, the following generic method declaration means that, for all class type E, we define funct1
public static <E> void funct1 (List<E>; list1) {
}
The following generic method declaration means that, for some existing class denoted by <?>, we define funct2.
public static void funct2(List<?> list) {
}
(Since your edit) Those two function signatures have the same effect to outside code -- they both take any List as argument. A wildcard is equivalent to a type parameter that is used only once.
In addition to those differences mentioned before, there is also an additional difference: You can explicitly set the type arguments for the call of the generic method:
List<Apple> apples = ...
ClassName.<Banana>funct2(apples); // for some reason the compiler seems to be ok
// with type parameters, even though the method has none
ClassName.<Banana>funct1(apples); // compiler error: incompatible types: List<Apple>
// cannot be converted to List<Banana>
(ClassName is the name of the class containing the methods.)
In this context, both wild card (?) and type parameter (E) will do the same for you. There are certain edges based on the use cases.
Let's say if you want to have a method which may have more than one params like:
public void function1(ArrayList<?> a, ArrayList<?> b){
// some process
}
public <T> void function2(ArrayList<T> a, ArrayList<T> b){
// some process
}
in function1 a can be AL of String and b can be AL of the Integer so it is not possible to control the type of both the params but this is easy for the function2.
We should use the Type Params (function 2) if we want to use the type later in the method or class
There are some features in WildCard and Type param:
WildCard(?)
It support the upper and lower bound in the type while the Type param (E) supports only upper bound.
Type Param(E)
SomeTime we do not need to pass the actual type ex:
ArrayList<Integer> ai = new ArrayList<Integer>();
ArrayList<Double> ad = new ArrayList<Double>();
function2(ai, ad);
//It will compile and the T will be Number.
In this case, the compiler infers the type argument for us based on the type of actual arguments
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) {
}
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
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.
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.
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.
I usually explain the difference between <E> and <?> by a comparison with logical quantifications, that is, universal quantification and existential quantification.
corresponds to "forall E, ..."
corresponds to "there exists something(denoted by ) such that ...."
Therefore, the following generic method declaration means that, for all class type E, we define funct1
public static <E> void funct1 (List<E>; list1) {
}
The following generic method declaration means that, for some existing class denoted by <?>, we define funct2.
public static void funct2(List<?> list) {
}
(Since your edit) Those two function signatures have the same effect to outside code -- they both take any List as argument. A wildcard is equivalent to a type parameter that is used only once.
In addition to those differences mentioned before, there is also an additional difference: You can explicitly set the type arguments for the call of the generic method:
List<Apple> apples = ...
ClassName.<Banana>funct2(apples); // for some reason the compiler seems to be ok
// with type parameters, even though the method has none
ClassName.<Banana>funct1(apples); // compiler error: incompatible types: List<Apple>
// cannot be converted to List<Banana>
(ClassName is the name of the class containing the methods.)
In this context, both wild card (?) and type parameter (E) will do the same for you. There are certain edges based on the use cases.
Let's say if you want to have a method which may have more than one params like:
public void function1(ArrayList<?> a, ArrayList<?> b){
// some process
}
public <T> void function2(ArrayList<T> a, ArrayList<T> b){
// some process
}
in function1 a can be AL of String and b can be AL of the Integer so it is not possible to control the type of both the params but this is easy for the function2.
We should use the Type Params (function 2) if we want to use the type later in the method or class
There are some features in WildCard and Type param:
WildCard(?)
It support the upper and lower bound in the type while the Type param (E) supports only upper bound.
Type Param(E)
SomeTime we do not need to pass the actual type ex:
ArrayList<Integer> ai = new ArrayList<Integer>();
ArrayList<Double> ad = new ArrayList<Double>();
function2(ai, ad);
//It will compile and the T will be Number.
In this case, the compiler infers the type argument for us based on the type of actual arguments
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.
For a generic interface:
public interface Foo<T> {
void f(T t);
}
The difference between the two fields:
public class Bar {
Foo foo1;
Foo<?> foo2;
}
Is that foo2 is a generic Type and foois not. Since ? is a wildcard (which I think means any type) and every type is a sub-type of Object, then I wold expect Foo<?> and Foo<Object> to semantically and syntactically equivalent.
However, check out the following:
public class Puzzler {
void f() {
Integer i = null;
Foo<?> foo1 = null;
foo1.foo(i); // ERROR
Foo foo2 = null;
foo2.foo(i); // OKAY
Foo<Integer> foo3 = null;
foo3.foo(i); // OKAY
Foo<Object> foo4 = null;
foo4.foo(i); // OKAY
}
private interface Foo<T> {
void foo(T t);
}
}
So Foo<?> and Foo<Object> are not the same syntactically.
What's going on here? I'm pretty stuck in trying to understand this.
Foo<?> is semantically the same as Foo<? extends Object>: it is a Foo with type parameter of something specific, but the only thing known about "something" is that it is some subclass of Object (which isn't saying too much, since all classes are subclasses of Object). Foo<Object>, on the other hand, is a Foo with type parameter specifically Object. While everything is assignment-compatible with Object, not everything will be assignment-compatible with ? where ? extends Object.
Here's an example of why Foo<?> should generate an error:
public class StringFoo implements Foo<String> {
void foo(String t) { . . . }
}
Now change your example to this:
Foo<?> foo1 = new StringFoo();
Since i is an Integer, there's no way that the compiler should allow foo1.foo(i) to compile.
Note that
Foo<Object> foo4 = new StringFoo();
will also not compile according to the rules for matching parameterized types since Object and String are provably distinct types.
Foo (without type parameter at all—a raw type) should usually be considered a programming error. According to the Java Language Specification (§4.8), however, the compiler accepts such code in order to not break non-generic, legacy code.
Because of type erasure, none of this makes any difference to generated the byte code. That is, the only differences between these are at compile time.
Consider these types:
List<Object>
List<CharSequence>
List<String>
Even though String is a subtype of CharSequence which is a subtype of Object, these List types do not have any subtype-supertype relationships. (Curiously, String[] is a subtype of CharSequence[] which is a subtype of Object[], but that's for historical reasons.)
Suppose we want to write a method which prints a List. If we do
void print(List<Object> list) {...}
this will not be able to print a List<String> (without hacks), since a List<String> is not a List<Object>. But with wildcards, we can write
void print(List<?> list) {...}
and pass it any List.
Wildcards can have upper and lower bounds for added flexibility. Say we want to print a list which contains only CharSequences. If we do
void print(List<CharSequence> list) {...}
then we encounter the same problem -- we can only pass it a List<CharSequence>, and our List<String> is not a List<CharSequence>. But if we instead do
void print(List<? extends CharSequence> list) {...}
Then we can pass this a List<String>, and a List<StringBuilder>, and so forth.
Well, due to the type erasure, anything generics-related is compile-time only; I guess that's what you are calling syntactical.
I think your initial assessment is correct and real difference is that makes it a generic-typed variable and plain Foo doesn't.
Object is the supertype of all types in java. However, Foo is not the supertype of all Foo. The supertype of all Foo is Foo. see http://docs.oracle.com/javase/tutorial/extra/generics/wildcards.html for more details.
The wildcard in Foo<?> indicates that within the current scope, you don't know or care what type of 'Foo' you have.
Foo<?> and Foo<? extends Object> are the same (the first is shorthand for the other). Foo<Object> is different.
A concrete example:
You can assign any sort of List to List<?>
e.g.
List<?> list1 = new ArrayList<String>();
List<?> list2 = new ArrayList<Object>();
List<?> list3 = new ArrayList<CharSequence>();
If you have a List<?> you can call size() because you don't need to know what type of list it is to find out its size. And you can call get(i) because we know that the list contains some sort of Object, so the compiler will treat it as if get returns and Object.
But you can't call add(o) because you don't know (and the compiler doesn't know) what sort of list you're dealing with.
In our example above you wouldn't want to allow list1.add(new Object()); because that's supposed to be a list of Strings
The reason for wildcards is so you can do things like this:
public static boolean containsNull(List<?> list)
{
for(Object o : list )
{
if( o == null ) return true;
}
return false;
}
That code can work on any sort of list that you want, a List<String>, List<Object>, List<Integer>, etc.
If the signature was public static boolean containsNull(List<Object> list) then you could only pass List<Object> to it, List<String> wouldn't work.