Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/334.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java中数组和泛型的类型规则_Java_Generics_Covariance_Erasure - Fatal编程技术网

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

Java中数组和泛型的类型规则,java,generics,covariance,erasure,Java,Generics,Covariance,Erasure,有效Java(2)第25项的最后一段说: 数组和泛型有非常不同的类型规则。数组是协变的和具体化的;泛型是不变的和擦除的。 有人能更好地定义Java中与数组和泛型相关的粗体术语吗?我也不介意举一些例子。如果你对某个特定概念感到困惑,你没有提到,所以我将尝试给出协方差和不变性的基本定义 协方差保持类型排序,不变性不保持。这意味着子类型是否被保留(在相反的情况下是反向的) 那么,如果你上过下面的课 public class A { public void go() { System.o

有效Java(2)第25项的最后一段说:

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


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

如果你对某个特定概念感到困惑,你没有提到,所以我将尝试给出协方差和不变性的基本定义

协方差保持类型排序,不变性不保持。这意味着子类型是否被保留(在相反的情况下是反向的)

那么,如果你上过下面的课

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();
}
public static void go(X<?> x) {

  x.go();
}
完全可以用作

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

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

go(xa);
go(xb);
换句话说,数组类型向运行时公开或具体化

对于不变类型(例如泛型),子类型不保留。因此,例如,
X
X
没有类型关系,而与
X
没有类型关系。这部分是泛型类型未暴露于运行时或未被擦除的结果

但是,您仍然可以分别使用
extends
super
在Java中显式表示协方差和逆变。例如,在课堂上

public class X<T extends A> {

  private T t_;

  public X(T t) {
   t_ = t;
  }

  public void go() {

    t_.go();
  }
}
公共类X{
私人T!;
公共X(T){
t=t;
}
公开作废go(){
t_.go();
}
}
功能

public static void go(A[] as) {

  for (A a : as)
    a.go();
}
public static void go(X<?> x) {

  x.go();
}
公共静态作废go(X X){
x、 go();
}
将有效地用作

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

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

go(xa);
go(xb);
xxa=新的X(a);
xxb=新的X(b);
go(xa);
go(xb);

解释了差异,尽管它更适用于c#。你试过维基百科吗?我想我会在这里得到更明确的答案。我还认为,还有其他人在读这本优秀的书,他们可能会提出与我类似的问题。