class Employee<T extends Number> { // valid
}
class Employee<? extends Number> { // invalid
}
private static void test(List<? super Number> list1) { // valid
}
private static <T>void test(List<T super Number> list1) { // invalid
}
what exactly is difference between ? and T and when to use what?
Why with class definition, ? doesn't work but it works with List and why T works with class definition but not with List?
Where to declare a generic
You can not use a generic type token
Tbefore introducing it.In your method example you try to declare the
Tat the wrong spot, that is invalid syntax. You have to introduce it beforehand.For the class example however, you have put it in the right spot.
Here is where you can introduce your generic type token on a class wide level:
and thats how you do it for a method only:
Bounded generics
In both cases you can bound your
T, likeT extends Numberand then use it accordingly:After you have introduced your
T, you will use it just like that. SoList<T>, as an example.Note that
T super Numberis invalid on as it makes little sense and does not provide more information than justTorNumberor simplyObject, depending on what you are trying to achieve. You can read more about that at Java generic methods: super can't be used?Wildcards
Wildcards are a different thing. They are not a generic type token that you have to introduce first, such as
T. Instead, they clarify the type range you want to accept.For example a method like
can be called with a
List<Dog>, aList<Animal>or even aList<Object>. We call such a list a consumer ofDogs. To be precise, these are all lists that would accept a dog, solist.add(new Dog())will work.On the other side, we have
which can be called with a
List<Dog>or also aList<Chihuahua>. We call such a list a producer (or provider) ofDogs. To be precise, these are all lists that can provide dogs. SoDog dog = list.get(0)will work.You can read more about the details of what wildcards are and how they work at What is PECS (Producer Extends Consumer Super)?
When to use which?
In general, you would use a generic type token
Twhen you actually still need to maintain the type safety throughout your code. I.e. when you need to be able to give the type a name. Otherwise you use wildcards?.For example, suppose you want to create a method that takes in a list and an element to add to it:
You need to introduce the
Tto ensure that the type of the list matches the given element. Otherwise someone could doaddToList(dogs, cat), which you do not want.If you do not have the need to actually name the type, you can also just use a wildcard. For example a method that takes a list and prints all its contents: