不可变对象
一,不可变对象的需要满足的条件
1.对象创建以后其状态就不能修改
2.对象的所有域都是final类型
3.对象是正确创建的(对象创建期间,this引用没有逸出)
二,可以采用的方式:
1.将类设置为final,该类不能被继承
2.将所有的成员声明为私有的,这样就不运行直接访问这些成员
3.对变量不提供setter方法,将所有可变的成员声明为final,这样只能对他们赋值一次,通过构造器初始化所有成员,
进行深度拷贝。在getter方法中不直接返回对象本身,而是克隆对象,并返回对象的拷贝
可以参考String类的设计
三,final关键字
1.final修饰类:类不能被继承。比如String,Integer,Long等
final类中成员可以根据需要设置为final.
final类中的所有成员方法都会被隐式的指定为final方法
2.final修饰方法
使用final方法的原因:
1.锁定方法不被继承类修改
2.效率,在早期的java实现版本中,会将final方法转为内嵌调用,但是如果方法过于庞大,效率并不会提高。
在最近的java版本中,不需要再使用final方法来进行优化了
注意:一个类的private方法会被隐式的指定为final方法
3.final修饰变量
1.修饰基本数据类型变量:数值一旦在初始化后,就不能再修改了
2.修饰引用类型的变量:对其初始化后,便不能再让他指向另外一个对象
public class ImmutableExample1 { private final static Integer a = 1; private final static String b = "2"; 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 = Maps.newHashMap(); map.put(1, 3); log.info("{}", map.get(1)); } private void test(final int a) { // a = 1; } }
四,其他的方法来实现不可变对象
1.Collections包中,提供了以unmodifiableXXX开头的对象 :Collection,List,Set,Map
Collections.unmodifiableXXX:Collection,List,Set,Map
2.谷歌的guava包里也提供了一些类
ImmutableXXX:Collection,List,Set,Map
所以我们在声明ImmutableList类的实例的时候,只需要调用初始化方法就可以了,一旦初始化完成,就不在进行修改
添加依赖:
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>20.0</version>
</dependency>
3.例子:
private static Map<Integer,Integer> map = new HashMap();
map.put(1,1);
map.put(2,2);
map.Collections.unmodifiableMap(map);//声明map不可变
map.put(1,3);//这一行代码执行时会报错
public class ImmutableExample2 { 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); } public static void main(String[] args) { map.put(1, 3); log.info("{}", map.get(1)); } }
4.原理(源码分析)
内部重新实现了创建了一个不可边Map:unmodifiableMap
public static <K,V> Map<K,V> unmodifiableMap(Map<? extends K, ? extends V> m) {
return new UnmodifiableMap<>(m);
}
在Map初始化的时候,把值复制到内部不可变的Map中,并规定这个不可边的集合里所有的修改方法都抛出异常
@Override
public boolean remove(Object key, Object value) {
throw new UnsupportedOperationException();
}
5.Immutable类的使用例子
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); 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)); } }
原文:https://www.cnblogs.com/inspred/p/9520900.html