Java 泛型中的“ super”和“ tended”的区别是什么

我正在努力学习 Java 泛型。我不清楚你什么时候会使用 <T extends Foo>和你什么时候会使用 <T super Foo>。这些东西对 T 来说意味着什么?假设我有 <T extends Comparable><T super Comparable>,它们分别是什么意思?

我已经在 sun.com 上读了几篇教程,但是我还是不明白。谁能举个例子说明一下?

42967 次浏览

It depends which way on the inheritance hierarchy it allows. Assume you have a class "Child" which inherits from "Parent" which inherits from "Grandparent".

<T extends Parent> accepts either Parent or Child while <T super Parent> accepts either Parent or Grandparent.

There are three types of wildcards:

  • ? extends Type: Denotes a family of subtypes of type Type. This is the most useful wildcard.
  • ? super Type: Denotes a family of supertypes of type Type.
  • ?: Denotes the set of all types or any.

If you are asking about type parameters, then there is no <T super X> construct in Java. Bounded parameter can only extend, but it can extend more than one type. E.g

public class MyClass< T extends Closeable & Runnable >
{
// Closeable and Runnable are chosen for demonstration purposes only
}

In this case if you see MyClass< ConcreteT > then ConcreteT must be declared as

public class ConcreteT
implements Closeable, Runnable
{
...
}

For bounded wildcards, read this article. Read section on get-put principle. Basically, super corresponds to write semantics, and extends corresponds to read semantics.

See Effective Java 2nd Edition, Item 28:

PECS

Producer extends, Consumer super

If your parameter is a producer, it should be <? extends T>, if it's a consumer it has to be <? super T>.

Take a look at the Google Collections, they know how to use it, because they got Bloch ;)

Remember PECS - Producer Extends Consumer Support. Also, uncle Bob discusses it well in his craftsman series. Check out http://objectmentor.com/resources/articles/The_Craftsman_44__Brown_Bag_I.pdf

For me the best answer came from @BSingh, when i read the article of Uncle Bob. I resume here, the conclusion of article.

Use List< T super Suit> whenever you are going to write into the list.

When you put an Object to the List, all you care about is that the object is of a type that is compatible with type held by the list. So you want the list to take the type of that object or any of the superclasses of that object.

Use List< T extends Suit> whenever you are going to read from a list.

On the other hand, when you read from a list, you want the type you are reading to be the type contained byt the list, or a derivative from that type.