【问题标题】:toArray() method in Collection classCollection 类中的 toArray() 方法
【发布时间】:2014-01-23 19:25:41
【问题描述】:

Collection 类中有2 个toArray() 方法:<T> T[] toArray(T[] a)Object[] toArray()。没有E[] toArray() 方法。为什么? 它与类型擦除有关,但有例如方法 - boolean add(E e)。为什么可以创建参数化的add 而无法创建toArray() 方法?

【问题讨论】:

  • 对反引号不太满意?
  • 你能解释更多吗?反引号有什么问题:p?
  • 没有错,我只是让你很难过 :) 在这么小的空间里看到这么多是很少见的。

标签: java generics collections


【解决方案1】:

没有 E[] toArray() 方法。为什么?

它不可能实际上在执行时创建E[],因为由于类型擦除,它不知道要创建的数组类型。

add 方法真的可以接受任何东西,但编译器首先检查参数类型是否与E 兼容。在执行时不需要知道任何事情。同样对于像List.get 这样的东西,编译器会在调用代码中插入一个强制转换:

List<String> strings = new ArrayList<>();
strings.add("hello");
String first = strings.get(0);

被编译为与此预泛型代码相同的代码:

List strings = new ArrayList();
strings.add("hello");
String first = (String) strings.get(0);

现在这很好,因为我们在调用代码中在执行时知道String 类型...但是在toArray() 中,创建数组的代码需要知道类型...并且类型擦除意味着它实际上并不知道。传入toArray() 的数组允许它创建一个相同类型的数组。实际上,创建的对象的 实际 类型可以显示为取决于您传入的数组:

import java.util.*;

public class Test {

    public static void main(String[] args) {
        List<Object> objects = new ArrayList<Object>();
        objects.add("xyz");

        Object[] array1 = objects.toArray(new String[0]);
        Object[] array2 = objects.toArray(new Object[0]);
        System.out.println(array1.getClass()); // class [Ljava.lang.String;
        System.out.println(array2.getClass()); // class [Ljava.lang.Object;
    }
}

如果我们传入new Integer[0],它会编译,但是当toArray 尝试强制转换String(唯一的元素) 到Integer

【讨论】:

  • 我说的对吗?很快:add 方法可以被编译器检查,所以可以有参数化类型。 'toArray` 方法也可以由编译器检查,但它什么也没给出,因为由于类型擦除,返回的类型将始终是对象数组?它可以被创建,但它是无用的。参数化类型在add 方法中,因为那里编译器可以检查参数,它很有用。
  • @Pawel:有点。这实际上与可以检查的内容和何时有关。我不太确定我是否完全按照您的想法进行操作,但希望它们与答案一致:)
猜你喜欢
  • 2012-03-13
  • 2014-01-18
  • 2019-09-09
  • 1970-01-01
  • 2012-02-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多