java并发编程——不可变对象

不可变类

不可变类:指这个类的实例一旦建立完成后,就不能改变其成员变量值。如JDK内部自带的8个包装类和String类都是不可变类(Interger、Long和String等)都是不可变类。因此不可变类并非指该类是被final修饰的,而是指该类的全部属性是被final修饰的java

可变类:相对于不可变类,可变类建立实例后能够改变其成员变量值,开发中建立的大部分类都属于可变类。编程

java中自定义不可变类应该遵照以下原则:缓存

  1. 使用private和final修饰符来修饰该类的属性。
  2. 提供带参数的构造器,用于根据传入的参数来初始化属性。
  3. 仅为该类属性提供getter方法,不要提供setter方法。
  4. 若是有必要,重写hashCode和equals方法,同时应保证两个用equals方法判断为相等的对象,其hashCode也应相等。

使用不可变类的好处?安全

  1. Immutable对象是线程安全的,能够不用被synchronize就在并发环境中共享
  2. Immutable对象简化了程序开发,由于它无需使用额外的锁机制就能够在线程间共享
  3. Immutable对象提升了程序的性能,由于它减小了synchroinzed的使用
  4. Immutable对象是能够被重复使用的,你能够将它们缓存起来重复使用,就像字符串字面量和整型数字同样。你可使用静态工厂方法来提供相似于valueOf()这样的方法,它能够从缓存中返回一个已经存在的Immutable对象,而不是从新建立一个。

immutable对象也有一个缺点就是会制造大量垃圾,因为他们不能被重用并且对于它们的使用就是”用“而后”扔“,字符串就是一个典型的例子,它会创造不少的垃圾,给垃圾收集带来很大的麻烦。固然这只是个极端的例子,合理的使用immutable对象会创造很大的价值。并发

不可变集合

一、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改变。ui

因此说Collections.unmodifiableList实现的不是真正的不可变集合。线程

二、Guava的immutable集合

Guava提供了对JDK里标准集合类里的immutable版本的简单方便的实现,以及Guava本身的一些专门集合类的immutable实现。当你不但愿修改一个集合类,或者想作一个常量集合类的时候,使用immutable集合类就是一个最佳的编程实践。code

注意:每一个Guava immutable集合类的实现都拒绝null值。咱们作过对Google内部代码的全面的调查,而且发现只有5%的状况下集合类容许null值,而95%的状况下都拒绝null值。万一你真的须要能接受null值的集合类,你能够考虑用Collections.unmodifiableXXX。对象

immutable集合能够有如下几种方式来建立:

  1. 用copyOf方法, ImmutableSet.copyOf(set)
  2. 使用of方法,ImmutableSet.of("a", "b", "c")或者ImmutableMap.of("a", 1, "b", 2)
  3. 使用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));
    }
}
相关文章
相关标签/搜索