A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 韩军博 黑马帝   /  2011-12-1 13:45  /  3538 人查看  /  6 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 韩军博 于 2011-12-1 16:18 编辑



运行结果是:
i1=i2true
i1=i2+i3   true
i4=i5false
i4=i5+i6true

不是很明白,请大家把每个运行结果解释一下原因。

评分

参与人数 1技术分 +1 收起 理由
admin + 1

查看全部评分

6 个回复

正序浏览
李盈科 黑马帝 2011-12-1 17:49:30
7#
本帖最后由 李盈科 于 2011-12-1 17:56 编辑

看一下源代码 很清楚了   这道题 感觉很恼火啊 哈哈  
我还真不知道 有常量池这个概念 去补习一下  根据源代码 Integer.valueOf 时候如果赋值在-128-+127之间 也就是byte的范围 会返回一个缓存数组的值啊,所以才相等.不会像String一样生成新对象,有个范围哈~
public static Integer valueOf(int i) {
        if(i >= -128 && i <= IntegerCache.high)
            return IntegerCache.cache[i + 128];
        else
            return new Integer(i);
    }
     private static class IntegerCache {
        static final int high;
        static final Integer cache[];

        static {//先于构造方法执行
            final int low = -128;

            // high value may be configured by property
            int h = 127;
            if (integerCacheHighPropValue != null) {
                // Use Long.decode here to avoid invoking methods that
                // require Integer's autoboxing cache to be initialized
                int i = Long.decode(integerCacheHighPropValue).intValue();
                i = Math.max(i, 127);
                // Maximum array size is Integer.MAX_VALUE
                h = Math.min(i, Integer.MAX_VALUE - -low);
            }
            high = h;

            cache = new Integer[(high - low) + 1];
            int j = low;
            for(int k = 0; k < cache.length; k++)
                cache[k] = new Integer(j++);
        }
private IntegerCache() {}
    }

评分

参与人数 1技术分 +1 收起 理由
admin + 1

查看全部评分

回复 使用道具 举报
韩军博 发表于 2011-12-1 16:18
谢谢回答

没事 能帮到你就好
回复 使用道具 举报
xiaolij3s 发表于 2011-12-1 16:01
Integer i1=40;Java在编译的时候会执行将代码封装成Integer i1=Integer.valueOf(40);
使用Integer i1=40时 ...

谢谢回答
回复 使用道具 举报
Integer i1=40;Java在编译的时候会执行将代码封装成Integer i1=Integer.valueOf(40);
使用Integer i1=40时,JVM会直接在该在对象池找到该值的引用。也就是说这种方式声明一个Integer对象时,JVM首先会在Integer对象的缓存池中查找有木有值为40的对象,如果有直接返回该对象的引用;如果没有,则创建一个对象,并返回该对象的引用地址。因为Java中【==】比较的是两个对象是否是同一个引用(即比较内存地址),i2和i2都是引用的同一个对象,So i1==i2结果为”true“;而使用new方式创建的i4=new Integer(40)、i5=new Integer(40),虽然他们的值相等,但是每次都会重新Create新的Integer对象,不会被放入到对象池中,所以他们不是同一个引用,输出false。

对于i1==i2+i3、i4==i5+i6结果为True,是因为,Java的数学计算是在内存栈里操作的,Java会对i5、i6进行拆箱操作,其实比较的是基本类型(40=40+0),他们的值相同,因此结果为True。

评分

参与人数 1技术分 +2 收起 理由
admin + 2

查看全部评分

回复 使用道具 举报
       首先"i1==i2"的结果为true,是因为"i1"在使用40时首先会去常量池中查找,如果有四十这个对象,就引用,池中没有的话就创建一个,而"i2"引用40时,因为池中已经在"i1"使用时创建了一个,所以"i2"会直接引用这一个,这样就证明它俩指向的是常量池中的同一个对象,所以结果为true;
       而"i1==i2+i3"两边的值同样是指向常量池中的已经有的那一个对象,所以和上面一样
       "i4=i5false"它俩使用new关键字创建的对象,所以它俩引用的内存地址不同,结果自然为false
       "4=i5+i6"这个比较复杂,我也不太明白,我试一下,在上网查查看吧

评分

参与人数 1技术分 +1 收起 理由
admin + 1

查看全部评分

回复 使用道具 举报
这个跟那个字符串比较的经典面试题很相似,在JAVA里面,为了优化运行速度,设计了常量池这个机制。当你简单的Integer i1 = 40时系统首先会在去查找常量池里面有没有这个常量,如果没有的话就会在内存里分配一块内存空间来存储,然后将这个常量的引用添加到常量池里面去,而当你第二次再Integer i2 = 40时同样地,系统会首先去常量池里查找有没有这个常量,结果他找到了。然后他就会将将i2也指向到前面分配的那块内存空间去,而不是再一次开辟一块内存空间出来。
而如果你是用Integer i3 = new Integer(40)这种方法来创建一个Integer的话,系统就不会去查找常量池里面有没有这个常量,而是直接新分配一块内存空间去存储这个对象,相应的,当你Integer i4 = new Integer(40)时系统也是新分配一块内存空间,所以(i3 == i4)的值就是false,这样解释你懂了么?

评分

参与人数 1技术分 +1 收起 理由
admin + 1

查看全部评分

回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马