不可变类
不可变类:指这个类的实例一旦创建完成后,就不能改变其成员变量值。如JDK内部自带的8个包装类和String类都是不可变类(Interger、Long和String等)都是不可变类。所以不可变类并不是指该类是被final修饰的,而是指该类的所有属性是被final修饰的。
可变类:相对于不可变类,可变类创建实例后可以改变其成员变量值,开发中创建的大部分类都属于可变类。
java中自定义不可变类应该遵守如下原则:
- 使用private和final修饰符来修饰该类的属性。
- 提供带参数的构造器,用于根据传入的参数来初始化属性。
- 仅为该类属性提供getter方法,不要提供setter方法。
- 如果有必要,重写hashCode和equals方法,同时应保证两个用equals方法判断为相等的对象,其hashCode也应相等。
使用不可变类的好处?
- Immutable对象是线程安全的,可以不用被synchronize就在并发环境中共享
- Immutable对象简化了程序开发,因为它无需使用额外的锁机制就可以在线程间共享
- Immutable对象提高了程序的性能,因为它减少了synchroinzed的使用
- Immutable对象是可以被重复使用的,你可以将它们缓存起来重复使用,就像字符串字面量和整型数字一样。你可以使用静态工厂方法来提供类似于valueOf()这样的方法,它可以从缓存中返回一个已经存在的Immutable对象,而不是重新创建一个。
immutable对象也有一个缺点就是会制造大量垃圾,由于他们不能被重用而且对于它们的使用就是”用“然后”扔“,字符串就是一个典型的例子,它会创造很多的垃圾,给垃圾收集带来很大的麻烦。当然这只是个极端的例子,合理的使用immutable对象会创造很大的价值。
不可变集合
1、JDK中实现immutable集合
在JDK中提供了Collections.unmodifiableXXX系列方法来实现不可变集合, 而jdk对不可变集合是通过抛出异常来实现的。但是存在一些问题,下面我们先看一个具体实例:
public class ImmutableTest {
@Test
public void testJDKImmutable(){
List<String> list=new ArrayList<String>();
list.add("a");
list.add("b");
list.add("c");
//通过list创建一个不可变的unmodifiableList集合
List<String> unmodifiableList=Collections.unmodifiableList(list);
System.out.println(unmodifiableList);
//通过list添加元素
list.add("ddd");
System.out.println("往list添加一个元素:"+list);
System.out.println("通过list添加元素之后的unmodifiableList:"+unmodifiableList);
//通过unmodifiableList添加元素
unmodifiableList.add("eee");
System.out.println("往unmodifiableList添加一个元素:"+unmodifiableList);
}
}
··············································································
运行结果:
[a, b, c]
往list添加一个元素:[a, b, c, ddd]
通过list添加元素之后的unmodifiableList:[a, b, c, ddd]
java.lang.UnsupportedOperationException
at java.util.Collections$UnmodifiableCollection.add(Collections.java:1055)
at dawn.thread.ImmutableTest.testJDKImmutable(ImmutableTest.java:31)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
通过运行结果我们可以看出:虽然unmodifiableList不可以直接添加元素,但是我的list是可以添加元素的,而list的改变也会使unmodifiableList改变。
所以说Collections.unmodifiableList实现的不是真正的不可变集合。
2、Guava的immutable集合
Guava提供了对JDK里标准集合类里的immutable版本的简单方便的实现,以及Guava自己的一些专门集合类的immutable实现。当你不希望修改一个集合类,或者想做一个常量集合类的时候,使用immutable集合类就是一个最佳的编程实践。
注意:每个Guava immutable集合类的实现都拒绝null值。我们做过对Google内部代码的全面的调查,并且发现只有5%的情况下集合类允许null值,而95%的情况下都拒绝null值。万一你真的需要能接受null值的集合类,你可以考虑用Collections.unmodifiableXXX。
immutable集合可以有以下几种方式来创建:
- 用copyOf方法, ImmutableSet.copyOf(set)
- 使用of方法,ImmutableSet.of("a", "b", "c")或者ImmutableMap.of("a", 1, "b", 2)
- 使用Builder类
Guava的immutale集合的简单使用
@Test
public void testGuavaImmutable(){
List<String> list=new ArrayList<String>();
list.add("a");
list.add("b");
list.add("c");
ImmutableList<String> imlist=ImmutableList.copyOf(list);
System.out.println("imlist:"+imlist);
ImmutableList<String> imOflist=ImmutableList.of("peida","jerry","harry");
System.out.println("imOflist:"+imOflist);
ImmutableSortedSet<String> imSortList=ImmutableSortedSet.of("a", "b", "c", "a", "d", "b");
System.out.println("imSortList:"+imSortList);
list.add("baby");
//关键看这里是否imlist也添加新元素了
System.out.println("list添加新元素之后看imlist:"+imlist);
ImmutableSet<Color> imColorSet =
ImmutableSet.<Color>builder()
.add(new Color(0, 255, 255))
.add(new Color(0, 191, 255))
.build();
System.out.println("imColorSet:"+imColorSet);
}
------------------------------------------------------------------------------
运行结果:
imlist:[a, b, c]
imOflist:[peida, jerry, harry]
imSortList:[a, b, c, d]
list添加新元素之后看imlist:[a, b, c]
imColorSet:[java.awt.Color[r=0,g=255,b=255], java.awt.Color[r=0,g=191,b=255]]
更智能的copyOf
copyOf方法比你想象的要智能,ImmutableXXX.copyOf会在合适的情况下避免拷贝元素的操作-先忽略具体的细节,但是它的实现一般都是很“智能”的。譬如:
@Test
public void testCotyOf(){
ImmutableSet<String> imSet=ImmutableSet.of("peida","jerry","harry","lisa");
System.out.println("imSet:"+imSet);
//set直接转list
ImmutableList<String> imlist=ImmutableList.copyOf(imSet);
System.out.println("imlist:"+imlist);
//list直接转SortedSet
ImmutableSortedSet<String> imSortSet=ImmutableSortedSet.copyOf(imSet);
System.out.println("imSortSet:"+imSortSet);
List<String> list=new ArrayList<String>();
for(int i=0;i<=10;i++){
list.add(i+"x");
}
System.out.println("list:"+list);
//截取集合部分元素
ImmutableList<String> imInfolist=ImmutableList.copyOf(list.subList(2, 8));
System.out.println("imInfolist:"+imInfolist);
}
----------------------------------------------------------------------------
运行结果:
imSet:[peida, jerry, harry, lisa]
imlist:[peida, jerry, harry, lisa]
imSortSet:[harry, jerry, lisa, peida]
list:[0x, 1x, 2x, 3x, 4x, 5x, 6x, 7x, 8x, 9x, 10x]
imInfolist:[2x, 3x, 4x, 5x, 6x, 7x]
ImmutableMap使用举例
public class ImmutableExample3 {
private final static ImmutableList<Integer> list = ImmutableList.of(1, 2, 3);
private final static ImmutableSet set = ImmutableSet.copyOf(list);
private final static ImmutableMap<Integer, Integer> map = ImmutableMap.of(1, 2, 3, 4);//map必须成对出现(偶数个)
private final static ImmutableMap<Integer, Integer> map2 = ImmutableMap.<Integer, Integer>builder().put(1, 2).put(3, 4).put(5, 6).build();
public static void main(String[] args) {
System.out.println(map2.get(3));
}
}
来源:oschina
链接:https://my.oschina.net/u/2634007/blog/2231250