简体   繁体   中英

What is the difference between A<T extends B> and A<? extends B>?

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>

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

? 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> List<? extends String> , your List can contains any element that extends String

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

(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 (ie wildcard capture)

There was no such thing as A<? extends B> 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> 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.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM