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是不能用的。


发布评论
IT序号网

微信公众号号:IT虾米 (左侧二维码扫一扫)欢迎添加!

Java String中理解起来模糊的东西,我来给我扫扫盲。(String类的intern() 、equal()、 == )知识解答
你是第一个吃螃蟹的人
发表评论

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。