5

以下语句之间有什么区别:

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>[])放在第一位呢?

4

3 回答 3

3

泛型通过在编译时检测到更多错误来增加代码的稳定性。

这是我给出的链接的一部分,认为这很重要,所以我在这里发布

这是java.util 包中接口List 和 Iterator定义的一小段摘录:

public interface List <E> {
    void add(E x);
    Iterator<E> iterator();
}

public interface Iterator<E> {
    E next();
    boolean hasNext();
}

这段代码应该都很熟悉,除了尖括号中的内容。这些是接口 List 和 Iterator的形式类型参数的声明。

类型参数可以在整个泛型声明中使用,几乎可以在使用普通类型的地方使用。

我们知道泛型类型声明List的调用,比如 List。在调用(通常称为参数化类型)中,所有出现的形式类型参数(在本例中为 E) 都被实际类型参数(在本例中为整数)替换。

你可能会想象 List 代表一个 List 版本,其中 E 已被 Integer 统一替换:

public interface IntegerList {
        void add(Integer x);
        Iterator<Integer> iterator();
    }

这种直觉可能会有所帮助,但也会产生误导

这很有帮助,因为参数化类型 List 确实有看起来像这种扩展的方法。

这是误导性的,因为泛型的声明实际上从未以这种方式扩展。代码没有多个副本——不在源代码中,不在二进制文件中,不在磁盘上,也不在内存中。

泛型类型声明一劳永逸地编译,并转换为单个类文件,就像普通的类或接口声明一样。

类型参数类似于方法或构造函数中使用的普通参数。就像一个方法有正式的值参数来描述它所操作的值的种类一样,泛型声明也有正式的类型参数。当一个方法被调用时,实际参数被替换为形式参数,并且方法体被评估。

当调用泛型声明时,实际类型参数将替换形式类型参数。这就是泛型的重要性。

您可以在此处查看有关泛型的更多信息

于 2013-08-24T17:25:29.003 回答
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 中不允许使用泛型数组。因为数组在运行时保持其元素类型,而泛型构造则不然。不能有没有严格定义元素类型的数组。

问题是由于定义了一个引用类型List<E>[],根据定义,它不允许在 Java 中实例化。因此,请避免使用此类类型。

您可以使用列表列表作为替代方案。

于 2013-08-24T17:58:18.020 回答
1

与泛型一样,存储在任何集合中的对象类型将在它们添加到集合时进行类型检查。主要通过泛型,代码可以被不需要了解泛型的其他人理解。因此,通过在编译时插入检查并在运行时擦除可以实现这种行为。

你可以看到: http ://docs.oracle.com/javase/tutorial/java/generics/

于 2013-08-24T17:59:07.683 回答