类型参数的数据类型如何在协方差和逆变量中确定?

时间:2012-03-23 08:51:39

标签: java generics collections covariance contravariance

我正在阅读书籍Java Generics and Collections作者:Maurice Naftalin,Philip Wadler,在前两章中,我的头脑中充满了怀疑。我无法弄清楚答案。

在电话中:

 public static <T> void copy(List<? super T> dst, List<? extends T> src) {
 for (int i = 0; i < src.size(); i++) {
 dst.set(i, src.get(i));
 }
}


 List<Object> objs = Arrays.<Object>asList(2, 3.14, "four");
 List<Integer> ints = Arrays.asList(5, 6);
 Collections.copy(objs, ints);
 assert objs.toString().equals("[5, 6, four]");

在调用“复制”功能期间:
第一个参数:?=对象
第二个参数:?=整数

但是T的数据类型是什么? jvm如何基于擦除实现来决定?

在书中说:在 Collections.copy(obj,ints)行中,类型参数T被认为是Number。允许调用,因为 objs 具有List&lt; Object&gt;类型,这是List&lt ;?的子类型超级数字&gt; (因为Object是超类所需的数字的超类型)而整数具有类型List&lt; Integer&gt;,这是List&lt ;?的子类型extends Number&gt; (因为Integer是Number的子类型,因为extends通配符需要)。

但是,由于Integer实现了Serializable和Comparable两者,因此扩展Number类的aprt和Object类也是Serializable和Comparable的超类型。

那么为什么不将T视为可序列化或可比较而不是数字,因为替换原则将允许它被采用。

提前谢谢。

3 个答案:

答案 0 :(得分:3)

http://docs.oracle.com/javase/specs/jls/se7/jls7.pdf

从“简单”示例中,JLS表示它选择满足其生成的所有约束的最具体类型。

15.12.2.7根据实际参数推断类型参数

  

超类型约束T:&gt; X暗示解决方案是其中之一   X的超类型。鉴于对T的几个这样的约束,我们可以相交   每个约束所暗示的超类型集合,因为   type参数必须是所有这些的成员。然后我们可以选择   交叉点中最具体的类型

Copy.java:11: incompatible types
found   : java.lang.Integer[]
required: java.lang.String[]
    String[] res = copy(Arrays.<Object>asList(2, 3.14, "four"), Arrays.asList(5, 6));
                       ^
1 error
➜  /tmp  cat Copy.java 
import java.util.*;
public class Copy {
public static <T> T[] copy(List<? super T> dst, List<? extends T> src) {
   for (int i = 0; i < src.size(); i++) {
      dst.set(i, src.get(i));
   }

   return null;
  }
  public static void main(String[] args) {
    String[] res = copy(Arrays.<Object>asList(2, 3.14, "four"), Arrays.asList(5, 6));
  }

}

答案 1 :(得分:1)

T是根据参数决定的,但也可以明确指定。所以,是的,它可以是Comparable和Serializable。

所有这些都是有效的:

     Collections.<Number>copy(objs, ints);
     Collections.<Comparable>copy(objs, ints);
     Collections.<Serializable>copy(objs, ints);
     Collections.<Integer>copy(objs, ints);

     Collections.copy(objs, ints); // implicitly Integer

如果未指定类型,则会选择整数,因为java documentation

中处理<? extends Integer>的方式已得到解释

答案 2 :(得分:-1)

对象类是Serializable和Comparable的超类型
这不是真的,Serializable和Comparable是接口,与Object没有关系。

此外,super ?extends ? 完全相反 这意味着它不能应用于接口。它可以应用于接口。

当你写? extends T时,它意味着? is an unknown subtype of T, probably T itself。我相信JVM解决了T自下而上,这意味着T实际上是Integer而不是Number(如果我错了,请纠正我)。

然后

   Collections.copy(objs, ints)

实际上是

   Collections.<Integer>(objs, ints)