java装箱操作和拆箱操作的学习
基本数据类型和包装器类型
Java为每种基本数据类型都提供了对应的包装器类型
基本类型 | 包装器类型 |
---|---|
int(4字节) | Integer |
byte(1字节) | Byte |
short(2字节 | Short |
long(8字节) | Long |
float(4字节) | Float |
double(8字节) | Double |
char(2字节) | Character |
boolean(未定) | Boolean |
装箱操作和拆箱操作
装箱:基本类型转变为包装器类型的过程。
拆箱:包装器类型转变为基本类型的过程。
//JDK1.5之前是不支持自动装箱和自动拆箱的,定义Integer对象,必须
Integer i = new Integer(8);
//JDK1.5开始,提供了自动装箱的功能,定义Integer对象可以这样
Integer i = 8;//自动装箱
int n = i;//自动拆箱
装箱是通过调用包装器类的 valueOf() 方法实现的
拆箱是通过调用包装器类的 xxxValue() 方法实现的,xxx代表对应的基本数据类型。
例如:
int装箱的时候自动调用Integer的valueOf(int)方法;
Integer拆箱的时候自动调用Integer的intValue方法。
Integer
我们来看下面的问题
Integer i1=127;
Integer i2=127;
System.out.println(i1==i2);
Integer i3=128;
Integer i4=128;
System.out.println(i3==i4);
输出结果:true
false
原因分析:看下面的源码,Integer的valueOf()方法创建Integer对象的时候,如果数值在[-128,127]之间,便返回指向IntegerCache.cache中已经存在的对象的引用;否则创建一个新的Integer对象。
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
通过观察IntegerCache 的源码我们发现使用的是静态工厂方法维持一个Integer数组,这种思想在很多源码中都有体现,它的好处在于不必每次新建一个对象。
private static class IntegerCache {
static final int high;
static final Integer cache[];
static {
final int low = -128;
// high value may be configured by property
int h = 127;
if (integerCacheHighPropValue != null) {
// Use Long.decode here to avoid invoking methods that
// require Integer's autoboxing cache to be initialized
int i = Long.decode(integerCacheHighPropValue).intValue();
i = Math.max(i, 127);
// Maximum array size is Integer.MAX_VALUE
h = Math.min(i, Integer.MAX_VALUE - -low);
}
high = h;
cache = new Integer[(high - low) + 1];
int j = low;
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);
}
private IntegerCache() {}
}
Double
再看一个问题
Double i1 = 100.0;
Double i2 = 100.0;
Double i3 = 200.0;
Double i4 = 200.0;
System.out.println(i1==i2);
System.out.println(i3==i4);
输出结果:false
false
原因分析:看下面的源码就知道了
在这里只解释一下为什么Double类的valueOf方法会采用与Integer类的valueOf方法不同的实现。很简单:在某个范围内的整型数值的个数是有限的,而浮点数却不是。
public static Double valueOf(double d) {
return new Double(d);
}
Boolean
再看一个问题
Boolean i1 = false;
Boolean i2 = false;
Boolean i3 = true;
Boolean i4 = true;
System.out.println(i1==i2);
System.out.println(i3==i4);
输出结果:true
true
Boolean的valueOf方法的具体实现
public static Boolean valueOf(boolean b) {
return (b ? TRUE : FALSE);
}
TRUE 和FALSE是Boolean类中定义的2个静态成员属性:
/**
* The {@code Boolean} object corresponding to the primitive
* value {@code true}.
*/
public static final Boolean TRUE = new Boolean(true);
/**
* The {@code Boolean} object corresponding to the primitive
* value {@code false}.
*/
public static final Boolean FALSE = new Boolean(false);
注意,Integer、Short、Byte、Character、Long这几个类的valueOf方法的实现是类似的。
Double、Float的valueOf方法的实现是类似的。
Short
public static Short valueOf(short s) {
final int offset = 128;
int sAsInt = s;
if (sAsInt >= -128 && sAsInt <= 127) { // must cache
return ShortCache.cache[sAsInt + offset];
}
return new Short(s);
}
注意,Integer、Short、Byte、Character、Long这几个类的valueOf方法的实现是类似的。
Double、Float的valueOf方法的实现是类似的。
Long
public static Long valueOf(long l) {
final int offset = 128;
if (l >= -128 && l <= 127) { // will cache
return LongCache.cache[(int)l + offset];
}
return new Long(l);
}
注意,Integer、Short、Byte、Character、Long这几个类的valueOf方法的实现是类似的。
Double、Float的valueOf方法的实现是类似的。
Float
public static Float valueOf(float f) {
return new Float(f);
}
其它注意事项
1、Boolean 的两个值 true 和 false 都是 cache 在内存中的,无须做任何改造,自己 new Boolean 是另外一块空间。
2、Byte 的 256 个值全部 cache 在内存中,和自己 new Byte 操作得到的对象不是一块空间。
3、Short、Long 两种类型的 cache 范围为-128~127,无法调整最大尺寸,即没有设置,代码中完全写死,如果要扩展,需自己来做。
4、Float、Double 没有 cache,要在实际场景中 cache 需自己操作,例如,在做图纸尺寸时可以将每种常见尺寸记录在内存中。
5、当 Integer 与 int 类型进行比较的时候,会将 Integer 转化为 int 类型来比较(也就是通过调用 intValue()方法返回数字),直接比较数字,在这种情况下是不会出现例子中的问题的。
6、Integer 做“>”、“>=”、“<”、“<=”比较的时候,Integer 会自动拆箱,就是比较它们的数字值。
7、switch case 为选择语句,匹配的时候不会用 equals(),而是直接用“==”。而在 switchcase 语句中,语法层面 case 部分是不能写 Integer 对象的,只能是普通的数字,如果是普通的数字就会将传入的 Integer 自动拆箱,所以它也不会出现例子中的情况。
8、在 JDK 1.7 中,支持对 String 对象的 switch case 操作,这其实是语法糖,在编译后的字节码中依然是 if else 语句,并且是通过 equals()实现的。
参考链接:
https://blog.csdn.net/u012070360/article/details/54574707
https://www.cnblogs.com/dolphin0520/p/3780005.html