public class SimpleCollection<T>{
public static void main(String[] args) {
Object[] o = new Object[10];
String[] s = (String[])o;①//运行报错:Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.String;

SimpleCollection<String> si = new SimpleCollection<String>();
si.method();
}

public void method(){
Object[] o = new Object[10];
T[] t = (T[])o;②//Type safety: Unchecked cast from Object[] 编译警告,运行正常
}
}为什么①转换会报错,而②却没有报错?请高手指教

解决方案 »

  1.   

    首先,子类数组转父类数组没问题,如 String[] s; 可以转为 Object[] o = (Object[])s;
    但父类数组不能转成子类数组,因为不能保证父类的元素都符合子类类型,因为同一个父类可以有不同的子类所以
    第一种情况,Object[] o是确定的类型,String[] s也是确定的类型,所以编译期间编译器能知道父类数组不能转成子类数组,所以报错而第二种是泛型擦除
    Object[] o是确定的类型,T[] t是泛型,编译的时候编译期不知道T[]是什么类型,而把泛型擦除,即把T[]变为Object[](Object[]是父类数组没问题),所以编译器只是给出警告
      

  2.   

    第一种:
    在编译期间任何向上转型和向下转型都被认为是正确的,所以第一种情况编译器会认为可以编译通过。到了运行期间,你实例化的是一个Object类型的数组,将其向下转型成为String类型的数组明显是不正确的,因此会抛出类型转化异常,如果你这样实例化,再向下转型,就没有任何错误:
    Object[] o = new String[10];第二种:
    在编译的时候,泛型可以是任何类型,所以编译器也无法判断你的强制类型转换是否正确,只能发出一个警报,提醒你注意。泛型的作用是在编译期间保证类型正确,而在运行期间,所有跟泛型有关的东西都将消失,所以你的这句:
    SimpleCollection<String> si = new SimpleCollection<String>();
    在运行时会变成为:
    SimpleCollection si = new SimpleCollection();
    现在SimpleCollection这个类中的泛型T,和String无关,至于它在运行时到底是什么类型,我也不知道,反正将它怎么转换都不算错。