目录
- 一、不可变对象
-
- 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
实现不可变对象
final
1. final
的使用
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***()
类实现不可变对象
Collections.Unmodifiable***()
1. Collections.Unmodifiable***()
介绍
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()
的源码如下:
- 首先将传入的map对象传入
对象的构造方法中,创建出UnmodifiableMap
对象来UnmodifiableMap
public static <K,V> Map<K,V> unmodifiableMap(Map<? extends K, ? extends V> m) {
return new UnmodifiableMap<>(m);
}
- 在
对象中,对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***
类实现不可变对象
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并发编程学习系列
如有帮助,烦请点赞收藏一下啦 (◕ᴗ◕✿)