zoukankan      html  css  js  c++  java
  • Java包装类之Integer的 "==" 判断数值是否相等的陷阱及原因分析

    在好久以前的一次面试中,面试官问了我这么一个问题:“现在有 Integer a = 56, b = 56, c = 180, d = 180;  请问:a == b ,c == d  是否成立,也就是是否为true?”

    我当时知道 a == b 是 为true,c == d 是为false的,我也是这么回答的。接着面试官问我,“为什么呢?”

    然后我就不知道了。那个的确是不是很清楚为什么会这样,不过虽然那个时候这个问题没有回答出来,但是其他问题都回答得不错,并且这是一面,到了二面的时候也回答得不错,所以最后还是拿下来了这个offer。

    虽然那个时候拿到了offer,但是没有回答出这个问题,我还是挺在意的,后面我也去研究了一下。

    首先我通过代码验证一下我那次面试的回答:

    1 //定义两组Integer变量
    2 Integer a = 56, b = 56, c = 180, d = 180;
    3 System.out.println("a == b:" + (a == b));
    4 System.out.println("c == d:" + (c == d));

    打印结果如下:

    1 a == b:true
    2 c == d:false

    接下来我们来找一下到底为什么?

    当我们按照  :

    1 Integer a = 56, b = 56, c = 180, d = 180; 

    定义变量的时候其实就相当于:

    1 Integer a = Integer.valueOf(56), b = Integer.valueOf(56), c = Integer.valueOf(180), d = Integer.valueOf(180);

    我们去看 Integer.valueOf() 的源码:

     1     /**
     2      * Returns an {@code Integer} instance representing the specified
     3      * {@code int} value.  If a new {@code Integer} instance is not
     4      * required, this method should generally be used in preference to
     5      * the constructor {@link #Integer(int)}, as this method is likely
     6      * to yield significantly better space and time performance by
     7      * caching frequently requested values.
     8      *
     9      * This method will always cache values in the range -128 to 127,
    10      * inclusive, and may cache other values outside of this range.
    11      *
    12      * @param  i an {@code int} value.
    13      * @return an {@code Integer} instance representing {@code i}.
    14      * @since  1.5
    15      */
    16     public static Integer valueOf(int i) {
    17         if (i >= IntegerCache.low && i <= IntegerCache.high)
    18             return IntegerCache.cache[i + (-IntegerCache.low)];
    19         return new Integer(i);
    20     }

    有以上的源码和注释中会发现从jdk1.5开始就有了这个方法,当传入的参数"i"大于等于 IntegerCache.low 且小于等于IntegerCache.high 的时候返回 IntegerCache.cache[i + (-IntegerCache.low)],否则 new 一个Integer变量返回,顾名思义IntegerCache 应该就是Integer的缓存用的相关静态类,这个时候我们可以继续去看 IntegerCache 的源码:

     1     /**
     2      * Cache to support the object identity semantics of autoboxing for values between
     3      * -128 and 127 (inclusive) as required by JLS.
     4      *
     5      * The cache is initialized on first usage.  The size of the cache
     6      * may be controlled by the {@code -XX:AutoBoxCacheMax=<size>} option.
     7      * During VM initialization, java.lang.Integer.IntegerCache.high property
     8      * may be set and saved in the private system properties in the
     9      * sun.misc.VM class.
    10      */
    11 
    12     private static class IntegerCache {
    13         static final int low = -128;
    14         static final int high;
    15         static final Integer cache[];
    16 
    17         static {
    18             // high value may be configured by property
    19             int h = 127;
    20             String integerCacheHighPropValue =
    21                 sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
    22             if (integerCacheHighPropValue != null) {
    23                 try {
    24                     int i = parseInt(integerCacheHighPropValue);
    25                     i = Math.max(i, 127);
    26                     // Maximum array size is Integer.MAX_VALUE
    27                     h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
    28                 } catch( NumberFormatException nfe) {
    29                     // If the property cannot be parsed into an int, ignore it.
    30                 }
    31             }
    32             high = h;
    33 
    34             cache = new Integer[(high - low) + 1];
    35             int j = low;
    36             for(int k = 0; k < cache.length; k++)
    37                 cache[k] = new Integer(j++);
    38 
    39             // range [-128, 127] must be interned (JLS7 5.1.7)
    40             assert IntegerCache.high >= 127;
    41         }
    42 
    43         private IntegerCache() {}
    44     }

    有上面的源代码可以看出,在Integer里定义了一个私有的静态内部类 IntegerCache ,在其中定义了 静态Integer数组 cache ,长度为 high = 127 和 low = -128  之间的差值,并且存储的是 从 low到high,即-128到127的值。 

    总结:

    由以上的分析我们可以知道,当我们  Integer a = 56, b = 56, c = 180, d = 180; 的时候:

    1. 如果定义的变量在 -128到127之间,则是直接去缓存cache里的值,所以如果数值一致则对应的地址值也会一致,所以我们用 == 判断两个值是否相等,是返回 true的;

    2. 如果定义的变量不在  -128到127之间,则通过new Integer(int i)的方式创建数值,并且每次都会重新new一个对象,这就导致每次的对象的数值即使一样但是地址值不一致,所以此时用 == 判断两个值是否相等就不如我们所愿了;

    3. 所以我们遇到包装类 Integer定义的变量的时候,如果要判断两个变量的值是否相等,则使用 equals来判断,尽量不要用 == 的来判断。

      

  • 相关阅读:
    python 端口扫描仪
    [ruby on rails] 深入(1) ROR的一次request的响应过程
    [ruby on rails] 跟我学之(10)数据输入验证
    [ruby on rails] 跟我学之(9)删除数据
    [ruby on rails] 跟我学之(8)修改数据
    [ruby on rails] 跟我学之(7)创建数据
    BZOJ 2301 [HAOI2011]Problem b (分块 + 莫比乌斯反演)
    BZOJ 2005 [Noi2010]能量采集 (数学+容斥 或 莫比乌斯反演)
    BZOJ 1497 [NOI2006]最大获利 (最小割)
    BZOJ [FJOI2007]轮状病毒 (找规律)
  • 原文地址:https://www.cnblogs.com/sunshine6/p/10746685.html
Copyright © 2011-2022 走看看