Java 为什么列表<;字符串>;。toArray()返回对象[]而不是字符串[]?如何解决这个问题?
有人知道为什么Java 1.6会有这种行为吗Java 为什么列表<;字符串>;。toArray()返回对象[]而不是字符串[]?如何解决这个问题?,java,generics,Java,Generics,有人知道为什么Java 1.6会有这种行为吗 List<String> list = ArrayList<String>(); String[] arr = (String[]) list.toArray(); List List=ArrayList(); String[]arr=(String[])list.toArray(); 我得到一个ClassCastException,因为它返回Object[],而不是String[] 我想 List.toArray()应返
List<String> list = ArrayList<String>();
String[] arr = (String[]) list.toArray();
List List=ArrayList();
String[]arr=(String[])list.toArray();
我得到一个ClassCastException,因为它返回Object[],而不是String[]
我想
List.toArray()
应返回T[]-否?有人能回答为什么语言中存在这种不便吗?
以及如何解决这个问题?如何从
列表
中获取字符串[],而不在项目中循环?您需要传入一个数组,这样它的运行时类型可以被toArray
用作提示。请改为尝试toArray(新字符串[0])
。您还可以传入预先调整大小的数组
要理解,考虑什么类型的擦除会使
new T[4]
工作。如果Java允许这样做,那么它在擦除后所能做的最好的事情就是
new Object[4]
大多数
toArray
实现都使用在类型提示作为类传递的情况下构造正确类型的输出数组,因为数组从一开始就在Java中,而泛型仅在Java 5中引入。而List.toArray()
方法是在泛型出现之前在Java1.2中引入的,因此它被指定返回Object[]
。许多现有代码现在都希望List.toArray()
返回Object[]
,因此现在无法更改它
此外,泛型在运行时会被擦除,所以ArrayList
甚至无法构造正确类型的数组
这个方法的漏洞是,它将返回一个正确类型的数组,前提是您给它一个正确类型的数组,以便它知道使用哪种类型。要理解为什么会发生这种情况,只需查看javadoc,然后查看该方法。还要记住,Java中的泛型在运行时会被删除。原因有二:
该方法在泛型之前,它们无法在不破坏向后兼容性的情况下更改签名
在任何情况下,由于列表
是在没有类
的情况下构造的,因此实现无法构造T
类型的数组
解决方法将使用:
List<String> list = new ArrayList<>();
list.add("Sputnik");
list.add("Explorer");
//String[] str = list.toArray();
谢谢你,Mike,我没有注意到这个方法t[]toArray(t[]arg0)-它返回我需要的。或者使用toArray(新字符串[list.size()])
如果你想避免分配大小为0的数组,那么下面的答案是list
接口不能提供E[]toArray()
方法,因为它会与旧的对象[]toArray()
方法冲突,该方法在1.2中引入,并且需要向后兼容。这是有道理的,因为您不能有两个只因返回类型而异的方法签名。但是你的回答暗示E[]toArray()
由于类型擦除而无法工作-我读对了吗?或者,在使用T
作为泛型类型和使用E
作为声明的列表界面之间是否存在细微差别?是的,我想我忽略了明显的差别。像E get(int index)
这样的列表方法之所以有效,是因为它们是在编译时强制执行的,不必在运行时知道或构造类型E[]toArray()
可以在运行时检查其返回值赋值/传递/等,但实际上构造数组需要了解正确的类型。Jave实际上没有t[]
的概念。可能是“的重复项”,因此它被指定为返回对象[]。许多现有代码现在需要List.toArray()返回对象[],因此现在无法更改。”胡说八道。Java收集方法的返回类型已更改为泛型。这完全无关。实际原因是不同类型的数组在运行时是不同的,因此它不可能返回正确类型的数组。这在泛型前后都是正确的。丹尼尔,真的吗?这个问题已经被问过多少次了?一百万?你是在教训我回答一个重复的问题吗?@unjutable:我昨天回答这个问题时,没有立即看到(也没有立即记住)一个完全重复的问题。今天我快速搜索了一下,我想已经够近了。如果你确信一个问题是重复的,那么与其假设你不诚实,为什么不投票结束你自己呢?你有足够的代表@newacct:我不确定这是否完全无关。的确,Java5还引入了返回类型协方差,因此返回t[]
而不是Object[]
不一定是一个突破性的改变。但是由于数组方差的工作方式很奇怪:,返回T[]
是否正确?我的一般经验法则是,您可以使用泛型,也可以使用数组协方差,但应避免同时使用这两种方法。@Daniel:返回类型协方差(处理重写方法的返回类型)在这里没有问题,因为它的所有超类(集合)中都有toArray()
方法也将更改为T[]
。至于你关于它是否正确的问题,假设一个方法可以神奇地返回一个T[],那么在大多数情况下它都是正确的,因为T[]
是Object[]
的一个子类,所以任何想要Object[]
的人都应该能够接受T[]
。唯一的例外是,如果他们试图在数组中插入一个不同类型的元素,这种可能性非常罕见。您会将签名更改为什么?您的意思是返回类型T[]?如果尝试使用ClassCastException,您将得到一个ClassCastException,因为当您更改方法签名时,该方法仍然会创建一个对象[]@newacct。通常情况下,更改实现以进行匹配。但是,请看我的编辑。我的反对意见是Java api中的所有方法签名都发生了更改(例如,所有集合类的方法,
Instead use:
String[] str = list.toArray(new String[0]);
or
String[] str = list.toArray(new String[list.size()]);