一、基本数据类型数组不能作为asList的入参,否则会引起程序的逻辑混乱。
这段时间在熟悉新的项目,在看项目代码的时候,发现以前的同事很喜欢用Arrays和Collections这两个工具类,实现数组与列表之间的转换。应该说,很多开发的童鞋在实现数组与列表之前转换的时候,都钟情于这两个工具类。鄙人为了理解这两个工具类,特意写了一个demo学习一下。
import java.util.Arrays; import java.util.List; public class BadWithAsList { @SuppressWarnings("rawtypes") public static void main(String[] args) { int[] data = {1,2,3,4,5}; List dataList = Arrays.asList(data); System.out.println("列表中元素的数量是:" + dataList.size()); } }
也许,你会说这个很简单,最后输出是5。那么,你就掉进了asList方法的陷阱里面了。事实上,这段程序最后输出的结果是1。
为什么最后的结果会是1?打开asList方法查询源码便知:
public static <T> List<T> asList(T... a){ return new ArrayList<T>(a); }
从asList的源码可以知道,入参是变长的,而返回值是一个定长的List。再看看这个demo,定义的数组是基本类型的数组,我们知道基本类型是不能泛型化的,要想作为泛型化就必须使用其包装类型。运行这个demo之所以不报错,那是因为数组本身也是一个对象,是可以泛型化的。也就是说这个例子把int类型的数组作为了T的类型,所以转换后在List中只有一个类型为int数组的元素了,可以通过打印结果来验证:
import java.util.Arrays; import java.util.List; public class BadWithAsList { @SuppressWarnings("rawtypes") public static void main(String[] args) { int[] data = {1,2,3,4,5}; List dataList = Arrays.asList(data); System.out.println("元素类型:" + dataList.get(0).getClass()); System.out.println("前后元素是否相等:" + data.equals(dataList.get(0))); } }
运行结果:
元素类型:class [I
前后元素是否相等:true
看这两行输出信息,很明显列表中的元素是一个int数组,但是元素类型为什么会是“[I”?我们并没有指明是Array类型,这是因为JVM不可能输出Array类型。Array类型是java.lang.reflect包中的,是通过反射访问数组元素的工具类。在Java中任何一个数组的类都是“[I”,根源就是Java并没有定义数组这个类,而是在编译的时候,通过编译器生成的这个类,这是一个特殊的类,在JDK的API中没有任何数组类的信息。
现在将第一个demo的数组修改成对应的包装类即可,运行输出结果:列表中元素的个数:5。
二、asList方法产生的List对象不可更改
为什么这么说呢?先通过一个例子说明一下:
public enum Week { SUN, MON, TUE, WED, THU, FRI, SAT }
import java.util.Arrays; import java.util.List; public class NoWriteAfterAsList { public static void main(String args[]){ Week[] workDays = {Week.MON,Week.TUE,Week.WED,Week.THU,Week.FRI}; List<Week> workDayList = Arrays.asList(workDays); workDayList.add(Week.SAT); System.out.println("周六加班:" + workDayList.get(5)); } }
运行结果:
Exception in thread "main" java.lang.UnsupportedOperationException
at java.util.AbstractList.add(AbstractList.java:148)
at java.util.AbstractList.add(AbstractList.java:108)
at com.zh.arrays.transfer.list.NoWriteAfterAsList.main(NoWriteAfterAsList.java:10)
UnsupportedOperationException,不支持List调用add的方法,这和我们以往所掌握的知识矛盾了,咱还是看看asList的源码,直接new 一个ArrayList返回了,要注意这里的ArrayList不是java.util包中的,而是Arrays工具类的内置类,其源码如下:
private static class ArrayList<E> extends AbstractList<E> implements RandomAccess, Serializable { private static final long serialVersionUID = -2764017481108945198L; private final E[] a; ArrayList(E[] var1) { this.a = (Object[])Objects.requireNonNull(var1); } public int size() { return this.a.length; } public Object[] toArray() { return (Object[])this.a.clone(); } public <T> T[] toArray(T[] var1) { int var2 = this.size(); if(var1.length < var2) { return Arrays.copyOf(this.a, var2, var1.getClass()); } else { System.arraycopy(this.a, 0, var1, 0, var2); if(var1.length > var2) { var1[var2] = null; } return var1; } } public E get(int var1) { return this.a[var1]; } public E set(int var1, E var2) { Object var3 = this.a[var1]; this.a[var1] = var2; return var3; } public int indexOf(Object var1) { Object[] var2 = this.a; int var3; if(var1 == null) { for(var3 = 0; var3 < var2.length; ++var3) { if(var2[var3] == null) { return var3; } } } else { for(var3 = 0; var3 < var2.length; ++var3) { if(var1.equals(var2[var3])) { return var3; } } } return -1; }
这里的ArrayList是一个私有的内部静态类,除了Arrays能访问以外,别的类不能访问。从源码中可以看出,这个类并没有提供add方法,查看其父类的源码如下所示:
public boolean add(E e) { add(size(), e); return true; } public void add(int index, E element) { throw new UnsupportedOperationException(); }
父类确实提供了,但是没有具体的实现,所以每个子类需要自己覆写add方法,而Arrays中的ArrayList类型没有覆写,所以在调用的时候会报错。
最后,建议在初始化List的时候,不要用Arrays.asList方法。除非你敢保证你的List在整个程序中只能用于读操作。
相关推荐
java-对象数组转换为json,自己的记录,能帮到人更好
主要介绍了Java实现字符数组全排列的方法,涉及Java针对字符数组的遍历及排序算法的实现技巧,需要的朋友可以参考下
实现 字符串,整型数据,字符型数组互相转换源码
char short int long float double 转换成byte数组
1. 编写一个程序打印数出有10个元素的浮点数组a1中最大值和最小值。 2.将有10个元素的数组a1 拷贝至含有15个元素的数组b1的一段位置。 3.将一个已存入数组中的值45,89,7,6,0,按0,6,7,89,45的次序打印...
Java-byte数组转换成16进制字符串
这是本人写的一个基于JSON的完整项目,实现了Java对象、数组、集合转换为Json(Json转化为Java对象、数组、集合)。这是一个完整的项目,下载解压后直接导入MyEclipse/Eclipse中,运行com.demo.JSONDemo类即可看到效果...
主要介绍了java实现二维数组转json的方法,涉及java数组遍历及json格式数据构造相关操作技巧,需要的朋友可以参考下
Educoder题目:Java入门 - 数组进阶答案解析
Educoder题目:Java入门 - 数组基础答案解析
.java文件,对java基础的数组部分的进制类型转换部分的说明。
Java中使用数组完成学生成绩统计的多种实现代码清单.pdf 学习资料 复习资料 教学资源
附件内容为:Java组装map数据,然后转换为json数据格式;Java解析json数据
使用链式编程写法实现Java中byte数组的拼接。例如byte[] bytes = ByteUtils.get().add(0x41).add(07).add(11).add("15288930000").add(0x45).toArray();更灵活用法请参考Mybytes
1.方便获得一个字符串表示的矩阵 2.删除二维数组中的第几行 3.删除二维数组中与所要删除行内容一样的此行 4.获得此二维数组
java 动态的数组链表 java 动态的数组链表 java 动态的数组链表
52.java二维数组静态初始化.zip52.java二维数组静态初始化.zip52.java二维数组静态初始化.zip52.java二维数组静态初始化.zip52.java二维数组静态初始化.zip52.java二维数组静态初始化.zip52.java二维数组静态初始化....
51.java二维数组动态初始化.zip51.java二维数组动态初始化.zip51.java二维数组动态初始化.zip51.java二维数组动态初始化.zip51.java二维数组动态初始化.zip51.java二维数组动态初始化.zip51.java二维数组动态初始化....
java语言中数组的基础教程学习资料适用新手java语言中数组的基础教程学习资料适用新手java语言中数组的基础教程学习资料适用新手java语言中数组的基础教程学习资料适用新手java语言中数组的基础教程学习资料适用新手...
java基本类型与byte数组互相转换.pdf