Java泛型下限使用:?超级T

On Java generics lower bound usage: ? super T

本问题已经有最佳答案,请猛点这里访问。

我试图在一定程度上理解下限通配符的用法。我正在尝试编写一个通用方法copy,它将一个List的内容复制到另一个List的内容。我想出了这个方法签名:

1
<T> void copy(List<T> dest, List<? extends T> src)

我认为这个签名是全面的,可以解决所有的情况。但是,我发现在Java集合类中,方法签名是这样的:

1
<T> void copy(List<? super T> dest, List<? extends T> src)

我不明白他们为什么用List dest而不仅仅是List dest。他们的签名是否有一些额外的灵活性?


如果没有明确的类型见证,就没有实际的区别。

如果不象ERAN那样指定类型见证,两种方法之间的灵活性就没有区别。

从本质上讲,使用? super T而不是T只是一种风格上的差异,但是它是更好的实践,可以通过应用一些良好代码的原则来看到:

  • 明确的意图:? super T更明确地显示了dest应该采用什么类型。
  • 模块化:您根本不需要查看src上的类型约束就可以知道dest可以采用什么类型。
  • producer extends,consumer super(pecs):producer参数(以下简称"in")应使用extends,consumer参数(以下简称"out")应使用super关键字。

使用EDCOX1,2,也被Java教程推荐(他们甚至使用EDCOX1 11函数):

For purposes of this discussion, it is helpful to think of variables as providing one of two functions:

An"In" Variable
An"in" variable serves up data to the code. Imagine a copy method with two arguments: copy(src, dest). The src argument provides the data to be copied, so it is the"in" parameter.

An"Out" Variable
An"out" variable holds data for use elsewhere. In the copy example, copy(src, dest), the dest argument accepts data, so it is the"out" parameter.

You can use the"in" and"out" principle when deciding whether to use a wildcard and what type of wildcard is appropriate. The following list provides the guidelines to follow:

Wildcard Guidelines:

  • An"in" variable is defined with an upper bounded wildcard, using the
    extends keyword.
  • An"out" variable is defined with a lower bounded
    wildcard, using the super keyword.


下面是一个例子:

以下代码段通过签名为 void copy(List dest, List src)的编译,但不适用于签名为 void copy(List dest, List src)的编译:

1
2
3
4
YourClass obj = new YourClass ();
List<HashMap<String,String>> lhm = new ArrayList<>();
List<Map<String,String>> lm = new ArrayList<>();
obj.<HashMap<String,String>>copy (lm,lhm);