sup*_*ish 5 java variadic-functions
我有一个使用varargs功能的方法:
void add(Animal ...);
Run Code Online (Sandbox Code Playgroud)
现在,.add(dog, cat)我有一个动物列表,其中包含未知数量的元素,而不是
List<Animal> i = new ArrayList<Animal>();
i.add(dog);
i.add(cat);
Run Code Online (Sandbox Code Playgroud)
并希望使用此列表的元素调用add.
我想我可以使用一个数组,但是当我这样做时.add(i.toArray()),它会产生编译错误.
这样做的正确方法是什么?
Tom*_*son 11
它的:
add(i.toArray(new Animal[i.size()]))
Run Code Online (Sandbox Code Playgroud)
List.toArray返回一个Object[],不管List上的类型参数如何:即使你可能会写new List<String>().toArray(),你也会得到一个Object[].但是,使用数组填充的toArray版本返回一个具有正确类型的数组:如果你写new List<String>().toArray(new String[0]),你将得到一个String[].请注意,传入的数组的大小甚至不必与列表的大小相匹配,尽管确保它的确如此.
这最终归因于泛型的一个稍微棘手的特征.乍一看,你可能会认为,String[]和List<String>意味着他们的基本类型相似的东西-一个是字符串数组,另一种是字符串列表.
然而,它们实际上是非常不同的.
数组是一种语言基元,并且其类型已烘焙到其中.如果您使用十六进制编辑器并查看JVM内存中的数组实例,您将能够找到(在附近的某个位置)它所拥有的对象类型的记录.这意味着如果您获取某个未知组件类型的数组的实例,您可以找出该类型是什么.相反,这意味着如果您要创建数组实例,则需要知道所需的组件类型.
的List,而另一方面,使用泛型,这在Java中与实现类型擦除,这意味着,粗略地讲,它是什么,存在于编译器,而不是在运行时(编译器可以检查你得到它的权利,但是JVM不能).这导致了一个简单而有效的实现(一个简单到足以在不更改JVM的情况下添加到预泛化Java),但它有一些缺点 - 特别是在运行时,没有办法告诉类型参数是什么在泛型类的任何特定实例上,因为类型参数仅存在于编译器中.因为List要处理的是实例toArray(),所以它唯一能做的就是创建一个Object[].它只是不知道要使用的更具体的类型.
查看这个的一种方法是数组有一个类型参数作为其类的一部分,而Lists有一个类型参数作为其类型的一部分,并且由于对象有类但变量有类型,你不能得到类型参数a List来自一个对象,只来自一个持有一个对象的变量(另外,你也不能从一个持有数组的变量中获取数组的类型参数(考虑Object[] array = new String[0];),但这并不重要,因为,变量让你掌握一个对象 - 除非它是空的).
将其归结为代码,问题是:
public <E> E[] createSimilarlyTypedArray(List<E> list) {
Class<E> componentType = list.???; // there is no way to do this
return Arrays.newInstance(componentType, list.size());
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2061 次 |
| 最近记录: |