个人主页:金鳞踏雨
个人简介:大家好,我是金鳞,一个初出茅庐的Java小白
目前状况:22届普通本科毕业生,几经波折了,现在任职于一家国内大型知名日化公司,从事Java开发工作
我的博客:这里是CSDN,是我学习技术,总结知识的地方。希望和各位大佬交流,共同进步 ~
一、什么是自动拆箱?
自动将基本数据类型转换为包装器类型。
Integer i = 56;//底层执行了:Integer i = Integer.valueOf(56);
数值 56 是基本数据类型 int,当赋值给包装器类型(Integer)变量的时候,触发自动装箱操作,创建一个 Integer 类型的对象,并且赋值给变量 i。
二、什么是自动装箱?
自动将包装器类型转化为基本数据类型。
int j = i; //底层执行了:int j = i.intValue();
当把包装器类型的变量 i,赋值给基本数据类型变量 j 的时候,触发自动拆箱操作,将 i 中的数据取出,赋值给 j。
三、为什么需要自动拆箱和自动装箱?
自动拆箱避免了手动调用 intValue()或类似方法来获取基本数据类型的值,使代码更简洁。
自动装箱允许我们将基本数据类型直接赋值给包装类对象,而不需要显式地创建对象。
自动拆箱(Auto-unboxing)和自动装箱(Auto-boxing)的主要目的是为了在基本数据类型(如int、double等)和它们的包装类(如Integer、Double等)之间实现自动转换,以简化编程和提高代码可读性。
四、在源码中的使用
我们可以直接看一下下面的这个例子:
Integer i1 = 56;
Integer i2 = 56;
Integer i3 = 129;
Integer i4 = 129;
System.out.println(i1 == i2); // true
System.out.println(i3 == i4); // false
输出的结果:
一个 true,一个 false
是不是很奇怪?似乎有点匪夷所思。
但实际上,这正是因为 Integer 用到了享元模式来复用对象,才导致了这样的运行结果。当我们通过自动装箱,也就是调用 valueOf() 来创建 Integer 对象的时候,如果要创建的 Integer 对象的值在 -128 到 127 之间,会从 IntegerCache 类中直接返回,否则才调用 new 方法创建。
简单的说,如果值在(-128 ~ 127)之间,不会创建对象,而是复用"缓存"中的对象。
Integer 的 valueOf()
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
Integer 的 静态内部类 IntegerCache
private static class IntegerCache {
static final int low = -128;
static final int high;
static final Integer cache[];
static {
// high value may be configured by property
int h = 127;
String integerCacheHighPropValue =
sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
if (integerCacheHighPropValue != null) {
try {
int i = parseInt(integerCacheHighPropValue);
i = Math.max(i, 127);
// Maximum array size is Integer.MAX_VALUE
h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
} catch( NumberFormatException nfe) {
// If the property cannot be parsed into an int, ignore it.
}
}
high = h;
cache = new Integer[(high - low) + 1];
int j = low;
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);
// range [-128, 127] must be interned (JLS7 5.1.7)
assert IntegerCache.high >= 127;
}
private IntegerCache() {}
}
这里的 IntegerCache 相当于,生成享元对象的工厂类,只不过名字不叫 xxxFactory 而已。这个类是 Integer 的内部类。
为什么 IntegerCache 只缓存 -128 到 127 之间的整型值呢?
在 IntegerCache 的代码实现中,当这个类被加载的时候,缓存的享元对象会被集中一次性创建好。
但是,毕竟整型值太多了,我们不可能在 IntegerCache 类中预先创建好所有的整型值,这样既占用太多内存,也使得加载 IntegerCache 类的时间过长。所以,我们只能选择缓存对于大部分应用来说最常用的整型值,也就是一个字节的大小(-128 到 127 之间的数据)。
不妨再看一个例子:
Integer a = new Integer(123);
Integer a = 123;
Integer a = Integer.valueOf(123);
- 第一种创建方式并不会使用到 IntegerCache
- 而后面两种创建方法可以利用 IntegerCache 缓存,返回共享的对象,以达到节省内存的目的
举一个极端一点的例子,假设程序需要创建 1 万个 -128 ~ 127 之间的 Integer 对象。
使用第一种创建方式,我们需要分配 1 万个 Integer 对象的内存空间;使用后两种创建方式,我们最多只需要分配 256 个 Integer 对象的内存空间。
文章到这里就结束了,如果有什么疑问的地方,可以在评论区指出~
希望能和大佬们一起努力,诸君顶峰相见
再次感谢各位小伙伴儿们的支持!!!