第一个例子:
public class BetterAddressBook {
private final List names; public BetterAddressBook(List names) {
this.names = Collections.unmodifiableList(names);
}
public List getNames() {
return names;
}
}
BetterAddressBook book = new BetterAddressBook(Arrays.asList("Landau", "Weinberg", "Hawking"));
book.getNames().add(0, "Montana");
//BetterAddressBook是不可变的。Collections类库中的封装类可以确保一旦设置了names的值,就不能对它再有任何更新。
这个Collections.unmodifiableList到底做了什么事让names不能再被改变呢???第二个例子:
public class BetterAddressBook {
private final List names; public BetterAddressBook(List names) {
this.names = Collections.unmodifiableList(names);
}
public List getNames() {
return names;
}
}
List physicists = new ArrayList();
physicists.addAll(Arrays.asList("Landau", "Weinberg", "Hawking"));
BetterAddressBook book = new BetterAddressBook(physicists);
physicists.add("Einstein");
for (String name : book.getNames())
System.out.println(name);
为什么names可以被修改呢??请大家解释一下!!!
public class BetterAddressBook {
private final List names; public BetterAddressBook(List names) {
this.names = Collections.unmodifiableList(names);
}
public List getNames() {
return names;
}
}
BetterAddressBook book = new BetterAddressBook(Arrays.asList("Landau", "Weinberg", "Hawking"));
book.getNames().add(0, "Montana");
//BetterAddressBook是不可变的。Collections类库中的封装类可以确保一旦设置了names的值,就不能对它再有任何更新。
这个Collections.unmodifiableList到底做了什么事让names不能再被改变呢???第二个例子:
public class BetterAddressBook {
private final List names; public BetterAddressBook(List names) {
this.names = Collections.unmodifiableList(names);
}
public List getNames() {
return names;
}
}
List physicists = new ArrayList();
physicists.addAll(Arrays.asList("Landau", "Weinberg", "Hawking"));
BetterAddressBook book = new BetterAddressBook(physicists);
physicists.add("Einstein");
for (String name : book.getNames())
System.out.println(name);
为什么names可以被修改呢??请大家解释一下!!!
可以往里面增加数据啊 ,但是 你不能吧 names 重新指向即比如 List list = new ArrayList() ;
names = list ;//这样是会报错de但是 names.add((object)o) ;
没有改变 names执行的对象引用 ,即他还是原来的对象
返回指定列表的不可修改视图。此方法允许模块为用户提供对内部列表的“只读”访问。在返回的列表上执行的查询操作将“读完”指定的列表。试图修改返回的列表(不管是直接修改还是通过其迭代器进行修改)将导致抛出 UnsupportedOperationException。
第一个报错是因为,返回传入参数列表的一个不可以修改的视图。所以直接修改names报错。
第二个是对physicists修改,physicists是源数据,所以可以修改。大家都知道视图是根据源数据变化的。如果源数据更新,视图也会更新。
public class Book {
private String title;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}public class Library {
private final List books; public Library(List books) {
this.books = Collections.unmodifiableList(new ArrayList(books));
}
public List getBooks() {
return books;
}
}
Book book = new Book();
book.setTitle("Dependency Injection")
Library library = new Library(Arrays.asList(book));
library.getBooks().get(0).setTitle("The Tempest"); //mutates Library
每一个被依赖的对象也必须是不可变的
implements List<E> {
static final long serialVersionUID = -283967356065247728L;
final List<? extends E> list; UnmodifiableList(List<? extends E> list) {//看构造器
super(list);//这个父类只是判断 传进来的list是否为空
this.list = list;
} public boolean equals(Object o) {return o == this || list.equals(o);}
public int hashCode() {return list.hashCode();} public E get(int index) {return list.get(index);}
public E set(int index, E element) {
throw new UnsupportedOperationException();
}
public void add(int index, E element) {
throw new UnsupportedOperationException();
}
public E remove(int index) {
throw new UnsupportedOperationException();
}
public int indexOf(Object o) {return list.indexOf(o);}
public int lastIndexOf(Object o) {return list.lastIndexOf(o);}
public boolean addAll(int index, Collection<? extends E> c) {
throw new UnsupportedOperationException();
}
public ListIterator<E> listIterator() {return listIterator(0);} public ListIterator<E> listIterator(final int index) {
return new ListIterator<E>() {
ListIterator<? extends E> i = list.listIterator(index); public boolean hasNext() {return i.hasNext();}
public E next() {return i.next();}
public boolean hasPrevious() {return i.hasPrevious();}
public E previous() {return i.previous();}
public int nextIndex() {return i.nextIndex();}
public int previousIndex() {return i.previousIndex();} public void remove() {
throw new UnsupportedOperationException();
}
public void set(E e) {
throw new UnsupportedOperationException();
}
public void add(E e) {
throw new UnsupportedOperationException();
}
};
}
感觉对并发有一定的启示!
super(list);//这个父类只是判断 传进来的list是否为空
this.list = list;
}
把外面传进来的list赋值给了不可变的final List<? extends E> list;
这时确保了fianl list里面的对象不可变,但是不能确保对象里面的内容不可变呀!
什么不能省呢?请详说!
所以让 List names不能修改,应该方法被改了,执行下面三个方法就报异常。所以说names为什么不能添加,删除,还有set方法。
我开始以为UnmodifiableList 只是把系统的util包下的list 赋给names,导致理解错误,以为那一步是多余的,既然自己设置了final,为什么还要final list 赋给他,其实他是在list里面做了手脚。public E set(int index, E element) {
throw new UnsupportedOperationException();
}
public void add(int index, E element) {
throw new UnsupportedOperationException();
}
public E remove(int index) {
throw new UnsupportedOperationException();
}
但是我们讨论的重点不是在那,而是:
public class Book {
private String title;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}public class Library {
private final List books;public Library(List books) {
this.books = Collections.unmodifiableList(new ArrayList(books));
}
public List getBooks() {
return books;
}
}
Book book = new Book();
book.setTitle("Dependency Injection")
Library library = new Library(Arrays.asList(book));
library.getBooks().get(0).setTitle("The Tempest"); //mutates Library
既然UnmodifiableList重写了util.list,把我们传入的list修改成不能修改的视图了。但是后面
library.getBooks().get(0).setTitle("The Tempest"); //mutates Library却可以重新取得不可修改的视图重新修改里面的内容,原因是视图里面的内容是可以修改的!不知我理解是否有误,请指出。。
但是如果是脱离那个例子的话Integer本身跟String是不可修改的类了,所以就不能被修改了!
private final List names; public BetterAddressBook(List names) {
this.names=names;
}
public List getNames() {
return names;
}
public static void main(String s[]){
BetterAddressBook book = new BetterAddressBook(Arrays.asList("Landau", "Weinberg", "Hawking"));
List list1=book.getNames();
list1.add("asf");
System.out.print("over");
//如果
}
}路人看了也有个问题!为什么这个时候 不是返回不可变的视图了,但是依然不可以添加呢??
final修饰的内存地址不可改变 但是他的值是可以改变的
import java.util.*;
public class test{
private static List names = Arrays.asList("dfs","sdfs","sad");
public static void main(String[] args){
names.add("adf");
}
}那么原因有可能就在于Arrays.asList这里了,查看API,发现
public static <T> List<T> asList(T... a) 返回一个受指定数组支持的固定大小的列表。(对返回列表的更改会“直接写”到数组。)是不是设定了列表的大小了,不能再修改了所以应该问题是在Arrays.asList这里。。
所以
physicists.addAll(Arrays.asList("Landau", "Weinberg", "Hawking"));
BetterAddressBook book = new BetterAddressBook(physicists);
physicists.add("Einstein");
再用一个List包这一个不可修改的list,然后修改外面那个List,不知理解有误,请指出!
这个还回是一个ArrayList,不过不是java.util.ArrayList,是Arrays的一个内部内ArrayList,里面木有add方法,而且数据是存在一个final的数组中,我们知道ArrayList的存储本来就是数组存储,而且该数组可以改变引用。但是这里是final,不能改变引用,所以数组长度就得到了限制。
而且该ArrayList也没提供add,remove方法。只提供set,get方法。所以你那段代码会报错。UnsupportedOperationException