问题发掘:
//1.1将数组对象转成List数据结构之后,竟然不能进行增删操作了 //1.2我们将字符串数组的第三个对象的值修改为4,但是很奇怪在打印List的时候,发现List也发生了变化。(注:strings已经赋值完后,在修改数组的值) |
private static void asListAdd(){
String[] arr = {"1", "2", "3"};
List<String> strings = new ArrayList<>(Arrays.asList(arr));
arr[2] = "4";
System.out.println(strings.toString());
Iterator<String> iterator = strings.iterator();
while (iterator.hasNext()){
if ("4".equals(iterator.next())){
iterator.remove();
}
}
strings.forEach(val ->{
strings.remove("4");
strings.add("3");
});
System.out.println(Arrays.asList(arr).toString());
}
//结果:[1, 2, 4]
//报错:
/**
Exception in thread "main" java.lang.UnsupportedOperationException at java.util.AbstractList.remove(AbstractList.java:161) at java.util.AbstractList$Itr.remove(AbstractList.java:374) at java.util.AbstractCollection.remove(AbstractCollection.java:293) at JavaBase.List.AsListTest.lambda$asListAdd$0(AsListTest.java:47) at java.util.Arrays$ArrayList.forEach(Arrays.java:3880) at JavaBase.List.AsListTest.asListAdd(AsListTest.java:46) at JavaBase.List.AsListTest.main(AsListTest.java:20)
*/产生原因:
2.1/** 初始化一个字符串数组,将字符串数组转换为 List,在遍历List的时候进行移除和新增的操作 抛出异常信息UnsupportedOperationException。 根据异常信息java.lang.UnsupportedOperationException,我们看到他是从AbstractList里面出来的,让我们进入源码一看究竟 我们在什么时候调用到了这个 AbstractList 呢? 其实 Arrays.asList(arr) 返回的 ArrayList 不是 java.util.ArrayList,而是 Arrays的内部类 ArrayList没有实现 AbstractList 中的 add() 和 remove() 方法,这里就很清晰了为什么不支持新增和删除,因为根本没有实现。 */ |
private static class ArrayList<E> extends AbstractList<E>
implements RandomAccess, java.io.Serializable{
private static final long serialVersionUID = -2764017481108945198L;
private final E[] a;
ArrayList(E[] array) {
a = Objects.requireNonNull(array);
}
@Override
public E get(int index) {}
@Override
public E set(int index, E element) {...}
...
}
public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> {
public boolean add(E e) {
add(size(), e);
return true;
}
public void add(int index, E element) {
throw new UnsupportedOperationException();
}
public E remove(int index) {
throw new UnsupportedOperationException();
}
}2.2/** 对原始数组的修改会影响到我们获得的那个List 一不小心修改了父List,却影响到了子List,在业务代码中,这会导致产生的数据发生变化,严重的话会造成影响较大的生产问题。 第二个坑的源码中,完成字符串数组转换为List之后, 我们将字符串数组的第三个对象的值修改为4,但是很奇怪在打印List的时候,发现List也发生了变化。 */ /** asList中创建了 ArrayList,但是他直接引用了原本的数组对象 所以只要原本的数组对象一发生变化,List也跟着变化 所以在使用到引用的时候,我们需要特别的注意。 */ |
public static <T> List<T> asList(T... a) {
return new ArrayList<>(a);
}
ArrayList(E[] array) {
a = Objects.requireNonNull(array);
}3. 解决思路:
//重新new一个新的 ArrayList 返回 ListList strings = new ArrayList<>(Arrays.asList(arr)); |