Java自动装箱、拆箱原理

在Java中, 所有要处理的东西几乎都是对象 (Object)

        在 Java SE 5.0之后提供了自动装箱的功能,可以直接使用以下语句来打包基本数据类型:Integer integer = 10;

        在进行编译时,编译器会判断是否进行自动装箱动作。自动装箱适用于 boolean、byte、short、char、long、float、double等基本数据类型,会使用对应的打包类型(Wrapper Types)Boolean、Byte、Short、Character、Long、Float或Double。

 

public class AutoBox {
 
    public static void main(String[] args) {
 
        Integer a = 1;//int类型自动装箱
        System.out.println(a + 1);//Integer自动拆箱
    }
 
}

 

装箱中如果数字为1个字节内(-128~127),则会将这个数字放入缓存池中,创建对象时返回该对象的引用,这涉及到了Java的享元模式Flyweigth

 

public class AutoBoxFlyweigth {
	 
    public static void main(String[] args) {
        Integer a = 12;
        Integer b = 12;
        System.out.println(a == b);// true
        Integer c = 1234;
        Integer d = 1234;
        System.out.println(c == d);// false
        
        Integer e = new Integer(13);
        Integer f = new Integer(13);
        System.out.println(e == f);	//false
        
        Integer g = new Integer(1200);
        Integer h = new Integer(1200);
        System.out.println(g == h);	//false
    }
 
}

 

通过Java源代码可以看到Integer.valueOf()中有个内部类IntegerCache(类似于一个常量数组,也叫对象池),它维护了一个Integer数组cache,长度为(128+127+1)=256,Integer类中还有一个Static Block(静态块)。从这个静态块可以看出,Integer已经默认创建了数值【-128-127】的Integer缓存数据。所以使用Integer a=12时,JVM会直接在该在对象池找到该值的引用。也就是说这种方式声明一个Integer对象时,JVM首先会在Integer对象的缓存池中查找有没有12的对象,如果有直接返回该对象的引用;如果没有,则使用new一个对象,并返回该对象的引用地址。因为Java中“==”比较的是两个对象的引用(即内存地址),a、b为同一个对象,所以结果为true,因为1234超过了Integer缓存数据范围,使用new方式创建:c = new Integer(1234);d=new Integer(40);虽然他们值相等,但是属于不同的对象,不会被放到对象池中,所以他们不是同一个引用,返回false。

       用一句简短通俗的话话概括享元模式:

       如果有很多个小的对象,它们有很多属性相同,那可以把它们变成一个对象,那些不同的属性把它们变成方法的参数,称之为外部状态,相同的属性称之为内部状态,这种机制即为享元模式。

 

 

int (-128,127) 范围的处理 和 String s= "a"; 类似 //从缓存池中取,如果没有在在池中和堆上创建

String s = new String("ss"); //直接在堆上创建

 

你可能感兴趣的:(拆箱,Java自动装箱)