您的位置:首页 > 其它

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

2015-11-01 15:24 309 查看
上一个建议指出了 asList方法在转换基本类型数组时存在的问题,接着我们看一下 asList方法返回的列表有何特殊的地方,代码如下所示:

public static void main(String[] args) {
Week[] workDays={Week.Sun,Week.Mon,Week.Tue,Week.Wed,Week.Fri};
List<Week> list=Arrays.asList(workDays);
list.add(Week.Sat);
}
}
enum Week{
Sun,Mon,Tue,Wed,Thu,Fri,Sat
}


很简单的程序呀,默认声明的工作日(workDays)是从周一到周五,偶尔周六也会算作 工作日加入到工作日列表中。不过,这段程序执行时会不会有什么问题呢?

编译没有任何问题,但是一运行,却出现了如下结果:

Exception in thread "main"java■lang•UnsupportedOperationException at java.util.AbstractList.add(AbstractList.java:131)at java.util.AbstractList.add{AbstractList.java:91)

UnsupportedOperationException,不支持的操作?居然不支持List的add方法,这真是 奇怪了!还是来追根寻源,看看asList方法的源代码:

public static <T> List<T> asList(T...a) {

    return new ArrayLiet<T>(a);                             f

}

直接new 了一个ArrayList对象返回,难道ArrayList不支持add方法?不可能呀!可 能,问题就出在这个ArrayList类上,此ArrayList非java.util.ArrayList,而是Arrays工具类 的一个内置类,其构造函数如下所示:

//这是一个静态私有内部类

private static classArrayList<E> extends AbstractList<E>

implements RandomAccess,java.io.Serializable {

//存储列表元素的数组

private final E [] a;

//唯一的构造函数

ArrayList (E [] array) {

  if (array==null)

          throw newNullPointerException();

  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的设计有悖00设计原则,但这不在我们讨论的范围内,而且我们也无力回天)。

有些开发者特别喜欢通过如下方式定义和初始化列表:

List<String> names = Arrays • asList ("张三"," 李四",
" 王五");

一句话完成了列表的定义和初始化,看似很便捷,却深藏着重大隐患——列表长度无 法修改。想想看,如果这样一个List传递到一个允许add操作的方法中,那将会产生何种结 果?如果读者有这种习惯,请慎之戒之,除非非常自信该Lis只用于读操作。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: