【多线程:设计模式】享元模式
01.介绍
保护性拷贝介绍
我之前的一篇文章浅显的模拟过String类 当时是为了探究为什么String类是不可变类型 文章地址在
https://blog.csdn.net/m0_71229547/article/details/125757561?spm=1001.2014.3001.5502
里面重要的结论就是 因为value数组是final修饰的 导致地址引用不可改变 所以Sting类的赋值 或者 获取子类的这种方法 其实都是再新new一个对象 然后返回,所以String类每次操作后返回的对象都是新的对象所以不可变,大家也可以看一下String类的substring方法
可以看出substring方法也是返回一个新的对象,这种通过创建副本对象来避免共享的手段称之为 保护性拷贝。
享元模式介绍
保护性拷贝会出现说明问题就是如果对String类操作过多 势必会创建出非常多的对象 很显然是不合适的,所以出现了享元模式 它的使用场景是 当需要重用的数量有限的同一类对象时,例如我们的字符串 假如某个字符串已经有了 我们可以直接用这个字符串对象 而不用再重写创建一个
02.享元模式在常见类中的体现
包装类
在jdk中 Boolean Byte Short Integer Long Character等包装类提供了valueOf()方法 例如Long的valueOf会缓存-128-127之间的Long对象,在这个范围之间会重用对象,大于这个范围,才会新建Long对象
注意
1.Byte Short Long缓存的范围都是-128-127
2.Character缓存的范围是0-127
3.Integer的默认范围是-128-127最小值不能变 但是最大值可以通过调整虚拟机参数 -Djava.lang.Integer.IntergerCache.high来改变
4.Boolean缓存了TRUE和FALSE
String类
String类是我们日常使用中最常用的类 所以它的优化很重要,在JVM中有一个字符串常量池,具体场景是这样
String a = "ss"; // 如果"ss"还没有创建 就创建 并且缓存到字符串常量池
String b = "ss"; // 如果创建过了 就从字符串常量池中获取"ss"的地址 并赋值给b
验证1
public class TestXYMS {
public static void main(String[] args) {
String a = new String("ss");
String b = new String("ss");
System.out.println(a == b);
}
}
结果
false
解释
此时我们都是通过new来创建 并没有从字符串常量池中获取 所以为false
验证2
public class TestXYMS {
public static void main(String[] args) {
String a = "ss";
String b = "ss";
System.out.println(a == b);
}
}
结果
true
解释
a = "ss" 创建了"ss"对象 并缓存到了常量池,b = "ss" 从常量池中获取
验证3
public class TestXYMS {
public static void main(String[] args) {
String t = new String("ss");
String a = t.intern(); // 从常量池中获取t的值
String b = "ss";
System.out.println(a == b);
}
}
结果
true
解释
new String("ss")后 "ss"缓存到字符串常量池 然后通过t.intern()可以从常量池获取到,通过b = "ss"也可以获取