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

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

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

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

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

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

打印结果如下:

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

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

当我们按照  :

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

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

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

我们去看 Integer.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) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}

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

     /**
* 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 {@code -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;
String integerCacheHighPropValue =
sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
if (integerCacheHighPropValue != null) {
try {
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);
} catch( NumberFormatException nfe) {
// If the property cannot be parsed into an int, ignore it.
}
}
high = h; cache = new Integer[(high - low) + 1];
int j = low;
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++); // range [-128, 127] must be interned (JLS7 5.1.7)
assert IntegerCache.high >= 127;
} private IntegerCache() {}
}

有上面的源代码可以看出,在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来判断,尽量不要用 == 的来判断。

  

Java包装类之Integer的 "==" 判断数值是否相等的陷阱及原因分析的更多相关文章

  1. java的File类的 delete方法删不掉文件的原因分析

    先举几个可以删除掉文件和删除不掉文件的例子(先在F盘创建test1.txt文件,然后可以直接拷贝代码到IDE执行),最后总结下原因: 例子一:下面的例子毫无疑问是能够删除掉文件的 import jav ...

  2. java integer对象判断两个数字是否相等

    java integer对象判断两个数字是否相等,不一定对 问题发生的背景:javaweb的项目,起先,因为在java中实体类中的int类型在对象初始化之后会给int类型的数据默认赋值为0,这样在很多 ...

  3. Java int和Integer包装类的区别和比较

    区别:                                                                                                  ...

  4. Java包装类缓存

    1.基本概念 在jdk1.5及之后的版本中,Java在5大包装类中(Byte,Charactor,Short,Integer,Long)增加了相应的私有静态成员内部类为相应包装类对象提供缓存机制,In ...

  5. Java包装类的常量池

     Integer a=Integer.valueOf(100); Integer b=Integer.valueOf(100); System.out.println(a==b); Double d1 ...

  6. 【转】java int与integer的区别

    java int与integer的区别 int与integer的区别从大的方面来说就是基本数据类型与其包装类的区别: int 是基本类型,直接存数值,而integer是对象,用一个引用指向这个对象 1 ...

  7. Java进阶(三十五)java int与integer的区别

    Java进阶(三十五)java int与Integer的区别 前言 int与Integer的区别从大的方面来说就是基本数据类型与其包装类的区别: int 是基本类型,直接存数值,而Integer是对象 ...

  8. Java 包装类笔记

    @(JDK)[包装类] Java 包装类笔记 当需要使用到集合的时候,如果是基础数据类型,需要转换为包装类,再使用,在JDK1.5之前,每次使用的时候,都需要手动转换为包装类(称为装箱),然后在使用的 ...

  9. (转)Java进阶java int与Integer的区别

    Java进阶java int与Integer的区别 前言 int与Integer的区别从大的方面来说就是基本数据类型与其包装类的区别: int 是基本类型,直接存数值,而Integer是对象,用一个引 ...

随机推荐

  1. ElasticSearch 一

    一:elasticSearch的目录结构的分类 /bin 运行ElasticSearch实例和管理插件呢的一些脚本 /config 配置文件 路径,包含elasticsearch.yml /data ...

  2. ORACLE中通过SQL语句(alter table)来增加、删除、修改字段

    1.添加字段: alter table  表名  add (字段  字段类型)  [ default  '输入默认值']  [null/not null]  ; 2.添加备注: comment on ...

  3. float和double的最大值和最小值

  4. String对象方法属性总结

    常用属性: constructor;length;prototype;(不在解释): 常用方法: charAt(index);返回指定位置的字符. concat(stringX);连接字符串. ind ...

  5. popwindow+动画

    布局: main: <Button android:id="@+id/btn" android:layout_width="match_parent" a ...

  6. Python 学习笔记6 变量-元组

    我们在上一篇中了解了变量list(列表), 今天我们来介绍下元组.元组是由括号和逗号,组织起来的一个元素的集合.和list不同的是,它其中的元素是不能被修改的,和其他语言中的常量相类似. 需要注意的是 ...

  7. ide phpStorm更换主题

    #主题下载地址 http://www.phpstorm-themes.com #更换方式 1.将主题配置保存在 xxx.icls(如果是xml也保存成.icls) 2.打开phpStorm设置(中上方 ...

  8. 关于ico图标

    ico图标可以作为网页标签上显示的小logo,比如: 要获取一个网站的ico图标,只需要在url后输入/favicon.ico即可,比如   https://www.baidu.com/favicon ...

  9. Xamarin打包

  10. Nginx(一)-windows下的安装配置

    第一步 下载 官网下载地址 因为只是测试这里选择最新版本1.13.9 下载完成得到zip压缩包 解压后得到如下目录 第二步  启动nginx 注意不要直接双击nginx.exe,这样会导致修改配置后重 ...