包装类中的缓存设计(享元模式:Flyweight Pattern)

一. 引出包装类中的缓存设计

首先我们看一段神奇的代码:

class CacheDemo 
{
	public static void main(String[] args) 
	{	
		// 装箱:方式1
		Integer num1 = new Integer(123);
		Integer num2 = new Integer(123);
		System.out.println(num1==num2); // false

		//装箱:方式2
		Integer num3 = Integer.valueOf(123);
		Integer num4 = Integer.valueOf(123);
		System.out.println(num3==num4); // true

		// 自动装箱
		Integer num5 = 123;
		Integer num6 = 123;
		System.out.println(num5==num6); // true

		System.out.println("-------------------------------------");

		// 装箱:方式1
		Integer num11 = new Integer(250);
		Integer num22 = new Integer(250);
		System.out.println(num11==num22); // false

		//装箱:方式2
		Integer num33 = Integer.valueOf(250);
		Integer num44 = Integer.valueOf(250);
		System.out.println(num33==num44); // fasle

		// 自动装箱
		Integer num55 = 123;
		Integer num66 = 123;
		System.out.println(num55==num66); // true
	}
}
---------- 运行java ----------
false
true
true
-------------------------------------
false
false
true

输出完成 (耗时 0 秒) - 正常终止

为什么会出现以上结果,我们来逐个分析:

1. System.out.println(num1==num2); 

num1和num2是两个Integer对象,“==” 比较的是两个对象的地址,显然为false 

 2. System.out.println(num3==num4);

num3和num4是通过装箱方式2 valueOf来创建的,我们来看下valueOf的源码:

在这里插入图片描述 

缓存中的值 :-128 ≤ value ≤ 127,超过这个范围就会重新创建一个对象,而在我们代码中,num3和num4都为123,在这个范围内,因此,没有创建新的对象,所有num3==num4为true;

3. System.out.println(num5==num6); 

创建num5和num6采用的是自动装箱的方式,在之前讲解基本类型的包装类博客中提到,自动拆箱和装箱是一个语法糖/编译器级别新特性。在底层依然是手动装箱和拆箱操作。但是,装箱操作使用的是Integer.valueOf的方式,而不是直接new Integer。因此与2中方式相同,num5==num6结果页为true. 

4. System.out.println(num11==num22);

num11和num22是两个Integer对象,“==”比较的是两个对象的地址,显然为false。 

5. System.out.println(num33==num44); 

num33和num44的值为250,不再缓存范围[-128,127]内,因此num22和num33是两个不同的对象,显然为false。

6. System.out.println(num55==num66); 

原因同5

二. 包装类中的缓存 

包装类的缓存设计,又称为享元设计

就是创建一个缓存区(有限定大小的)来将重复使用的数据放进去,从而达到少占用内存空间的效果。

包装类缓存大小

除了Character包装类是:0-127之间,其余(Integer,Long等)都是-128-127之间。
一旦超过缓存空间,则系统会在堆内存中new一个新的对象出来。

包装类的缓存设计(享元模式),本质就是缓存设计:

Byte,Short,Integer,Long:缓存[-128,127]区间的数据;
Character:缓存[0,127]区间的数据.

1. Double中没有缓存

	Double d1 = 1.0;
	Double d2 = 1.0;
	System.out.println(d1==d2); // fasle

2. Float没有缓存

	Float f1 = 1.3f;
	Float f2 = 1.3f;
	System.out.println(f1==f2); // fasle

3. Character只对[0,127]具有数据缓存功能

	Character c1 = 1;
	Character c2 = 1;
	System.out.println(c1==c2); // true

4. Boolean数据缓存只有TRUE 和FALSE

	Boolean b1 = false;
	Boolean b2 = false;
	System.out.println(b1==b2);

总结:

Byte (缓存范围:[-128,127])
Short (缓存范围:[-128,127])
Long (缓存范围:[-128,127])
Integer (缓存范围:[-128,127])
Character (缓存范围:[0,127])
Boolean (全部缓存)
Float (没有缓存)
Doulbe (没有缓存)

三. 如何比较包装类型中的值

如果使用包装类存储的值超过缓存范围,如何比较它们值是否相同?

采用equals方法

	Integer num1 = 123;
	Integer num2 = 123;
	System.out.println(num1.equals(num2));

在之前的博文中,我们就已经讲到,子类都应该覆盖父类中(Object)的equals方法,从而比较我们想关心的数据。我们来看下Integer中equals方法,其实就是把包装类型进行了拆箱,然后比较基本数据类型的值。

在这里插入图片描述

所以,在今后我们比较包装类型的值时,统统采用equal方法。 

猜你喜欢

转载自blog.csdn.net/m0_50370837/article/details/124060356