asList方法产生的List对象不可更改

代码如下所示:

enun week { sun , Mon,Tue, wed, Thu , Fri,sat}
public static void main (string [] args) {
//五天工作制
week [] workDays = {week.Mon,week.Tue,Week.wed , week. Thu, Week.Fri} ;l//转换为列表
List list = Arrays .asList (workDays);//增加周六也为工作日
1ist.add (weak.sat):/*工作日开始干活了*/

很简单的程序呀,默认声明的工作日( workDays)是从周一到周五,偶尔周六也会算作工作日加入到工作日列表中。不过,这段程序执行时会不会有什么问题呢?
编译没有任何问题,但是一运行,却出现了如下结果:
Exception in thread "main" java. lang, Unsupportedoperationgxception
at java.uti1. AbstractList .add(AbstractList.java : 131)
at java.util.AbstractList.add(AbstractList.java : 91)
UnsupportedOperationException,不支持的操作?居然不支持List 的add方法,这真是奇怪了!还是来追根寻源,看看asList方法的源代码:
public static List asList (T... a){
return new ArrayList(a) ;
直接new了一个 ArrayList对象返回,难道ArrayList不支持add方法?不可能呀!可能问题就出在这个ArrayList类上,此 ArrayList非java.util.ArrayList,而是Arrays 工具类的一个内置类,其构造函数如下所示:

//这是一个静态私有内部类
private static class ArrayList extends AbstractListimplements RandomAccess, java.io.serializable 
{
//存储列表元素的数组
private final E[] a ;
//唯一的构造函数
ArrayList ( E [] array){
if (array == null)
throw new NullPointerException () ;
a = array ;
}
/*其他方法省略*/

这里的ArrayList是一个静态私有内部类,除了Arrays能访问外,其他类都不能访问。仔细看这个类,它没有提供add方法,那肯定是父类AbstractList提供了,来看代码:

public boolean add (E e){
throw new UnsupportedoperationException ( ) ;
}

父类确实提供了,但没有提供具体的实现(源代码上是通过add方法调用add(int,E)方法来实现的,为了便于讲解,此处缩减了代码),所以每个子类都需要自己覆写add方法,而Arrays 的内部类ArrayList没有覆写,因此 add一个元素就会报错了。
我们再深入地看看这个ArrayList静态内部类,它仅仅实现了5个方法:
size:元素数量。
toArray:转化为数组,实现了数组的浅拷贝。get:获得指定元素。
set:重置某一元素值。contains:是否包含某元素。
对于我们经常使用的List.add和 List.remove方法它都没有实现,也就是说asList返回的是一个长度不可变的列表,数组是多长,转换成的列表也就是多长,换句话说此处的列表只是数组的一个外壳,不再保持列表动态变长的特性,这才是我们要关注的重点(虽然此处JDK的设计有悖OО 设计原则,但这不在我们讨论的范围内,而且我们也无力回天)。
有些开发者特别喜欢通过如下方式定义和初始化列表:
List 一句话完成了列表的定义和初始化,看似很便捷,却深藏着重大隐患——列表长度无法修改。想想看,如果这样一个List传递到一个允许add操作的方法中,那将会产生何种结果﹖如果读者有这种习惯,请慎之戒之,除非非常自信该Lis 只用于读操作。

你可能感兴趣的:(asList方法产生的List对象不可更改)