Effective-Java-28列表优于数组
数组与泛型相比,有两个重要的不同点。首先,数组是协变的(covariant)。这个词听起来有点吓人,其实只是表示,如果Sub为Super的子类型,那么数组类型Sub[]就是Super[]子类型。相反,泛型则是可变的(invariant):对于任意两个不同的类型Type1和Type2,List
1 | // Fails at runtime! |
但下面这段代码则不合法
1 | // Won't compile! |
这其中无论哪一种方法,都不能将 String 放进 Long 容器中,但是使用数组,你会在运行时才发现所犯的错误;而使用列表,则可以在编译时就发现错误。
数组与泛型的第二大区别:数组是具象化的 (reified)[JLS, 4.7]。因此数组会在运行时知道和强化它们的元素类型。如上所述,将 String 保存到 Long 数组中,就会得到一个 ArrayStoreException 异常。泛型则是通过擦除(erasure)[JLS, 4.6]来实现的。泛型只会在编译时强化它们的类型信息,运行时丢弃(或者擦除)它们的元素信息。擦除就是使泛型可以与没有使用泛型的代码随意进行互用(见26条),以确保在Java5中平滑过渡到泛型。
因为以上这些根本的区别,数组和泛型不能很好地混合使用。例如,创建泛型、参数化类型或者类型参数的数组是非法的。
以下数组创建表达式没有一个是合法的:
这些在编译期会产生一个泛型数组创建(generic array creation)错误。
1 | new List<String>[]; |
从技术角度上来说,E、List