18

I am a new java learner. Recently I was reading Generic programming and got my self confused with this...

A<T extends B> and A<? extends B>
Zach Langley
  • 6,776
  • 1
  • 26
  • 25
arpanoid
  • 2,123
  • 4
  • 17
  • 15

4 Answers4

19

First of all, those are completely different constructs used in different contexts.

A<T extends B> is a part of generic type declaration such as

public class A<T extends B> { ... }

It declares generic type A with type parameter T, and introduces a bound on T, so that T must be a subtype of B.


A<? extends B> is a parameterized type with wildcard, it can be used in variable and method declarations, etc, as a normal type:

A<? extends B> a = ...;

public void foo(A<? extends B> a) { ... }

Variable declaration such as A<? extends B> a means that type of a is A parameterized with some subtype of B.

For example, given this declaration

List<? extends Number> l;

you can:

  • Assign a List of some subtype of Number to l:

    l = new ArrayList<Integer>(); 
    
  • Get an object of type Number from that list:

    Number n = l.get(0);
    

However, you can't put anything into list l since you don't know actual type parameter of the list:

Double d = ...;
l.add(d); // Won't compile
axtavt
  • 239,438
  • 41
  • 511
  • 482
8

? is what is called a wildcard. It means anything that extends B.

When you write List<T extends String>, your List can contains only elements of type T.

When you write List<? extends String>, your List can contains any element that extends String

I hope I'm clear, since these concepts are complicated.

krtek
  • 26,334
  • 5
  • 56
  • 84
  • 1
    you can't write `List` – newacct Jun 26 '12 at 18:07
  • 1
    also, `When you write List extends String>, your List can contains any element that extends String` is not true. It has a specific type parameter which is unknown – newacct Jun 26 '12 at 18:08
  • Newacct want’s to say that: String is final it means String in java is immutable and can’t be extended. Anyother informations is helpful for us))) – Musa Sep 08 '19 at 16:31
5

Generics is a complicated subject in general, and especially in Java. But basically the difference is:

T extends B

There is a specific type T, it is just limited to being B or a subclass of B, but it is a specific know type. Any plain old generic declaration is like saying: <T extends Object> By saying T extends B, we are saying that T is more limited than any object, it has to specifically be a type of B.

? extends B

This means that the generic type is unknown, exactly, but what we can say about it is that it extends B. It may be B, it may be a subclass of B. With a wildcard and the word extends, it means that you can get B out of the object, but you cannot put anything in the object in a type safe way. (? super B means the opposite - you can put something in a method parameter that is a B or a superclass of B, but you cannot be sure what the return value of a method would be.)

Community
  • 1
  • 1
Yishai
  • 90,445
  • 31
  • 189
  • 263
  • what is a pros from using one over another as in any case we can only invoke methods that are defined in B class(in first case via generic `T` reference and in second case from `B` reference, however in first case we can insert generic `T` reference into the collection)? – maks Dec 06 '12 at 21:12
  • @maks, the point is for cases where you want to take in a type with a generic definition as a parameter. You don't want to be limited to only one type, or one generic parameter, you can be open to a larger range. – Yishai Dec 07 '12 at 04:41
5

(a long comment, not an answer)

Totally different things. The similarity in syntax is a grave mistake made by Java. And this mistake leads to a bigger mistake - many people try to understand wildcard as a type parameter (i.e. wildcard capture)

There was no such thing as A<? extends B> until Java invented it. Until then the syntax used by researchers was A<B+>. Java thought that it is too mysterious for our poor programmers, so it invented that syntax A<? extends B> that seems to read better on first round.

Well it is damn verbose and ugly. If an API has a few wildcard, it looks like vomit of symbols.

But the worse thing is the confusion it causes. It looks like a type parameter. And Java did that on purpose! Java did not believe that its programmers can ever understand covariant types, so syntactically it made the convariant types look like parameterized types, to guide programmers into the erroneous way of understanding, that, admittedly, can be useful in occasions, but ultimately makes people clueless.

irreputable
  • 44,725
  • 9
  • 65
  • 93
  • Interesting. Will like to know more about covariant as you specified `A` *in general as perceived by researchers*, not just in some specific languages say C# variance. (will like any links but need that `A` related ones too) – Mahesha999 Mar 10 '15 at 13:54
  • It seems Java thought many things would be too mysterious for us. like unsigned arithmetics for instance... :( – Matthieu Sep 14 '15 at 10:03