128陷阱(缓冲池)

名字高大上原理 so easy
1.浅层次理解:首先看名字,128就能想到我们java中的数值空间,数据基本类型中的Integer他的数据范围为-128~127,如果在此范围之内,就会直接在缓冲池中获取数据。
2. 在进一步理解:在jdk1.5之后就出现了自动装箱和自动拆箱。就是在程序编译过程中会自动的将基本数据类型转化为自己对应的包装类。
3. 有了一些理论之后进行实践:看一下代码(代码是抄别人的,但是足以说明问题):

public class Test{
    public static void main(String... args){
        Integer i1 = 128;
        Integer i2 = 128;
        /*
             由于自动装箱是编译器阶段,所以以上代码会在编译器变成
             Integer i1 = new Integer(128);
             Integer i2 = new Integer(128);
             由于i1和i2指向堆中创建的两个对象所以 i1==i2会输出false
        */
        System.out.println(i1 == i2); // false

        // 请看一下代码
        Integer i3 = 127;
        Integer i4 = 127;
        System.out.println(i3 == i4); // true
    /*
        结果却输出了true,这是由于java虚拟机里面除了字符串常量池还有
        一个常用的数字常量池,其范围是-128~127,所以如果Integer指向
        这个范围内的数字在编译的时候会直接指向常量池中的数字,而不会创
        建新的对象,所以输出为true。
    */
    }
}
public class IntegerDemo {
    public static void main(String[] args) {
        Integer i1 = new Integer(127);
        Integer i2 = new Integer(127);
        System.out.println(i1 == i2);       //false
        System.out.println(i1.equals(i2));   //true
        System.out.println("-----------");

        Integer i3 = new Integer(128);
        Integer i4 = new Integer(128);
        System.out.println(i3 == i4); //false
        System.out.println(i3.equals(i4)); //true
        System.out.println("-----------");

        Integer i5 = 128;
        Integer i6 = 128;
        System.out.println(i5 == i6); //true
        System.out.println(i5.equals(i6)); //true
        System.out.println("-----------");

        Integer i7 = 127;
        Integer i8 = 127;
        System.out.println(i7 == i8);
        System.out.println(i7.equals(i8));

        // 通过查看源码,我们就知道了,针对-128到127之间的数据,做了一个数据缓冲池,如果数据是该范围内的,每次并不创建新的空间
        Integer ii = Integer.valueOf(127);
    }
}

通过上面两份代码可以看出来为什么有些事false有些确实true,不急我们先看看源码:

* @return a <tt>Integer</tt> instance representing <tt>i</tt>.
     * @since  1.5
     */
    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);
    }

从代码中可以看到,当在-128~127之间的时候可以在数据池中取到相应的值,但是当超过他所在的范围之后,就会重新new出一个新空间来。
所以当程序编译的时候首先会自动装箱,然后在进行做判断,在封装器中如果超过了就会new出一个空间来存放他,否则直接返回需要的数据,判断完之后会进行拆箱转换为基本类型.
==是判断两个变量或实例是不是指向同一个内存空间,equals是判断两个变量或实例所指向的内存空间的值是不是相同
这下明白了吧!!!!!!!!!!!!!!!!!!!!!!!!!!!!
double,float有可能会丢失精度,建议使用BigDecimal类型。

发布了40 篇原创文章 · 获赞 5 · 访问量 9466

猜你喜欢

转载自blog.csdn.net/qq_40873540/article/details/104701513
今日推荐