自动封装和自动解封(简单类型和封装类型之间),但只是在必要的时候进行,比如向上就近原则中public static void method(Byte b){}:调用这个方法的时候不会像上就近调用int,而是直接调用这个方法。
Integer i = 3 // OK 封箱
int i = new Integer(3) // OK 解箱
i++ ; // OK ,i是Integer
在方法中的参数也可以自动的封箱解箱,但是如果存在两个方法:
方法重载依然存在:
public static void method( Integer I ) { … }
public static void method( int I ) { … }
这个时候调用 method( 10 ) //会调用第二个方法,因为封箱和解箱都是在迫不得已的情况下才会被调用。
public static void method( Byte b ) { … }
public static void method( short s ) { … }
这个时候调用 byte b = 1 ; method( byte ) //会调用第二个方法,因为封箱和解箱都是在迫不得已的情况下才会被调用。
同样存在问题:拿byte举例: byte : 256 种(1个字节)然而 Byte : 257 种(多了一个null)
所以如果 Integer I = null ; int i = I ; //会有空指针异常
封装类有个重要的特性:就是封装0
自动解箱要注意的:
Byte b = null;
Byte b = 1;
int i = 0;(默认i=0),有二义性,究竟0是否是有效数字0,还是没有赋值而使用默认给得值; 所以此时用Integer就可以避免这样的二义性。
例如:在hibernate中使用Long而不是long去设定ID的类型,则hibernate会自动检查类型是否是有效数字
// 在-128~127 之外的数
Integer i1 = 200 ;
Integer i2 = 200 ;
System.out.println( " i1==i2: " + (i1 == i2));
// 在-128~127 之内的数
Integer i3 = 100 ;
Integer i4 = 100 ;
System.out.println( " i3==i4: " + (i3 == i4));
输出的结果是:
<div class="cnblogs_code" style="margin: 5px 0px; padding: 5px; background-color: rgb(245, 245, 245); font-family: 'Courier New' !important; font-size: 12px !important; border: 1px solid rgb(204, 204, 204); overflow: auto; "><pre style="margin-top: 0px; margin-bottom: 0px; padding: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: 'Courier New' !important; "><div style="margin: 0px; padding: 0px; background-color: rgb(245, 245, 245); "><span style="margin: 0px; padding: 0px; line-height: 1.5; "> i1</span><span style="margin: 0px; padding: 0px; line-height: 1.5; ">==</span><span style="margin: 0px; padding: 0px; line-height: 1.5; ">i2: </span><span style="margin: 0px; padding: 0px; line-height: 1.5; color: rgb(0, 0, 255); ">false</span><span style="margin: 0px; padding: 0px; line-height: 1.5; "><br style="margin: 0px; padding: 0px; " /> i3</span><span style="margin: 0px; padding: 0px; line-height: 1.5; ">==</span><span style="margin: 0px; padding: 0px; line-height: 1.5; ">i4: </span><span style="margin: 0px; padding: 0px; line-height: 1.5; color: rgb(0, 0, 255); ">true</span></div>
在自动装箱时对于值从–128到127之间的值,它们被装箱为Integer对象后,会存在内存中被重用,
所以范例中,i3 与 i4实际上参考至同一个对象。
如果超过了从–128到127之间的值,被装箱后的Integer对象并不会被重用,
即相当于每次装箱时都新建一个 Integer对象,所以范例中,i1与i2参考的是不同的对象。
另外,当不使用自动装箱功能的时候,情况与普通类对象一样,请看下例:
1 Integer i3 = new Integer( 100 );
2 Integer i4 = new Integer( 100 );
3 System.out.println( " i3==i4: " + (i3 == i4)); // 显示false
JVM中包装对象大小
一个基本的object对象大小为8字节,而且这8字节不包括任何实例数据。那么,一个包装对象最起码大小为16字节,8字节+8字节实例数据,由于对象大小必须是8的倍数,所以实例数据部分最小占8字节,所以一个包装对象大小至少为16字节,而一个基本类型所占空间大小,明显小于16字节,比如int只占4个字节,最大的double、long也只占8字节。所以,在JVM内,会自动进行拆包以节省内存。