Java中List转换为数组,数组转List

XiaoHeiGou7 2014-01-11 04:23:35
今天写代码遇到一个奇怪的问题,具体代码不贴出了,写一个简化的版本。如下:
ArrayList<String> list=new ArrayList<String>();
String strings[]=(String [])list.toArray();

这样写代码个人觉得应该没什么问题,编译也没有问题。可是具体运行的时候报异常,如下:Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object;
但是这么写是没有问题的:
ArrayList<String> list=new ArrayList<String>();
String strings[]=new String[list.size()];
for(int i=0,j=list.size();i<j;i++){
strings[i]=list.get(i);
}
对于这个现象我们可以这么解释:Java中允许向上和向下转型,但是这个转型是否成功是根据Java虚拟机中这个对象的类型来实现的。Java虚拟机中保存了每个对象的类型。而数组也是一个对象。数组的类型是[Ljava.lang.Object。把[Ljava.lang.Object转换成[Ljava.lang.String是显然不可能的事情,因为这里是一个向下转型,而虚拟机只保存了这是一个Object的数组,不能保证数组中的元素是String的,所以这个转型不能成功。数组里面的元素只是元素的引用,不是存储的具体元素,所以数组中元素的类型还是保存在Java虚拟机中的。

根据上面的解释,我们可以把这个问题归纳到下面这个模型:
Object objs[]=new Object[10];
String strs[]=(String[])objs;

这样子和刚才上面编译错误是一样的。如果我们修改一下这个代码,如下:
String strs[]=new String[10];
Object objs[]=strs;

这样子就可以编译通过了。所以这个问题我们可以归结为一个Java转型规则的问题。下面谈一下Java数组对范型的支持问题。

JDK5中已经有了对范型的支持,这样可以保证在集合和Map中的数据类型的安全,可是,List的toArray方法返回的竟然是Object []让人很迷惑。个人感觉应该可以根据范型,直接返回相应的T []。仔细看了一下JDK的源码发现List转化为array有两个方法:

public Object[] toArray();
这个方法把List中的全部元素返回一个相同大小的数组,数组中的所有元素都为Object类型。

public <T> T[] toArray(T[] a);
这个方法把List中的全部元素返回一个相同大小的数组,数组中的所有元素都为T类型。

List如此设计是因为Java编译器不允许我们new范型数组。也就是说你不能这么定义一个数组:
T arr=new T[size];

但是你却可以用T[]来表示数组,而且可以把数组强制转化为T[]。比如List中的public <T> T[] toArray(T[] a)是这么实现的:
public <T> T[] toArray(T[] a) {
if (a.length < size)
a = (T[])java.lang.reflect.Array.
newInstance(a.getClass().getComponentType(), size);
System.arraycopy(elementData, 0, a, 0, size);
if (a.length > size)
a[size] = null;
return a;
}

从上面代码中可以看到,因为你不知道这个数组的类型,你必须通过反射机制创建这个数组(a.getClass().getComponentType()方法是取得一个数组元素的类型)。

最终,List转换为Array可以这样处理:

ArrayList<String> list=new ArrayList<String>();

String[] strings = new String[list.size()];

list.toArray(strings);

反过来,如果要将数组转成List怎么办呢?如下:

String[] s = {"a","b","c"};
List list = java.util.Arrays.asList(s);

摘自 xxf880324
...全文
2991 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复
引用 6 楼 CS_liuqing 的回复:
[Ljava.lang.Object 是什么类型啊?
就是 Object[] 类型 每一个 [ 表示一维数据,L 表示对象类型,后面 java.lang.Object 表示类型名称,其实最后还有个分号给你漏了
简易人 2014-01-20
  • 打赏
  • 举报
回复
楼主,好样的,兄弟顶你的肺。
 
List<String> _listStr=new ArrayList<String>();
_listStr.add("0");
_listStr.add("1");
_listStr.add("2");
_listStr.add("3");
 //一切尽在不言中
String[] array = _listStr.toArray(new String[_listStr.size()]);
System.out.println(Arrays.toString(array));
coooliang 2014-01-20
  • 打赏
  • 举报
回复
list.toArray(new String[]{});
你好毒你好毒 2014-01-20
  • 打赏
  • 举报
回复
虽然经常用,但是还是赞一个,toArray(T[] a)这个方法还是很有用的!!!
且走且珍惜 2014-01-20
  • 打赏
  • 举报
回复
[Ljava.lang.Object 是什么类型啊?
  • 打赏
  • 举报
回复
总结的很好。
  • 打赏
  • 举报
回复
前面的学习了 但是泛型,作为Java中有名的“糖衣炮弹”,只是为了程序更加安全。实际是加入集合的元素类型还是会转换成Object...
Inhibitory 2014-01-11
  • 打赏
  • 举报
回复
import java.util.ArrayList;
import java.util.Arrays;

public class Aloha {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<String>();
        list.add("One");

        String[] strs = list.toArray(new String[0]);
        System.out.println(Arrays.toString(strs));
    }
}
XiaoHeiGou7 2014-01-11
  • 打赏
  • 举报
回复
呵呵 今天突然的发现
krock_java 2014-01-11
  • 打赏
  • 举报
回复
以前没考虑过这个问题,学习了!!

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