在好久以前的一次面试中,面试官问了我这么一个问题:“现在有 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. python开发之virtualenv与virtualenvwrapper讲解

    在使用 Python 开发的过程中,工程一多,难免会碰到不同的工程依赖不同版本的库的问题: 亦或者是在开发过程中不想让物理环境里充斥各种各样的库,引发未来的依赖灾难. 此时,我们需要对于不同的工程使用 ...

  2. C++中继承与抽象类

    继承语法格式如下: class 子类名称 : 继承方式(public private protected 三种) 父类名称 纯虚函数格式: virtual 返回值类型 函数名(参数列表)= 0:含有纯 ...

  3. CentOS7安装MySQL并允许远程登录

    下载 mysql 源安装包 $ curl -LO http://dev.mysql.com/get/mysql57-community-release-el7-11.noarch.rpm 安装 mys ...

  4. yield关键字

    1.yield语句有两种形式 (1)yield return <expression>;一次返回一个元素 运行yield return 语句时,会返回一个 值,并记录当前位置及保留该值.下 ...

  5. golang 学习路径

    目录 一 了解 go 二 入门教程 三 安装运行环境 & IDE(goland) 四 gotour 五 简易源码解析 六 开始写代码 七 学习框架 八 惯用法 九 调优 一 了解 go 谷歌一 ...

  6. 如何追踪产生大量REDO的来源

    从10点到12点数据库中对象块变化排名靠前的对象 select to_char(begin_interval_time,'YYYY_MM_DD HH24:MI') snap_time, dhsso.o ...

  7. boost::filesystem总结

    boost::filesystem是Boost C++ Libraries中的一个模块,主要作用是处理文件(Files)和目录(Directories).该模块提供的类boost::filesyste ...

  8. mysql自动更新时间

    ALTER TABLE sys_user MODIFY COLUMN update_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDAT ...

  9. 3n+1猜想——模拟

    package dxb.com; import java.util.Scanner; public class caixiang { public static void main(String[] ...

  10. C# 多线程之Task(任务

      1.简介 为什么MS要推出Task,而不推Thread和ThreadPool,以下是我的见解: (1).Thread的Api并不靠谱,甚至MS自己都不推荐,原因,它将整个Thread类都不开放给W ...