Arrays.aslist新建的list集合不能add()、remove()你知道吗?

java.lang.UnsupportedOperationException
at java.util.AbstractList.add(AbstractList.java:148)
at java.util.AbstractList.add(AbstractList.java:108)
就像上一篇文章,有2个方法可以实现数组和list之间的转换,但是问题总是发生在你不知道的地方。
我领导兼同事,问我,你看看你那个new出来的list能不能add(),然后让我试一下。当然 ,在编写
代码的时候,你add()是没问题的,当代码跑起来的时候,哦嘿,出问题啦,抛异常啦。如上的异常。

然后

分析原因:
终其原因是Arrays.asList方法返回的ArrayList是继承自AbstractList同时实现了RandomAccess和Serializable接口,
定义如下:

	    public static <T> List<T> asList(T... a) {
        return new ArrayList<>(a);
    }

子类是正常的复写了2个方法 get(index) 和 set(index,element),这俩能正常用,但是,add()和remove()就抛异常了

	//。。。。
	    private static class ArrayList<E> extends AbstractList<E> implements RandomAccess, java.io.Serializable
	
	//我们再来看看AbstractList这个类的定义:
	public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> 
	
	//这时我们发现AbstractList这个类的set add remove方法定义如下:
	
        // 没被复写,使用的时候会抛异常的。
	    public void add(int index, E element) {
        throw new UnsupportedOperationException();
    }
       // 没被复写,会抛异常的。
	    public E remove(int index) {
        throw new UnsupportedOperationException();
    }
        // set方法被复写了,这个是正常的。
	    public E set(int index, E element) {
        throw new UnsupportedOperationException();
    }

现在知道了它throw UnsupportedOperationException异常的原因了。
直接扔异常。so知道啦。
通过上面的分析,我们知道,其实通过asList方法得到的List是只读的。
怎样避免这样的错误

	List<String> list = Lists.newArrayList(Arrays.asList(checkedData));//瓜娃的集合初始化的东西

在新建个集合来接收这个arrays new 出来的集合。就没有异常啦。也可以避免问题。

另外:

    private static void testArrayList() {
        int[] ints = {1, 2, 3, 4, 5};
        List list = Lists.newArrayList(Arrays.asList(ints));
        System.out.println("list's size is:" + list.size());
        System.out.println("list.get(0) 的类型:" + list.get(0).getClass());
        System.out.println("list.get(0) == ints:" + list.get(0).equals(ints));

        Integer[] ints_ = {1,2,3,4,5};
        List list_ = Arrays.asList(ints_);
        System.out.println("list_'size:" + list_.size());
        System.out.println("list_.get(0) 的类型:" + list_.get(0).getClass());
        System.out.println("list_.get(0) == ints_[0]:" + list_.get(0).equals(ints_[0]));
    }
	//测试结果如下:
	"C:\Program Files\Java\jdk1.8.0_73\bin\java"。。。
	list's size is:1
	list.get(0) 的类型:class [I
	list.get(0) == ints:true
	list_'size:5
	list_.get(0) 的类型:class java.lang.Integer
	list_.get(0) == ints_[0]:true

	Process finished with exit code 0

解释如下:
程序的运行结果并没有像我们预期的那样是5而是逆天的1,这是什么情况?
asList接受的参数是一个泛型的变长参数,我们知道基本数据类型是无法泛型化的,也就是说8个基本类型是无法作为asList的参数的, 要想作为泛型参数就必须使用其所对应的包装类型。但是这个这个实例中为什么没有出错呢?因为该实例是将int 类型的数组当做其参数,而在Java中数组是一个对象,它是可以泛型化的。所以该例子是不会产生错误的。既然例子是将整个int 类型的数组当做泛型参数,那么经过asList转换就只有一个int 的列表了
所以:
1.在使用asList时不要将基本数据类型当做参数。
2.得到是个不可操作的集合。

又更新了一下,之前的set是不会异常的,被正常复写了,get和set方法是被正常实现的,其他的比如add或者remove是不能用的。

 

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值