Java自动装箱、拆箱及缓存池

Java自动装箱、拆箱是JDK1.5以后才引入的新的内容,在许多情况下装箱和拆箱是由编译器自行完成的。

自动装箱就是将基本数据类型封装为对象类型,来符合Java的面向对象。例如:

Integer num = 10;//声明一个Integer对象
Integer num = new Integer(10);//以上的声明就是用到了自动装箱,相当于这句。

自动拆箱就是将对象重新传化成基本数据类型:

//装箱
Integer num = 10;
//拆箱
int num2 = num;

那我我们再来看看下面的运行结果:

public static void main(String[] args) {

Integer a=100;

Integer b=100;

Integer c=200;

Integer d=200;

System.out.println(a==b); //true

System.out.println(a==100); //true

System.out.println(c==d); //false

System.out.println(c==200); //true

}

在java种,”==”是比较object的reference而不是value,自动装箱后,abcd都是Integer这个Oject,因此“==”比较的是其引用。

自动装箱时,java在编译的时候 Integer a = 100; 被翻译成-> Integer a = Integer.valueOf(100);

我们先来看看IntegerCache源码:

1
2
3
4
5
6
7
8
9
10
 private static class IntegerCache {
    private IntegerCache(){}

    static final Integer cache[] = new Integer[-(-128) + 127 + 1];

    static {
        for(int i = 0; i < cache.length; i++)
        cache[i] = new Integer(i - 128);
    }
    }

再来看valueOf方法:

1
2
3
4
5
6
7
 public static Integer valueOf(int i) {
    final int offset = 128;
    if (i >= -128 && i <= 127) { // must cache
        return IntegerCache.cache[i + offset];
    }
        return new Integer(i);
    }

valueOf方法会自动调用IntegerCache这个类,
IntegerCache初始化后内存中就有Integer缓冲池cache[]了,
-128~127区间的int值有其对应的的包装对象
java使用该机制是为了达到最小化数据输入和输出的目的,这是一种优化措施,提高效率
其他的包装器:
Boolean:(全部缓存)
Byte:    (全部缓存)
Character (   <=127 缓存)
Short     (-128~127 缓存)
Long      (-128~127 缓存)
Float     (没有缓存)
Doulbe    (没有缓存)

主题:java迷题:等于,还是不等于?
代码片段1

public static void main(final String[] args) {
Integer a = new Integer(100);
Integer b = 100;
System.out.println(a == b);
}

解答:
结果输出false
因为new Integer(100)是指明了再堆内存中创建对象
而Integer b = 100; 这句是自动装箱,
得到的是Integer缓冲池中的对象,是这句代码return IntegerCache.cache[100 + 128]
明显a和b的地址是不一样的,不是同一个对象
代码片段2

public static void main(final String[] args) {
Integer a = 100;
Integer b = 100;
System.out.println(a == b);
}

解答:
结果输出true
a和b指向了同一个对象,都是IntegerCache.cache[100 + 128]
代码片段3

public static void main(final String[] args) {
Integer a = 156;
Integer b = 156;
System.out.println(a == b);
}

解答:
结果输出false
由于156大于128,它的包装对象不在缓冲池中,而是执行return new Integer(156);
new了2次,都在堆内存中,但地址不一样
代码片段4

public static void main(final String[] args) {
Integer a = Integer.valueOf(100);
Integer b = 100;
System.out.println(a == b);
}

解答:
结果输出true
我们上面说过了,Integer b = 100 就相当于Integer b=Integer.valueOf(100)
所以a和b指向缓冲池中的同一对象.

 

除非注明,饮水思源博客文章均为原创,转载请以链接形式标明本文地址

本文地址:http://www.alonemonkey.com/java-auto-box.html

本文链接:http://www.alonemonkey.com/java-auto-box.html