Java中数组和泛型的类型规则

Posted

技术标签:

【中文标题】Java中数组和泛型的类型规则【英文标题】:Type rules of arrays and generics in Java 【发布时间】:2015-11-11 17:53:31 【问题描述】:

Effective Java (2nd)第25条最后一段中说:

数组和泛型有非常不同的类型规则。数组是协变的reified;泛型是不变的擦除的。

有人可以更好地定义与 Java 中的数组和泛型相关的粗体术语吗?我也不介意一些例子。

【问题讨论】:

this eric lippert blog 解释了差异,尽管它更适用于 c#。你试过***吗? 我想我会在这里得到更明确的答案。我也认为还有其他人在阅读这本出色的书,并且可能会遇到与我类似的问题。 【参考方案1】:

您没有提到您是否对某个特定概念感到困惑,因此我将尝试仅给出协方差不变性的基本定义。 p>

Covariance 保留类型顺序,invariance 不保留。这意味着子类型被保留或不被保留(在 逆变 的情况下反转)。

所以,如果你有以下课程

public class A 

  public void go() 

    System.out.println("A");
  

还有……

public class B extends A 

  @Override
  public void go() 

    System.out.println("B");
  

使用协变类型(例如数组),函数

public static void go(A[] as) 

  for (A a : as)
    a.go();

完全有效的用作

A[] as = new A[8];
B[] bs = new B[8];

go(as);
go(bs);

换句话说,数组类型暴露给运行时或reified

对于不变类型(例如泛型),不保留子类型。因此,例如,X<B> 除了X 之外,与X<A> 没有类型关系。这部分是泛型类型没有暴露给运行时或擦除的结果。

但是,您仍然可以分别使用extendssuper 在Java 中明确表达协方差逆变。例如类

public class X<T extends A> 

  private T t_;

  public X(T t) 
   t_ = t;
  

  public void go() 

    t_.go();
  

功能

public static void go(X<?> x) 

  x.go();

将有效地用作

X<A> xa = new X<A>(a);
X<B> xb = new X<B>(b);

go(xa);
go(xb);

【讨论】:

以上是关于Java中数组和泛型的类型规则的主要内容,如果未能解决你的问题,请参考以下文章

Java、静态方法绑定和泛型都包含一些方法重载

Java泛型:包含泛型的数组[重复]

Java 泛型的读写规则:PECS

Java 泛型的读写规则:PECS

Java 泛型的读写规则:PECS

初识Java集合及包装类和泛型的基本使用