天天看点

Java并发编程——不可变对象一、不可变对象二. final实现不可变对象三. Collections.Unmodifiable***()类实现不可变对象四. guava:Immutable***类实现不可变对象

目录

  • 一、不可变对象
    • 1. 不可变对象需要满足的条件:
    • 2.具体来说可以通过以下策略来实现:
  • 二. `final`实现不可变对象
    • 1. `final`的使用
  • 三. `Collections.Unmodifiable***()`类实现不可变对象
    • 1.`Collections.Unmodifiable***()`介绍
      • 2. 实现原理,以`Collections.unmodifiableMap()为例
  • 四. `guava:Immutable***`类实现不可变对象
    • Java并发编程学习系列

一、不可变对象

1. 不可变对象需要满足的条件:

  • 对象创建以后其状态就不能修改;
  • 对象所有的域都是final类型;
  • 对象是正确创建的(在创建期间,this引用没有逸出)

2.具体来说可以通过以下策略来实现:

  • 将类声明成final,那么该类就无法被继承了;
  • 将所有的成员设置成

    private

    属性,使外界不能直接访问成员变量;
  • 设置成员变量不提供

    setter()

    方法,并将成员变量声明成

    final

    属性,使成员变量只能被赋值一次;
  • 通过构造器初始化所有成员,进行深度拷贝;
  • 在成员变量的

    getter()

    方法中,不直接返回变量本身,而是克隆对象,并返回对象得到拷贝;

不可变对象的实现可以参考String对象的实现;

二.

final

实现不可变对象

1.

final

的使用

final关键字主要用于修饰类、方法、变量:

  • 修饰类:该类则无法被继承;
  • 修饰方法:锁定方法不能被继承类修改;提高使用效率
  • 修饰变量:

    如果是修饰基本数据类型变量,那么一旦初始化后,该变量就不能被修改了;

    如果是修饰引用类型变量,那么一旦初始化后,该变量就不能被指向另外的对象,但是依然可以修改该对象内部的值

    如代码所示:

@Slf4j
public class ImmutableExample1 {

    private final static Integer a=1;
    private final static String b="2";
    //线程不安全的map
    private final static Map<Integer,Integer> map = Maps.newHashMap();

    static {
        map.put(1,2);
        map.put(3,4);
        map.put(5,6);
    }

    public static void main(String[] args) {
//        a=2;  //编译报错
//        b=3;  //编译报错
        map.put(1,10);
        log.info("{}",map.get(1));
    }

 }
           

三.

Collections.Unmodifiable***()

类实现不可变对象

1.

Collections.Unmodifiable***()

介绍

通过将

Collection

List

Set

Map

类型的变量,放入指定的

Collections.Unmodifiable***()

方法中,那么该引用型变量内部的值,初始化后将不允许再次被修改;

@Slf4j
@ThreadSafe
public class ImmutableExample2 {

    private final static Integer a=1;
    private final static String b="2";
    private static Map<Integer,Integer> map = Maps.newHashMap();

    static {
        map.put(1,2);
        map.put(3,4);
        map.put(5,6);
        //将map放入Collections.unmodifiableMap()方法中
        map = Collections.unmodifiableMap(map);
    }

    public static void main(String[] args) {
        //尽管编译不出错,但是执行会抛出异常
        map.put(1,10);
        log.info("{}",map.get(1));
    }

 }
           

代码运行结果:

Exception in thread "main" java.lang.UnsupportedOperationException
	at java.util.Collections$UnmodifiableMap.put(Collections.java:1457)
	at com.mmall.concurrency.example.immutable.ImmutableExample2.main(ImmutableExample2.java:32)

Process finished with exit code 1
           

2. 实现原理,以`Collections.unmodifiableMap()为例

unmodifiableMap()

的源码如下:

  1. 首先将传入的map对象传入

    UnmodifiableMap

    对象的构造方法中,创建出

    UnmodifiableMap

    对象来
public static <K,V> Map<K,V> unmodifiableMap(Map<? extends K, ? extends V> m) {
        return new UnmodifiableMap<>(m);
    }
           
  1. UnmodifiableMap

    对象中,对

    UnmodifiableMap

    对象进行的更新、修改、移除等操作,全部被设置成了抛异常操作,源码如下:
public V put(K key, V value) {
            throw new UnsupportedOperationException();
        }
        public V remove(Object key) {
            throw new UnsupportedOperationException();
        }
        public void putAll(Map<? extends K, ? extends V> m) {
            throw new UnsupportedOperationException();
        }
        public void clear() {
            throw new UnsupportedOperationException();
        }
           

四.

guava:Immutable***

类实现不可变对象

具体代码示例如下:

public class ImmutableExample3 {

    private final static ImmutableList list = ImmutableList.of(1,2,3);

    private final static ImmutableSet set = ImmutableSet.copyOf(list);

    //ImmutableMap初始化时,需要成对输入参数
    private final static ImmutableMap<Integer,Integer> map1 = ImmutableMap.of(1,2,3,4,5,6);

    //ImmutableMap第二种初始化方式先调用builder()方法,然后每插一条数据,就调用一次put(key,value)方法,最后调用build()结束
    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) {
//        list.add(2);  //不能添加元素,执行会抛出异常
//        set.add(2);  //不能添加元素,执行会抛出异常
        map1.put(1,4); //不能添加元素,执行会抛出异常
    }
}
           

Java并发编程学习系列

如有帮助,烦请点赞收藏一下啦 (◕ᴗ◕✿)

继续阅读