以下陈述之间有什么区别:
List<E>[] x = (List<E>[]) new List[100];
和
List<E>[] x = new List[100];
在我的脚本中,注意前者是创建泛型数组的正确方法(尽管它会导致编译器警告)。但我无法弄清楚(List<E>[])
语句的用法是什么。 List<E>[]
甚至不是它自己的类型,编译器只会用(List[])
替换它,所以你得到
List<E>[] x = (List[]) new List[100];
从List[]
转换为List[]
,这是无用的。那么为什么首先放入(List<E>[])
呢?
答案 0 :(得分:3)
泛型通过在编译时检测到更多错误来增加代码的稳定性。
这是我给出的链接的一部分,认为同样重要,所以我在这里张贴
这是接口 List的定义的一小段摘录 和java.util包中的Iterator :
public interface List <E> { void add(E x); Iterator<E> iterator(); } public interface Iterator<E> { E next(); boolean hasNext(); }
这个代码应该都很熟悉,除了角度的东西 括号。这些是接口List和Iterator的formal type parameters的声明。
类型参数可以在整个通用声明中使用,非常好 你会使用普通类型的地方。
我们知道泛型类型声明List的调用,例如 的列表。在调用中(通常称为参数化 输入),所有出现的形式类型参数(在本例中为E) 将替换为实际的类型参数(在本例中为Integer)。
您可能会想到List代表List的版本 其中E已被Integer统一替换:
public interface IntegerList { void add(Integer x); Iterator<Integer> iterator(); }
这种直觉可能有所帮助,但它也误导。
这很有用,因为参数化类型List有 确实有一些方法看起来就像这种扩张。
这是误导性的,因为通用的声明永远不会 实际上以这种方式扩展。没有多个副本 代码 - 不是源代码,不是二进制代码,不是磁盘而不是内存。
泛型类型声明一劳永逸地编译并转换 单个类文件,就像普通的类或接口一样 声明。强>
类型参数类似于中使用的普通参数 方法或构造函数。很像一种方法具有正式价值 用于描述其操作的值类型的参数,通用的 声明具有正式的类型参数。调用方法时 实际参数代替形式参数,以及 方法体被评估。
当调用泛型声明时, 实际类型参数替换形式类型参数。这就是泛型的重要性。
您可以在此处查看more information about Generics
答案 1 :(得分:1)
此:
List<E>[] x = new List[100];
表示x是一种数组类型。该数组的元素是列表,可以容纳类型E 对象。并且您正在为其分配一系列列表,这些列表可以容纳任何对象。
下一个声明:
List<E>[] x = (List<E>[]) new List[100];
不是更好。施法无济于事。这个缺陷仍然是一样的。
最终,所有这些都是这样做的借口:
List<E>[] x = new List<E>[100];
Java中不允许使用泛型数组。因为Arrays在运行时保持它们的元素类型,而泛型构造则不然。必须没有没有严格定义元素类型的数组。
问题是由于定义了一个引用类型List<E>[]
,根据定义,它不允许在Java中实例化。所以,避免使用这种类型。
您可以使用列表列表作为替代。
答案 2 :(得分:1)
与泛型一样,存储在任何集合中的对象类型将在添加到集合中时进行类型检查。主要通过泛型,其他那些不需要了解泛型的人可以理解代码。因此,通过在编译时插入检查并在运行时擦除可以实现此行为。