1、不可變集合的優勢java
不可變對象有不少優勢,包括:編程
建立對象的不可變拷貝是一項很好的防護性編程技巧。Guava爲全部JDK標準集合類型和Guava新集合類型都提供了簡單易用的不可變版本。安全
摘自:http://ifeve.com/google-guava-immutablecollections/less
2、建立不可變集合ide
1.使用of方法工具
如:I測試
mmutableList<String> ilist = ImmutableList.of("a","b","c","d","e");ui
2.使用copyOfthis
如:google
List<String> slist = new ArrayList<String>(20);
slist.add("a");
slist.add("b");
slist.add("c");
slist.add("d");
slist.add("e");
//經過已有List建立不可變list
ImmutableList<String> ilist = ImmutableList.copyOf(slist);
3.使用Builder工具
如:
List<String> slist = new ArrayList<String>(20);
slist.add("a");
slist.add("b");
slist.add("c");
slist.add("d");
slist.add("e");
ImmutableList<String> ilist = ImmutableList.<String>builder().addAll(list).build();
3、如何實現不可變
1.對不可變集合調用addAll、add、set、remove都會拋出UnsupportedOperationException異常
以下是ImmutableList類的源碼:
/**
* Guaranteed to throw an exception and leave the list unmodified.
*
* @throws UnsupportedOperationException always
* @deprecated Unsupported operation.
*/
@CanIgnoreReturnValue
@Override
public final boolean addAll(int index, Collection<? extends E> newElements) {
throw new UnsupportedOperationException();
}
/**
* Guaranteed to throw an exception and leave the list unmodified.
*
* @throws UnsupportedOperationException always
* @deprecated Unsupported operation.
*/
@CanIgnoreReturnValue
@Deprecated
@Override
public final E set(int index, E element) {
throw new UnsupportedOperationException();
}
/**
* Guaranteed to throw an exception and leave the list unmodified.
*
* @throws UnsupportedOperationException always
* @deprecated Unsupported operation.
*/
@Deprecated
@Override
public final void add(int index, E element) {
throw new UnsupportedOperationException();
}
/**
* Guaranteed to throw an exception and leave the list unmodified.
*
* @throws UnsupportedOperationException always
* @deprecated Unsupported operation.
*/
@CanIgnoreReturnValue
@Deprecated
@Override
public final E remove(int index) {
throw new UnsupportedOperationException();
}
2.集合中存儲的可變對象仍可改變
Users[] arr = new Users[3];
arr[0] = new Users();
arr[0].setId(1);//id=1
arr[1] = new Users();
arr[1].setId(2);
arr[2] = new Users();
arr[2].setId(3);
//copyof 是淺拷貝,所以集合中存放可變對象時,原對象的屬性修改了,集合中對象的屬性也會修改
ImmutableList<Users> alist = ImmutableList.copyOf(arr);
arr[0].setId(5);
System.out.println(alist.get(0).getId());//id=5
4、源碼中有趣的地方
不可變集合能夠經過of方法來建立,of方法是包含12個重載方法以下:
@SuppressWarnings("unchecked")
public static <E> ImmutableList<E> of() {
return (ImmutableList<E>) EMPTY;
}
public static <E> ImmutableList<E> of(E element) {
return new SingletonImmutableList<E>(element);
}
public static <E> ImmutableList<E> of(E e1, E e2) {
return construct(e1, e2);
}
public static <E> ImmutableList<E> of(E e1, E e2, E e3) {
return construct(e1, e2, e3);
}
public static <E> ImmutableList<E> of(E e1, E e2, E e3, E e4) {
return construct(e1, e2, e3, e4);
}
public static <E> ImmutableList<E> of(E e1, E e2, E e3, E e4, E e5) {
return construct(e1, e2, e3, e4, e5);
}
public static <E> ImmutableList<E> of(E e1, E e2, E e3, E e4, E e5, E e6) {
return construct(e1, e2, e3, e4, e5, e6);
}
public static <E> ImmutableList<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7) {
return construct(e1, e2, e3, e4, e5, e6, e7);
}
public static <E> ImmutableList<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8) {
return construct(e1, e2, e3, e4, e5, e6, e7, e8);
}
public static <E> ImmutableList<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9) {
return construct(e1, e2, e3, e4, e5, e6, e7, e8, e9);
}
public static <E> ImmutableList<E> of(
E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9, E e10) {
return construct(e1, e2, e3, e4, e5, e6, e7, e8, e9, e10);
}
public static <E> ImmutableList<E> of(
E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9, E e10, E e11) {
return construct(e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11);
}
// These go up to eleven. After that, you just get the varargs form, and
// whatever warnings might come along with it. :(
@SafeVarargs // For Eclipse. For internal javac we have disabled this pointless type of warning.
public static <E> ImmutableList<E> of(
E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9, E e10, E e11, E e12, E... others) {
Object[] array = new Object[12 + others.length];
array[0] = e1;
array[1] = e2;
array[2] = e3;
array[3] = e4;
array[4] = e5;
array[5] = e6;
array[6] = e7;
array[7] = e8;
array[8] = e9;
array[9] = e10;
array[10] = e11;
array[11] = e12;
System.arraycopy(others, 0, array, 12, others.length);
return construct(array);
}
java方法是支持可變參數的,徹底能夠寫成,public static <E> ImmutableList<E> of(E... others);這樣實現的緣由大神在註釋中給出了,爲了不調用者處理類型檢測警告。
當方法聲明爲泛型可變參數時,調用該方法時,編譯器就會提示該警告,在JDK1.6以前,能夠在方法調用的地方添加@SuppressWarnings("unchecked")註解,但這樣比較麻煩,項目組每一個調用的地方都須要處理,固然也能夠忽略這個問題。
此處ImmutableList中of方法的12個重載的前11個就是爲了儘可能減小類型檢測警告,大神仍是很貼心滴爲咱們寫了11個重載,而第12個方法經過JDK1.7的新註解@SafeVarargs 來避免類型檢測警告。
@SafeVarargs的用法請參考:http://book.51cto.com/art/201205/339154.htm