1、数组是协变的(convariant),如果Sub是Super的子类型,那么数组类型Sub[]就是Super[]的子类型。
泛型确实不可变的,List<Sub>不是List<Super>的子类型。
2、数组是具体化的(reified),因此数组在运行时才知道并检查它们的元素类型约束。
泛型则是通过擦除(erasure)来实现,因此泛型只在编译时强化它们的类型信息,并在运行时丢弃(或者擦除)它们的元素类型约束。擦除就是使泛型可以与没有使用泛型的代码随意进行互用(见第23条)。
1 | Object[] obs=new Long[1]; |
1 | List<String>[] stringLists=new List<String>[1];//创建一个泛型数组,假设合法 |
数组和泛型有两个重要的不同点。从技术的角度来说,像E、List和List这样的类型应称作不可具体化的(nonreifiable)类型(不可具体化类型是指其运行时表示法包含的信息比它编译时表示法包含的信息更少的类型)。唯一可具体化(reifiable)的参数化类型是无限制的通配符类型,如List<?>,Map<?,?>。虽然不常用,但是创建无限制通配类型的数组是合法的。1
List<?>[] stringLists=new List<?>[1];//是合法的
数组和泛型有着非常不同的类型规则。数组是协变且可以具体化的;泛型是不可变的且可以被擦除的。因此,数组提供了运行时的类型安全,但是没有编译时的类型安全,反之,对于泛型也一样。一般来说,数组和泛型不能很好地混合使用。如果你发现自己将它们混合起来使用,并且得到了编译时错误或者警告,你的第一反应就应该是用列表代替数组。