今天写代码遇到一个奇怪的问题,具体代码不贴出了,写一个简化的版本。如下:

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);

Java中List转换为数组,数组转List的更多相关文章

  1. Java中的二维数组

    Java 中的二维数组 所谓二维数组,可以简单的理解为是一种"特殊"的一维数组,它的每个数组空间中保存的是一个一维数组. 那么如何使用二维数组呢,步骤如下: 1. 声明数组并分配空 ...

  2. JAVA中文件与Byte数组相互转换的方法

    JAVA中文件与Byte数组相互转换的方法,如下: public class FileUtil { //将文件转换成Byte数组 public static byte[] getBytesByFile ...

  3. java中如何使用列表数组

    java中如何使用列表数组 觉得有用的话,欢迎一起讨论相互学习~Follow Me 转载链接 https://blog.csdn.net/hgtjcxy/article/details/8183519 ...

  4. Java中excel转换为jpg/png图片 采用aspose-cells-18.6.jar

    一  Java中excel转换为jpg/png图片 package com.thinkgem.jeesite.modules.task.util; import com.aspose.cells.Im ...

  5. 161101、在Java中如何高效判断数组中是否包含某个元素

    如何检查一个数组(无序)是否包含一个特定的值?这是一个在Java中经常用到的并且非常有用的操作.同时,这个问题在Stack Overflow中也是一个非常热门的问题.在投票比较高的几个答案中给出了几种 ...

  6. Java 中 byte、byte 数组和 int、long 之间的转换

    Java 中 byte 和 int 之间的转换源码: //byte 与 int 的相互转换 public static byte intToByte(int x) { return (byte) x; ...

  7. 七、如何在Java中高效检查一个数组是否含有一个值

    如何检查一个数组(非排序的)是否包含特定的值.这是个非常有用或经常被在Java中使用.这是个在Stack Overflow中高得票的问题.在已经高得票的答案中,有许多不同的处理方法,但是时间的复杂度非 ...

  8. Java中使用 foreach 操作数组

    foreach 并不是 Java 中的关键字,是 for 语句的特殊简化版本,在遍历数组.集合时, foreach 更简单便捷.从英文字面意思理解 foreach 也就是" for 每一个& ...

  9. Java中一维,二维数组的静态和动态初始化

    今天我们要开始来讲讲Java中的数组,包括一维数组和二维数组的静态初始化和动态初始化 数组概述: 数组可以看成是多个相同类型数据的组合,对这些数据的统一管理; 数组变量属于引用数据类型,数组也可以看成 ...

随机推荐

  1. java常见错误的列表

    ava常见错误列表: 找不到符号(symbol) 类X是public的,应该被声明在名为X.java的文件中 缺失类.接口或枚举类型 缺失X 缺失标识符 非法的表达式开头 类型不兼容 非法的方法声明; ...

  2. Sqlite 错误码

    #define SQLITE_OK 0 /* 成功 | Successful result */ /* 错误码开始 */ #define SQLITE_ERROR 1 /* SQL错误 或 丢失数据库 ...

  3. XCode的一些调试技巧

    XCode 内置GDB,我们可以在命令行中使用 GDB 命令来调试我们的程序.下面将介绍一些常用的命令以及调试技巧. po 命令:为 print object 的缩写,显示对象的文本描述(显示从对象的 ...

  4. 32.Spring-对象依赖.md

    [toc] 1.对象依赖的分类 Spring中,给对象属性赋值的方法: 构造函数 Set方法 p命名空间 自动装配 注解 1.1构造函数 构造方法通过配置文件中constructor-arg标签实现, ...

  5. FFMPEG 截取RTMP直播流图片命令

    CentOS 6.5  yum安装FFMPEG步骤 1. 手动添加yum源配置 vi /etc/yum.repos.d/dag.repo   [dag] name=Dag RPM Repository ...

  6. POJ 2010 Moo University - Financial Aid( 优先队列+二分查找)

    POJ 2010 Moo University - Financial Aid 题目大意,从C头申请读书的牛中选出N头,这N头牛的需要的额外学费之和不能超过F,并且要使得这N头牛的中位数最大.若不存在 ...

  7. 九度OJ 1025 最大报销额(01背包)

    题目1025:最大报销额 时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:2683 解决:608 题目描述: 现有一笔经费可以报销一定额度的发票.允许报销的发票类型包括买图书(A类).文具( ...

  8. Chrome扩展与用户隐私

    转载自https://www.imququ.com/post/chrome-extensions-and-user-privacy.html   Google Chrome浏览器应该早就是大家的默认了 ...

  9. MongoDB-固定集合 capped collection 操作 介绍

    固定集合:capped collection 是性能出色的固定大小的集合,以LRU算法淘汰记录,自助维护集合中的对象的插入顺序,创建时预先制定大小,空间使用完,心对象取代旧的对象,保持最新的数据. 可 ...

  10. js监听回车事件

    标题通俗的说,也就是绑定当用户按下回车键要执行的事件. 下面,入正题. 第一步,先编写简单的页面代码,这里我们只需要一个按钮就足够了.当然,还有按钮事件. <html> <head& ...