从
JDK1.5
开始
java
添加了一个新特性:自动装箱和拆箱。这极大的简化了简单类型与包装类型之间的转换,那么自动装箱和拆箱是怎么实现的呢?
现来看一行源代码:
Integer a = 125;
用javap
工具查看其字节码为:
0: bipush 125
2: invokestatic #16; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
5: astore_1
2: invokestatic #16; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
5: astore_1
可以发现Integer
类的自动装箱是通过调用类的静态方法valueOf
实现的。
阅读Integer
类的源代码发现该类还用到了享元模式,对于范围在-128
~127
的int
类型数,不是新创建一个对象,而是返回内存中已有的对象,对于不在此范围里的数则新创建一个对象。可以看一段代码:
Integer a = 125;
Integer b = 125;
System.out.println(a == b);
Integer a1 = 128;
Integer b1 = 128;
System.out.println(a1 == b1);
Integer b = 125;
System.out.println(a == b);
Integer a1 = 128;
Integer b1 = 128;
System.out.println(a1 == b1);
输出是:
true
false
false
这是怎么实现的呢?
原因就在于在Integer
类里有个内隐类IntegerCache
,存放-128
~127
范围内的对应Integer
类对象。
该类的静态方法valueOf
的实现是当数在此范围之内时直接返回内隐类IntegerCache
中存放的对应的Integer
类对象,否则用new
新生成一个对象。这个就是设计模式中的享元模式吧。
那自动拆箱呢?
也先来看两行代码:
Integer a = 125;
int b = a;
int b = a;
其字节码指令为:
0: bipush 125
2: invokestatic #16; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
5: astore_1
6: aload_1
7: invokevirtual #22; //Method java/lang/Integer.intValue:()I
10: istore_2
11: return
2: invokestatic #16; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
5: astore_1
6: aload_1
7: invokevirtual #22; //Method java/lang/Integer.intValue:()I
10: istore_2
11: return
可以看到自动拆箱是调用Integer
类的成员方法intValue()
实现的,而intValue
方法就一行语句”返回其value
值。