在好久以前的一次面试中,面试官问了我这么一个问题:“现在有 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. 解决ajax 跨域请求问题

    浏览器console报错: has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is 解决: 服务端加入代 ...

  2. ValidateCode源码

    ValidataCode.java: package com.itcast; /** * @author 大汉 */ import java.awt.Color; import java.awt.Fo ...

  3. python全栈开发 * 表格标签 表单标签 css 引入方式 * 180807

    html部分 一.表格标签<table> 1.一个表格<table>由每行<tr>组成的,每行是由<td>组成的. 注意: 一个表格是由行组成的(行是由 ...

  4. SSIS - 2.使用脚本任务弹出对话框

    步骤如下: 1.打开Visual Studio 2012或者SSDT工具->单击“文件”->选择"新建"打开创建新工程的对话框如下: 2.在"Business ...

  5. 19.3.19 使用Flask框架搭建一个简易登录服务器

    import Flask import json from Flask import request server1 = flask.Flask(__name__) #实例化一个flask对象 @se ...

  6. 在C++中,子类重载一个操作符时,如何调用父类被重载的操作符函数

    使用static_cast运算符将子类转换为父类即可 #include <iostream> using namespace std; class Base { public: Base( ...

  7. 树状数组 || JZOI 1024. @szefany 的树

    题面:无 题解:无 代码: #include<cstdio> #include<cstring> #include<iostream> #include<al ...

  8. rbac权限控制,基于无线分类

    2018年9月18日11:21:28 数据库结构 CREATE TABLE `admin` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `c ...

  9. GridFS and Geospatial

    GridFS - specification for storing and retrieving large files... images,audio file, video files... F ...

  10. Linux unalias命令 取消别名

    unalias 提示:命令行处理别名仅为临时取消别名,重启系统后就失效了 [root@MongoDB ~]# alias |grep cp alias cp='cp -i' [root@MongoDB ...