hel*_*ker 8 java arrays collections arraylist
我正在使用Java中的Collection框架,在那里我遇到了一个奇怪的问题.我在ArrayList的帮助下制作了2个Strings 1列表,而第二个是使用Arrays.asList(T ...)制作的.
创建这两个列表后,我尝试将这些列表转换为带有list.toArray()的String数组,
因为list.toArray()方法调用返回一个对象数组,所以我必须显式地转换为String [].
在施放后,一些奇怪的行为发生在:
情况#1 :(使用ArrayList创建列表),将运行时异常作为java.lang.ClassCastException:[Ljava.lang.Object; 无法转换为[Ljava.lang.String;
情况2 :(使用Arrays.asList(T ...)创建的列表)运行正常.
这是代码
String [] str = null ,str1 = null ;
List<String> list = new ArrayList<String>();
list.add("a");
List<String> list1 = Arrays.asList("a");
str = (String[]) list.toArray(); // Runtime Exception
str1 = (String[]) list1.toArray(); // Runs Fine
Run Code Online (Sandbox Code Playgroud)
一个ArrayList是由一个支持Object[].返回该数组的副本toArray().
以适当的顺序(从第一个元素到最后一个元素)返回包含此列表中所有元素的数组.
它不保证返回的数组类型.但我们从异常的消息中知道这一点.如果您希望它返回a String[],请使用为此原因提供的重载方法.
str = list.toArray(new String[0]);
Run Code Online (Sandbox Code Playgroud)
演员变得不必要了.
List返回的实现Arrays.asList维护对作为其变量arity参数传递的数组(隐式或显式)的引用.
返回由指定数组支持的固定大小的列表.
调用
List<String> list1 = Arrays.asList("a");
Run Code Online (Sandbox Code Playgroud)
创建一个String[]并将其作为参数传递给asList.API文档没有明确指出这一点,但支持似乎表明它将返回相同的数组.(查看实现,它返回一个克隆.)因为它是a String[],所以在转换并将其分配给该类型的变量时没有错误.
在这两种情况下,适当的解决方案是使用重载List#toArray(T[]).
为了好玩,运行以下命令并检查返回的数组类型.
List<String> list1 = (List) Arrays.<Object> asList("a");
System.out.println(list1.toArray().getClass());
Run Code Online (Sandbox Code Playgroud)
不要做出假设.始终依赖API文档.如果不清楚,请尝试找到更好的解决方案.
对的不同调用将toArray返回具有不同组件类型的数组。您可以通过运行以下代码来查看此内容:
List<String> list = new ArrayList<String>();
list.add("a");
List<String> list1 = Arrays.asList("a");
System.out.println(list.toArray().getClass());
System.out.println(list1.toArray().getClass());
Run Code Online (Sandbox Code Playgroud)
在任何版本的Java 8或更早版本上,结果是
class [Ljava.lang.Object;
class [Ljava.lang.String;
Run Code Online (Sandbox Code Playgroud)
基本上,此输出分别为Object[]和String[]。
但是,这是一个错误。参见JDK-6260652。尽管没有明确说明,但Collection.toArray() 必须返回,Object[]而不是的子类型的数组Object。有两个原因。
首先是Collection.toArray()JDK 1.2中引入的功能,早于将泛型添加到该语言中。除之外Object[],没有任何实现返回的可能性,因此,为了兼容起见,所有集合的toArray()实现都必须返回Object[]。
第二个原因是,规范中对于的一句简而言之便是toArray(T[]):
请注意,toArray(new Object [0])在功能上与toArray()相同。
这再次需要toArray()返回,Object[]而不是其他类型的数组。
此错误已在JDK 9中修复。在最新的JDK 9构建上运行上面的代码段将产生以下输出:
class [Ljava.lang.Object;
class [Ljava.lang.Object;
Run Code Online (Sandbox Code Playgroud)
Arrays.asList("a")使用a String[]作为内部存储的事实是一个实现细节。toArray()除了Object[]此实现细节外,返回了其他错误的漏洞也已泄漏出去。(实际上,数组是由varargs机制创建的,使用方法的type参数作为数组组件的类型。Arrays.asList()只包装给定的数组。)
正如其他人所说,如果要控制返回数组的组件类型,请使用另一个重载toArray(T[]):
String[] array = list.toArray(new String[0]);
String[] array1 = list1.toArray(new String[0]);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
360 次 |
| 最近记录: |