什么是自动装箱与自动拆箱
//把int类型的数值自动转成Integer类型的对象a
Integer a = 100;
//把Integer类型的对象a自动转成int类型的b
int b = a;
也就是说,自动装箱就是把基本数据类型转在包装器类型,而自动拆箱则相反,把包装器类型转成基本数据类型。
自动装箱
java是怎么把100转成Integer的呢?
反编译一下字节码文件:
javap相关的参数:
-help , --help , or -?
Prints a help message for the javap command.
-version
Prints release information.
-verbose or -v
Prints additional information about the selected class.
-l
Prints line and local variable tables.
-public
Shows only public classes and members.
-protected
Shows only protected and public classes and members.
-package
Shows package/protected/public classes and members (default).
-private or -p
Shows all classes and members.
-c
Prints disassembled code, for example, the instructions that comprise the Java bytecodes, for each of the methods in the class.
-s
Prints internal type signatures.
-sysinfo
Shows system information (path, size, date, MD5 hash) of the class being processed.
-constants
Shows static final constants.
--module module or -m module
Specifies the module containing classes to be disassembled.
--module-path path
Specifies where to find application modules.
--system jdk
Specifies where to find system modules.
--class-path path, -classpath path , or -cp path
Specifies the path that the javap command uses to find user class files. It overrides the default or the CLASSPATH environment variable when it’s set.
-bootclasspath path
Overrides the location of bootstrap class files.
-Joption
Passes the specified option to the JVM. For example:
java代码:
public class Test{
public static void main(String[] args){
Integer a = 99;
int b = a;
}
}
反编译结果:
想看懂什么意思可以参考Java虚拟机指令集
Compiled from "Test.java"
public class Test {
public Test();
Code:
0: aload_0 //把当前对角
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
LineNumberTable:
line 1: 0
public static void main(java.lang.String[]);
Code:
//把99压入栈中
0: bipush 99
//调用Integer的静态方法valueOf
2: invokestatic #2 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
// 将valueOf返回的对象地址存到局部变量1(a)中
5: astore_1
// 装载指向的值
6: aload_1
// 调用Integer里的intValue方法
7: invokevirtual #3 // Method java/lang/Integer.intValue:()I
// 将返回的值给到局部变量2(b)
10: istore_2
11: return
LineNumberTable:
line 3: 0
line 4: 6
line 5: 11
这个流程走下来,我个看到,先是99进栈,然后调用了Integer的valueOf方法。
看看这个方法,是酱紫的。把int类型的数值扔进去,返回的是一个Integer类型的对象。里面封装了int类型的值。
继续往里面看,有一些东西值得我们看的。
/**
* Returns an {@code Integer} instance representing the specified
* {@code int} value. If a new {@code Integer} instance is not
* required, this method should generally be used in preference to
* the constructor {@link #Integer(int)}, as this method is likely
* to yield significantly better space and time performance by
* caching frequently requested values.
*
* This method will always cache values in the range -128 to 127,
* inclusive, and may cache other values outside of this range.
*
* @param i an {@code int} value.
* @return an {@code Integer} instance representing {@code i}.
* @since 1.5
*/
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
static final int low = -128;
static final int high; //可以进行配置,默认是127
那么上在这代码可以改成这样,比较方便阅读:
public static Integer valueOf(int i) {
if (i >= -128 && i <= 127)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
在[-128,127]这个区间内的,就直接云缓存里获取,而其他的则会自动创建一个对象。
这就是int类型自动装箱的过程。
自动拆箱
按前面的套路去看,我们知道拆箱的时候,走了一个方法。
/**
* Returns the value of this {@code Integer} as an
* {@code int}.
*/
public int intValue() {
return value;
}
直接返回包装的值