[转载] 在java中为什么变量1000 = 1000 返回false,但是100=100返回true?

ps:题目的意思是指定义相同内容的不同变量之间的==比较。如果直接比较(1000 == 1000)的结果是true。

运行以下代码:

    Integer a = 1000, b = 1000;
        System.out.println(a == b);
        Integer c = 100, d = 100;
        System.out.println(c == d);

结果是:

false
true

我们知道,如果两个引用指向不同的对象,即使对象拥有相同的内容时,他们用==比较的结果就是不相等(返回false)。

按道理说,最后返回的结果应该也是false才对。但是事实并非如此。

这就是有趣的地方,如果你查看Integer.java类,你会发现Integer类有一个叫做IntegerCache的内部类,这个内部类缓存了所有在-128和127之间的Integer对象。

/**
 * Cache to support the object identity semantics of autoboxing for values between
 * -128 and 127 (inclusive) as required by JLS.
 *
 * The cache is initialized on first usage.  The size of the cache
 * may be controlled by the -XX:AutoBoxCacheMax=<size> option.
 * During VM initialization, java.lang.Integer.IntegerCache.high property
 * may be set and saved in the private system properties in the
 * sun.misc.VM class.
 */

private static class IntegerCache {
    static final int low = -128;
    static final int high;
    static final Integer cache[];

    static {
        // high value may be configured by property
        int h = 127;
        //获取配置中的high值,默认的最大值是127,但是这个值也是可以自定义写在配置文件
        String integerCacheHighPropValue =
            sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
        if (integerCacheHighPropValue != null) {
            int i = parseInt(integerCacheHighPropValue);
            i = Math.max(i, 127);
            // Maximum array size is Integer.MAX_VALUE
            h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
        }
        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() {}
}

所以像以下定义的Integer变量会存在Integer缓存中。

Integer c = 100;//100在-128和127之间。

内部实现是:

Integer i = Integer.valueOf(100);

现在再查看一下valueOf()方法,会看到以下实现代码:

/**
 * Returns an {@code Integer} instance representing the specified
 * {@code int} value.  If a new {@code Integer} instance is not
 * required, this method should generally be used in preference to
 * the constructor {@link #Integer(int)}, as this method is likely
 * to yield significantly better space and time performance by
 * caching frequently requested values.
 *
 * This method will always cache values in the range -128 to 127,
 * inclusive, and may cache other values outside of this range.
 *
 * @param  i an {@code int} value.
 * @return an {@code Integer} instance representing {@code i}.
 * @since  1.5
 */
public static Integer valueOf(int i) {
    assert IntegerCache.high >= 127;
    if (i >= IntegerCache.low && i <= IntegerCache.high)
        return IntegerCache.cache[i + (-IntegerCache.low)];
    return new Integer(i);
}
如果值在-128至127的范围之间,它从缓存中返回实际的值。所以

Integer c = 100, d = 100;
实际是指向同一个对象。

这就是当变量c和d比较(==)的结果是true的原因。

System.out.println(c == d);//true
现在你可能会问,为什么这需要缓存呢?

逻辑上的理由是,在这个范围内的“较小”的整数使用远大于较大的,所以使用相同的底层对象是值得的,以减少潜在的内存占用。

以下代码通过反射来获取Integer缓存变量。

public class IntegerDemo {

public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
    Class cache = Integer.class.getDeclaredClasses()[0]; //1
    Field myCache = cache.getDeclaredField("cache"); //2
    myCache.setAccessible(true);//3
    Integer[] newCache = (Integer[]) myCache.get(cache); //4
    for(int i = 0; i < newCache.length; i++){
        System.out.printf("index[%d]-->vlaue[%d]\n",i,newCache[i]);
    }
   }
 }
转载自:作者:林补
链接:https://zhuanlan.zhihu.com/p/20703688
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
时间: 2024-12-24 21:55:48

[转载] 在java中为什么变量1000 = 1000 返回false,但是100=100返回true?的相关文章

【转载】Java中String类的方法及说明

转载自:http://www.cnblogs.com/YSO1983/archive/2009/12/07/1618564.html String : 字符串类型 一.构造函数     String(byte[ ] bytes):通过byte数组构造字符串对象.     String(char[ ] value):通过char数组构造字符串对象.     String(Sting original):构造一个original的副本.即:拷贝一个original.     String(Strin

Java中的变量与变量的作用域

