What is the meaning of the <?> token in this code copied from www.JavaPractices.com? When I replace it with the more conventional looking <T> used for generic types, it fails to compile. (Error: T cannot be resolved to a type.) Why?
// <?> occurs 3 times in the entire program. When it is replaced with <T> the
// program no longer compiles.
void activateAlarmThenStop()
{
Runnable myPeriodicTask = new PeriodicTask();
ScheduledFuture<?> soundAlarmFuture =
this.executorService.scheduleWithFixedDelay(myPeriodicTask,
startT,
period,
TimeUnit.SECONDS
);
Runnable stopAlarm = new StopAlarmTask(soundAlarmFuture);
this.executorService.schedule(stopAlarm, stopT, TimeUnit.SECONDS);
}
private final class StopAlarmTask implements Runnable
{
StopAlarmTask(ScheduledFuture<?> aSchedFuture)
{
fSchedFuture = aSchedFuture;
}
public void run()
{
CConsole.pw.println("Stopping alarm.");
fSchedFuture.cancel(doNotInterruptIfRunningFlag);
executorService.shutdown();
}
private ScheduledFuture<?> fSchedFuture;
}
Edit: Of course when we use generic type tokens like <T>, it has to appear in the class declaration. Here there is no <T> nor <?> in the class declaration but it still compiles and runs properly.
It fails to compile, because your class is not generic (nor any of your methods). In this particular example joker (?) means that ScheduledFuture may be parametrized by anything.
Sometimes, there is no sense to make the whole class generic if you use another generic class inside and you don't know the exact type that will be used.
In this example you had three options:
make StopAlarmTask generic (there is no sense in this case)
use concrete type in ScheduledFuture, but then it would be only one possible result type, for example String or Integer
use wildcard (< ? >) - it allows to retrieve anything as a result of FutureResult (String, Integer, your custom class). You can also narrow the scope of a possible generic type into some subclasses, for example ScheduledGeneric< ? extends MyObject > or into superclasses: ScheduledGeneric< ? super MyObject >
This is an example of using wildcard in a type argument. i.e. a generic type.
A wildcard parameterized type is an instantiation of a generic type where at least one type argument is a wildcard. Examples of wildcard parameterized types are Collection<?> , List<? extends Number> , Comparator<? super String> and Pair<String,?> .
A wildcard parameterized type denotes a family of types comprising concrete instantiations of a generic type. The kind of the wildcard being used determines which concrete parameterized types belong to the family.
Assuming this.executorService is a subtype of ScheduledExecutorService (available since Java 1.5), the return type of scheduleWithFixedDelay() is ScheduledFuture<?>. You can't change the return type from ScheduledFuture<?> to ScheduledFuture<T>, ScheduledFuture<Integer> or anything else for that matter. You could, however, change it to just ScheduledFuture since <?> is a wildcard generic type parameter that approximates a raw type for backward compatibility.
See What is a raw type and why shouldn't we use it? for a good discussion on raw types and generics.
That is Generic Type... usually we set String, Object, or any other objects as generic types... but here they make it general. and generic type stands for the value it can store or hold. its generally used in Collections..
well there is no much diff between the both.. - takes all kind of objects
<T>-is also called `formal type parameter` makes use of what ever type of object you pass in .. for instance you can do this with <T> and not with <?>
public class Box<T> {
private T t; // T stands for "Type"
public void add(T t) {
this.t = t;
}
public T get() {
return t;
}
}
for more see http://java.sun.com/j2se/1.5/pdf/generics-tutorial.pdf and http://download.oracle.com/javase/tutorial/java/generics/gentypes.html
A letter in brackets like <T> would be a type parameter. You would say class StopAlarmTask<T> to mean that you are parameterizing the type StopAlarmTask with the type T. The type parameter T would become a part of the type, sort of like a constructor argument becomes part of a new instance.
Then, whenever you declared a StopAlarmTask, you would provide a type, e.g. String, to fill in the type parameter T. You could then refer to that type parameter within the class body. For example, you could define methods which take a T or return a T, or parameterize member variables like fSchedFuture with T. For example, if you parameterized a declaration of StopAlarmTask<T> as StopAlarmTask<String>, then String would be captured as T and wherever you used T within that StopAlarmTask it would act as String.
However, in the code you have listed, StopAlarmTask does not have a type parameter and cannot be parameterized with any type. There is no captured type to refer to as T within the class body.
On the other hand, <?> means "I don't know which type it will be; I don't even know that it will be the type that someone has used to parameterize StopAlarmTask."
You could have parameterized StopAlarmTask<T>, and in that case you could have two variables:
private ScheduledFuture<T> fSchedFuture1;
private ScheduledFuture<?> fSchedFuture2;
The first declaration says that the type parameter of the ScheduledFuture is the same as the type parameter of the enclosing StopAlarmTask. E.g. StopAlarmTask<String> would make fSchedFuture1 into a ScheduledFuture<String>. The second declaration says that we don't know what the type parameter of the ScheduledFuture is, even if we know the type parameter of the enclosing StopAlarmTask.
The joker ? can hold any type. If you want to use the same type for all methods/members you can make the whole class generic. By writing StopAlarmTask<T> you define the type T in the whole class.
private final class StopAlarmTask<T> implements Runnable
{
StopAlarmTask(ScheduledFuture<T> aSchedFuture)
{
fSchedFuture = aSchedFuture;
}
public void run()
{ /* */ }
private ScheduledFuture<T> fSchedFuture;
}
It can take any parameter like Object,String,Integer.... and so on
Now when you plan to use generics then you have to provide the type inside the angel bracket.
EDIT:
<?> is strictly appliable to Collections.
<T> used as type or template for your normal class
StopAlarmTask is not a generic type.
In the following example, you would not think Foo is a generic type.
class Foo
{
Foo(int i)
{ }
doStuff(List<Integer> numbers)
{ }
}
The fact that the constructor of StopAlarmTask uses a generic parameter does not make the class generic any more than doStuff() makes Foo generic.
Use <?> to "refer to" the the declaration of a generic type in a generic way, that is, without specificity. In StopAlarmTask it just happens to be a constructor parameter. It is an "employment of" a generic type and not a declaration of a generic type because it is "merely" a parameter declaration.
In other words, the short answer is that the parameter in the method
StopAlarmTask(ScheduledFuture<?> aSchedFuture)
{ ... }
is applicable for all objects that are instances of ScheduledFuture<T> for all T.
The following is further background on generics.
Use <T> or <E> or whatever to declare the generic type ScheduledFuture<T>. Specifically, <?> would not be used in the declaration of ScheduledFuture<> because the convention is to use a single uppercase letter.
Note that the following test code, if fed to a compiler, will show that the first class compiles but the second does not, so to say that there is a convention to use a letter would actually be an understatement.
class TGeneric1<E> {
List<E> list = new ArrayList<E>();
TGeneric1(E value) {
this.list.add(value);
}
E getHead() {
return this.list.get(0);
}
}
class TGeneric2<?> {
List<?> list = new ArrayList<?>();
TGeneric2(? value) {
this.list.add(value);
}
? getHead() {
return this.list.get(0);
}
}
Illustrated in the following test code, there is no single letter constraint, so the following is also correct.
class TGeneric1<EE> {
List<EE> list = new ArrayList<EE>();
TGeneric1(EE value) {
this.list.add(value);
}
EE getHead() {
return this.list.get(0);
}
}
Related
Background: the question came up in this answer (the first revision of the answer, to be exact). The code presented in this question is reduced to the bare minimum to explain the problem.
Suppose we have the following code:
public class Sample<T extends Sample<T>> {
public static Sample<? extends Sample<?>> get() {
return new Sample<>();
}
public static void main(String... args) {
Sample<? extends Sample<?>> sample = Sample.get();
}
}
It compiles without warning and executes fine. However, if one tries to somehow define the inferred type of return new Sample<>(); in get() explicitly the compiler complains.
Up until now, I was under the impression that the diamond operator is just some syntactic sugar to not write explicit types and thus could always be replaced with some explicit type. For the given example, I was not able to define any explicit type for the return value to make the code compile. Is it possible to explicitly define the generic type of the return value or is the diamond-operator needed in this case?
Below are some attempts I made to explicitly define the generic type of the returned value with the corresponding compiler errors.
return new Sample<Sample> results in:
Sample.java:6: error: type argument Sample is not within bounds of type-variable T
return new Sample<Sample>();
^
where T is a type-variable:
T extends Sample<T> declared in class Sample
Sample.java:6: error: incompatible types: Sample<Sample> cannot be converted to Sample<? extends Sample<?>>
return new Sample<Sample>();
^
return new Sample<Sample<?>> results in:
Sample.java:6: error: type argument Sample<?> is not within bounds of type-variable T
return new Sample<Sample<?>>();
^
where T is a type-variable:
T extends Sample<T> declared in class Sample
return new Sample<Sample<>>(); results in:
Sample.java:6: error: illegal start of type
return new Sample<Sample<>>();
^
The JLS simply says:
If the type argument list to the class is empty — the diamond form <> — the type arguments of the class are inferred.
So, is there some inferred X that will satisfy the solution? Yes.
Of course, for you to explicitly define such an X, you'd have to declare it:
public static <X extends Sample<X>> Sample<? extends Sample<?>> get() {
return new Sample<X>();
}
The explicit Sample<X> is compatible with the return type Sample<? extends Sample<?>>, so compiler is happy.
The fact that return type is a messed up Sample<? extends Sample<?>> is an entirely different story.
Instantiating Generics with Wildcards
There's a couple problems here, but before delving into them, let me address your actual question:
Is it possible to explicitly define the generic type of the return value or is the diamond-operator needed in this case?
It is not possible to explicitly instantiate a Sample<? extends Sample<?>> (or a Sample<?> for that matter). Wildcards may not be used as type arguments when instantiating a generic type, though they may be nested within type arguments. For example, while it is legal to instantiate an ArrayList<Sample<?>>, you cannot instantiate an ArrayList<?>.
The most obvious workaround would be to simply return some other concrete type that is assignable to Sample<?>. For example:
class Sample<T extends Sample<T>> {
static class X extends Sample<X> {}
public static Sample<? extends Sample<?>> get() {
return new X();
}
}
However, if you specifically want to return a generic instantiation of the Sample<> class containing wildcards, then you must rely on generic inference to work out the type arguments for you. There are a few ways to go about this, but it usually involves one of the following:
Using the diamond operator, as you are doing right now.
Delegating to a generic method that captures your wildcard with a type variable.
While you cannot include a wildcard directly in a generic instantiation, it's perfectly legal to include a type variable, and that's what makes option (2) possible. All we have to do is ensure that the type variable in the delegate method gets bound to a wildcard at the call site. Every mention of the type variable the method's signature and body then gets replaced with a reference to that wildcard. For example:
public class Sample<T extends Sample<T>> {
public static Sample<? extends Sample<?>> get() {
final Sample<?> s = get0();
return s;
}
private static <T extends Sample<T>> Sample<T> get0() {
return new Sample<T>();
}
}
Here, the return type of Sample<T> get0() gets expanded to Sample<WC#1 extends Sample<WC#1>>, where WC#1 represents a captured copy of the wildcard inferred from the assignment target in Sample<?> s = get0().
Multiple Wildcards in a Type Signature
Now, let's address that method signature of yours. It's hard to tell for sure based on what code you've provided, but I would guess that a return type of Sample<? extends Sample<?>> is *not* what you really want. When wildcards appear in a type, each wildcard is distinct from all others. There is no enforcement that the first wildcard and second wildcard refer to the same type.
Let's say get() returns a value of type X. If it was your intention to ensure that X extends Sample<X>, then you have failed. Consider:
class Sample<T extends Sample<T>> {
static class X extends Sample<X> {}
static class Y extends Sample<X> {}
public static Sample<? extends Sample<?>> get() {
return new Y();
}
public static void main(String... args) {
Sample<?> s = Sample.get(); // legal (!)
}
}
In main, variable s holds a value that is a Sample<X> and a Y, but not a Sample<Y>. Is that what you'd intended? If not, I suggest replacing the wildcard in your method signature with a type variable, then letting the caller decide the type argument:
class Sample<T extends Sample<T>> {
static class X extends Sample<X> {}
static class Y extends Sample<X> {}
public static <T extends Sample<T>> Sample<T> get() { /* ... */ }
public static void main(String... args) {
Sample<X> x = Sample.get(); // legal
Sample<Y> y = Sample.get(); // NOT legal
Sample<?> ww = Sample.get(); // legal
Sample<?> wx = Sample.<X>get(); // legal
Sample<?> wy = Sample.<Y>get(); // NOT legal
}
}
The version above effectively guarantees that, for some return value of type A, the returned value extends Sample<A>. In theory, it even works when T is bound to a wildcard. Why? It goes back to wildcard capture:
In your original get method, the two wildcards could end up referring to different types. In effect, your return type was Sample<WC#1 extends Sample<WC#2>, where WC#1 and WC#2 are separate wildcards that are not related in any way. But in the example above, binding T to a wildcard captures it, allowing the same wildcard to appear in more than one spot. Thus, when T is bound to a wildcard WC#1, the return type expands to Sample<WC#1 extends Sample<WC#1>. Remember, there is no way to express that type directly in Java: it can only be done by relying on type inference.
Now, I said this works with wildcards in theory. In practice, you probably won't be able to implement get in such a way that the generic constraints are runtime-enforceable. That's because of type erasure: the compiler can emit a classcast instruction to verify that the returned value is, for example, both an X and a Sample, but it cannot verify that it's actually a Sample<X>, because all generic forms of Sample have the same runtime type. For concrete type arguments, the compiler can usually prevent suspect code from compiling, but when you throw wildcards into the mix, complex generic constraints become difficult or impossible to enforce. Buyer beware :).
Aside
If all this is confusing to you, don't fret: wildcards and wildcard capture are among the most difficult aspects of Java generics to understand. It's also not clear whether understanding these will actually help you with your immediate goal. If you have an API in mind, it might be best to submit it to the Code Review stack exchange and see what kind of feedback you get.
I'm confused about type parameter.In the following code, types inside CollectionData angle bracket can be called type parameter. Types inside ArrayList and Generator are not type parameter and should be the same in CollectionData. How to understand it?
//correct
public class CollectionData<T> extends ArrayList<T> {
CollectionData(Generator<T> generator) {
}
}
interface Generator<E> {
E next();
}
Following is wrong. But I can't helping writing this sometimes.
// wrong
public class CollectionData<T> extends ArrayList<E> {
CollectionData(Generator<W> generator) {
}
}
interface Generator<E> {
E next();
}
Added: In the example above, can type variables be only defined in angle bracket of CollectionData, rather than ArrayList or Generator ? Then ArrayList and CollectionData use these types. Right?
These generic types are just type variables.
Writing
public class CollectionData<T> extends ArrayList<E> {
is similar to writing
public int func(int x) {
return y;
}
If there is no variable y, then this code is wrong.
But because you declared x, you can use x where appropriate:
public int func(int x) {
return x;
}
The same is true for generic types.
When you write
public class CollectionData<T> extends ArrayList<T>
you are saying that the T inside ArrayList<T> is the identical T as given by the generic type argument to your class.
The same is true for the constructors's parameter type.
So, to help you knowing when to write the "correct" code: if you require that both generic types are the same (e.g. the generic type given to your class, and the generic type of your base class or a function's argument), then you have to use the same type variable.
This is the same as you would use the same variable inside a function when you need the exact value that is stored in that variable.
Edit for your addendum:
The generic types can only be declared on the class name:
public class CollectionData<T> extends ArrayList<E>
Declares T, but only uses E. This, of course, requires that E has been declared as a generic type (or class, for the fact) somewhere. (When E is a generic type, this should only be valid when CollectionData<T> is inside an outer class which declares E.)
Of course, generic types can also be declared for every function:
public <T> void foo(T x) { x.baz(); }
This declares T and shadows any definition of T.
For example, in this context
public class Foo<T> {
public <T> void foo(T x) { x.baz(); }
}
The T inside the foo method is not the T declared by the class Foo.
This works—again—like shadowing variables:
public class Foo {
int x;
public int foo(int x) {
// returns x from argument, not the field of the class
return x;
}
}
I will assume that you are trying to fill your CollectionData instances with the content passed-in by the Generator in the constructor.
You need to use the same type parameter when you require a match. In your first example, all of the type parameters in CollectionData are T. Since they have the same identifier, the compiler knows that they must match.
In the second example, you have type parameters T, W and E. This does not work because you cannot necessarily fill a list of E or T with instances of W. The compiler has no way of knowing that the instance types are compatible.
I think what's causing your confision is the difference between defining a generic type and using one.
Defining a generic type is basically like defining a function - you define it's parameters and how it uses it's parameters.
Using a generic type means it has to be fully understandable by the compiler - it cannot depend on a yet to be defined type.
Here, in your example, the definition ends with the word extends. Everything that follows is using generic types and so cannot use types that are not known, except for the type parameters from the definition header. The analogy to function definitions should help clear the confusion.
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