并发之不可变对象

什么是不可变对象

不可变对象:一个对象的状态在对象被创建之后就不再变化。不可变对象对于缓存是非常好的选择,因为你不需要担心它的值会被更改。

必须满足三个条件才可以称之为不可变对象

  1. 对象创建完成后其状态不可修改。(数据私有并且没有对状态的修改方法)
  2. 对象的所有域都是final不可变的.(也可以不是final的但是不能有指向可变域的引用逸出)
  3. 对象时正确创建的,即创建对象没有this对象逸出。

final介绍final finally finalize的区别

示例

final定义不可变对象

修饰成员变量

  1. @Slf4j
  2. public class finalExample {
  3. private final StringBuffer sb = new StringBuffer("Hello");
  4. @Test
  5. public void finalStringBufferTest(){
  6. sb.append(" World");
  7. log.info("{}",sb.toString());
  8. }
  9. private static final Map<Integer,Integer> map = new HashMap<>();
  10. static {
  11. map.put(1,2);
  12. map.put(2,3);
  13. map.put(3,4);
  14. }
  15. @Test
  16. public void finalMapTest(){
  17. log.info("{}",map.toString());
  18. map.put(5,1);
  19. log.info("{}",map.toString());
  20. }
  21. }

final修饰方法的形参

  1. private void finalTest(final int x){
  2. log.info("{}",x);
  3. }

其他不可变处理变量的方式

Collections工具包中unmodifiableMap方法

  1. public class OtherImmutableExample {
  2. private static Map<Integer,Integer> map = new HashMap<>();
  3. static {
  4. map.put(1,2);
  5. map.put(2,3);
  6. map.put(3,4);
  7. map = Collections.unmodifiableMap(map);
  8. }
  9. @Test
  10. public void collectionsTest(){
  11. map.put(1,3);
  12. }
  13. }

会抛出异常
谷歌的common里的immutable中的方法

  1. private static final ImmutableMap<Integer,Integer> imap = ImmutableMap.of(1,2);
  2. @Test
  3. public void immutableMapTest(){
  4. imap.put(1,3);
  5. }

会抛出异常

总结

不可变对象对于常规类型的不可变对象可以使用final修饰,对于集合相关的不可变对象可以使用java的collections或者谷歌的common处理。