定义
使用共享对象可有效地支持大量的细粒度的对象
细粒度对象
内部状态
- 对象可共享出来的信息,存储在享元对象内部并且不随环境的改变而改变。相当于细粒度对象公用的那一部分
外部状态
- 对象得以依赖的标记,是随环境改变而改变,不可以共享的状态。相当于细粒度对象个性化的部分
类图

- TrainTicket中的from和to即为内部状态
- showInfo传的bunk铺位即为外部状态,是人可以选择不一样的硬座、软座、上铺、下铺等
- TICKET_FACTORY即为内部存储工厂,以内部状态from->to存储共享对象,外部对象也是可以作为key的根据场景的不同做变换,达到共享的目的
应用场景
- 系统中存在大量的相识对象,内部状态与环境无关
- 需要线程池的场景
String
public static void main(String[] args) {
String s1 = "hello";//双引号中内容放到字符串常亮池内
String s2 = "hello";//s1已经声明,s1和s2持有都是hello的引用,hello存储在堆中
String s3 = "he" + "llo";//编译器优化 s3="hello" s1=s2=s3 hello的引用
String s4 = "hel" + new String("lo");//存储新的常量hel和lo,产生新的对象lo和hello,s4是新的对象hello
String s5 = new String("hello");//常量池hello已有,新的hello对象
//intern将内置加入常量池,进入常量池时已存在返回它的引用,没有加入并返回新的引用,这里相当
//于s6=s1=s2=s3 hello的引用
String s6 = s5.intern();
String s7 = "h";//新的常量池对象h引用
String s8 = "ello";//新的常量池对象 ello引用
String s9 = s7 + s8;//新的对象hello
System.out.println(s1==s2);//true
System.out.println(s1==s3);//true
System.out.println(s1==s4);//false
System.out.println(s1==s9);//false
System.out.println(s4==s5);//false
System.out.println(s1==s6);//true
}
- 用双引号声明的字符串会加入字符串常量池
- intern会将当前String的字符串加入常亮池,进入常量池时已存在返回它的引用,没有加入并返回新的引用
- 减轻了重复字符串在内存的存在
Integer
public static void main(String[] args) {
Integer a = Integer.valueOf(100);
Integer b = 100;
Integer c = Integer.valueOf(1000);
Integer d = 1000;
//a==b:true c==d:false Integer缓存了[-128,127]的数字
System.out.println("a==b:" + (a==b));
System.out.println("c==d:" + (c==d));
}
- 节省了最常用到数字的频繁创建
优缺点
- 优点
- 减少对象创建,降低内存,提高效率
- 减少内存之外的其他资源使用
- 缺点
- 增加复杂度,关注内外部状态
网友评论