记一次问题-Arrays.asList()和 new ArrayList<>()的区别以及导致数组类型转换异常的解决Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.Integer;
问题代码如下:
public static void main(String[] args) { Integer[] intArr={9,4,7,8,4,6};
//第一种创建ArrayList方式 List<Integer> intOldList = Arrays.asList(intArr);
//第二种创建ArrayList方式
List<Integer> intNewList = new ArrayList<>(); intNewList.add(9); System.out.println(intOldList.toArray().getClass().getSimpleName()); System.out.println(intNewList.toArray().getClass().getSimpleName()); Integer [] toArrayOld = (Integer[]) intOldList.toArray(); //这一行 类型转换异常 Integer [] toArrayNew = (Integer[]) intNewList.toArray(); }
打印结果:
Integer[] Object[] Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.Integer; at test.main(test.java:13)
到这里有人在想了,两种方式最后的结果都是创建ArrayList,为什么有一个能够转换成功,有一个就不能转换成功呢???
虽然展示给咱们的感觉是相同的,但是咱们通过intOldList.toArray().getClass().getSimpleName()方法获取源代码底层类的名称,得到的结果确实不一样的,一个Integer[]一个Object[],这又是为什么呢???
其实到这里已经说明了问题原因,两者的类型就是不一样的,所以一个正常转换,一个类型转换异常,Object[]不能直接强转为Integer[],如果想深究,那么请往下看。
以上代码总结出以下两点
1、Arrays.asList转换过来的ArrayList和直接new出来的ArrayList是不一样的
两个集合类,一个是通过数组工具类的Arrays.asList转换而来的,一个是直接new出来的。打印出来的结果却不一样,一个是Integer[],一个是Object[]。最后第二个直接new出来的在类型转换时还报了异常。
原因如下:
Arrays.asList返回的是Arrays中的内部类ArrayList,可以直接点击该方法,查找源代码。
/** * @serial include */ private static class ArrayList<E> extends AbstractList<E> implements RandomAccess, java.io.Serializable { private static final long serialVersionUID = -2764017481108945198L; private final E[] a; ArrayList(E[] array) { a = Objects.requireNonNull(array); } ......省略部分代码 }
但是直接new出来直接就是ArrayList,两者是不一样的。两者根源的不一样又导致两个类的toArray方法的不一样,具体请看以下截图说明:
首先来说一说在ArrayList这个类源码中的toArray方法
public Object[] toArray() { return Arrays.copyOf(elementData, size); }
transient Object[] elementData;
可以看出,其实在ArrayList中直接调用的Arrays.copyOf方法,里面的参数elementData,是一个Object的数组,在这里我个人认为是做了一次类型擦除。也是由于在这里,将Integer类型的数组转换为Object类型的数组。
然后来说一说Arrays中的toArray方法
public Object[] toArray() { return a.clone(); }
可以看出,这里直接用的Object的底层clone方法,这样就保持了原来的数组类型。
2、扩展,接下来说说ArrayList的toArray方法的使用
ArrayList提供了一个将List转为数组的一个非常方便的方法toArray。toArray有两个重载的方法: (1)list.toArray(); (2)list.toArray(T[] a); 第一个重载方法,是将list直接转为Object[] 数组; 第二个方法是将list转化为你所需要类型的数组,当然我们用的时候会转化为与list内容相同的类型。
第一个方法如下写法:
ArrayList<String> list=new ArrayList<String>(); for (int i = 0; i < 10; i++) { list.add(""+i); } String[] array= (String[]) list.toArray();
运行就会报错:
Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.String;
原因是:不能将Object[] 直接通过以上例子中类型强转换的方式转化为String[],转化的话只能是取出每一个元素再转化。像这样:
Object[] arr = list.toArray(); for (int i = 0; i < arr.length; i++) { String e = (String) arr[i]; System.out.println(e); }
第二个方法如下写法:
String[] array =new String[list.size()]; list.toArray(array);
运行正常。
结论:建议使用带参数的转换方式
集合转数组用方法,比如:list.toArray(new String[list.size()]);
利用set去重list重复数据转数组:set.toArray(new String[set.size()]);
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 上周热点回顾(3.3-3.9)
· AI 智能体引爆开源社区「GitHub 热点速览」
2019-07-14 安装mysql报错
2019-07-14 linux系统解压命令总结
2019-07-14 linux系统忘记root的登录密码
2019-07-14 linux系统的认识