关于Java中的变量及变量的作用域 关于Java中的变量及变量的作用域 0. 变量的概念 在程序运行期间,系统可以为程序分配一块内存单元,用来存储各种类型的数据.系统分配的内存单元要使用一个标记符来标识,这种内存单元中的数据是可以更改的.所有叫变量.定义变量的标记符就是变量名,内存单元中所装载的数据就是变量值.用一个变量定义一块内存以后,程序就可以用变量名代表这块内存中的数据.根据所存储数据类型的不同,有各种不同类型的变量. 1. Java的变量类型 2. 注意变量的有效取值范围 系统为不同的变

java中成员变量、代码块、构造函数执行顺序

1.java虚拟机运行程序,首先需要装载类,安装现装载父类,初始化父类的静态代码块和静态成员变量 再load子类.初始化子类静态代码块和成员变量 2.load完毕父类与子类后,从main函数入口执行程序,先输出,接着new实例化Beetle类,则先实例化父类Insect,实例化父类时,先初始化非静态成员变量和非静态代码块,接着执行父类构造方法 再实例化子类,实例化子类时,先初始化非静态成员变量和非静态代码块,接着执行子类构造方法. package it.xiangnan.test; public

java中的变量及其转换

java中的变量  变量或变数,是指没有固定的值,可以改变的数.变量以非数字的符号来表达,一般用拉丁字母.变量是常量的相反,变量的用处在于能一般化描述指令的方式. 从本质上讲,变量其实是内存中的一小块区域,使用变量名来访问这块区域,因此,每个变量使用前必须先要声明,然后必须填充内容,最后才能使用. 变量的分类  (1)按所属的数据类型划分:基本数据类型变量和引用数据类型变量 (2)按声明的位置划分:局部变量和全局变量(成员变量) 局部变量:方法或语句块内部定义的变量: 全局变量(成员变量):方法

谈谈java中静态变量与静态方法继承的问题

谈谈java中静态变量与静态方法继承的问题 学习的中如果遇到不明白或者不清楚的的时候,就是自己做些测试,自己去试试,这次我就做一个关于静态变量的继承和静态方法继承问题的测试. 首先我先建一个父类: 这样我在建一个子类: 这些都准备好以后,我对子类创建对象,然后用  类名.静态变量/静态方法  和  对象名.静态方法/静态变量  对他们输出的结果进行测试. 这样输出种类有: 这样我输出的结果是: 这样来总结一下: 1. 通过类名来调用子类中的静态变量和静态方法,当父类与子类相同时是,子类会隐藏父类

谈谈java中成员变量与成员方法继承的问题

谈谈java中成员变量与成员方法继承的问题 关于成员变量和成员方法的的继承问题,我也可以做一个小测试,来看看结果. 首先我们先创建一个父类: 其次再创建一个子类,子类中要比父类中少一个成员方法: 这样我们对子类创建对象,如果不创建对象,我们是无法访问子类的成员变量和成员方法的,因为“无法从静态上下文中引用非静态方法”.我们要输出有: 从以上的数据中,我们就可以得出的输出结果是 这样我们就可以得出结论. 总结: 1.   在结果中可以看出,子类的成员变量和成员方法,与其父类的相同的时候,子类就会覆

随笔⑨ java中的变量 --- 类变量(静态变量),final变量,成员变量,局部变量

java中的变量 --- 类变量(静态变量),final变量,成员变量,局部变量 ① 类变量(也叫静态变量)是类中独立于方法之外的变量,用static 修饰,静态变量随着类的加载而加载. ② final变量:用final关键字修饰,不能被修改.与static一起用可表示常量. ③ 成员变量(也叫"实例变量"."域"):也是类中独立于方法之外的变量,不过没有static修饰.可以不进行初始化,Java会自动进行初始化,如果是引用类型默认初始化为null,如果是基本类型

004 java中的变量

这篇文章为你搞懂三个问题 什么是变量? 如何使用变量? 变量命名有哪些规范? 变量 计算机的内存类似于人的大脑,电脑使用内存来存储计算所需要的数据. 内存像旅馆一样,不同的房间类型对应不同的数据类型,内存存储数据时会根据数据的需求为它申请一块合适的空间.用于存储数据的这个空间就是变量. 变量名 内存地址 值 name 0x5c2a0c3f.. 张三 age 0xcd4d72a... 10 变量名.内存和存储的值如上表↑ 可以看到内存地址长而不方便记忆,但是变量名可以像给一个人起外号一样,方便记忆

java中double变量保留小数问题

(转载自玄影池扁舟) 做java项目的时候可能经常会遇到double类型变量保留小数的问题,下面便把我的经验做个简短的总结: java中double类型变量保留小数问题大体分两种情况: (一):小数点后面位数过长,四舍五入保留指定位数: 可以用以下代码实现: public class TestDemo { public static void main(String[] args) {     double a=15.32743859;     double b=Math.round(a*100