不可变对象-final

final关键字:

  • 修饰类:不能被继承(所有的方法都会隐式的标注为final)
  • 修改方法:1.锁定方法不被继承类修改 2.效率(已经忽略) private方法会隐式的标注为final方法
  • 修饰变量:基本类型变量初始化之后不能被修改
    引用类型变量,被初始化之后,不能再指向其他的对象

@Slf4j
public class immutableExample {
  private static final Integer anInt = 1;
  private static final String s = "s";
  private static final int i = 1;
  private static final Map<Integer, Integer> map = Maps.newHashMap();

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

  public static void main(String[] args) {
    // anInt =2;
    //   i  = 2;
    // map = Maps.newHashMap();//不能修改引用地址
    map.put(1, 9);//可以修改引用地址中的值
    log.info("{}", map.get(1));
  }
}

除了final 还有哪些不可变对象

@Slf4j
public class immutableExample2 {

  private static Map<Integer, Integer> map = Maps.newHashMap();

  static {
    map.put(1, 2);
    map.put(2, 3);
    map = Collections.unmodifiableMap(map);
  }

  public static void main(String[] args) {
    map.put(1, 9); // 修改引用地址中的值会抛出异常
    log.info("{}", map);
  }
}

immutableExample2

@Slf4j
public class immutableExample3 {

  private static ImmutableList<Integer> immutableList = ImmutableList.of(1, 2, 3);
  private static ImmutableMap<String, String> immutableMap = ImmutableMap.of("name", "xmc000");
  private static ImmutableMap<String, String> map =
      ImmutableMap.<String, String>builder().put("name", "xmc000").build();

  public static void main(String[] args) {
    map.put("sex", "1");
    ImmutableSet<Integer> set = ImmutableSet.copyOf(immutableList);
    set.add(4);
    boolean add = immutableList.add(4);
    immutableMap.put("sex", "1");
  }
}

Q:是否应该将类似HashMap集合做出不可变?

如果一个hashmap被多个线程共享且不会修改,是特别建议设计成不可变的。有时作为参数传给别人,但是又不希望被修改时,也可以考虑设计成不可变对象。

设计成不可变主要是防止多个线程修改却没同步措施导致线程不安全,因此单线程使用时不需要刻意去做成不可变(比如局部变量),同时对于需要不断变化的,这时设置成不可变明显不太合适,这时使用线程安全的hashmap更好些(课程里后面会介绍的concurrentHashMap,或者加上同步处理)