Integer 和 int 的比较问题

Posted 刘润森!

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Integer 和 int 的比较问题相关的知识,希望对你有一定的参考价值。

本文主要分析 Integer 和 int 之间的比较问题,接下来慢慢展开。

版本约定

  • JDK 版本:1.8.0_231
  • Java SE API Documentation:https://docs.oracle.com/javase/8/docs/api/

正文

引用类型缓存池

我们先来看一段代码,猜猜它的执行结果是什么样子?

public static void main(String[] args) 
    Integer a = new Integer(123);
    Integer b = new Integer(123);
    System.out.println("a == b: " + (a == b));
    Integer c = Integer.valueOf(123);
    Integer d = Integer.valueOf(123);
    System.out.println("c == d: " + (c == d));
    Integer e = Integer.valueOf(128);
    Integer f = Integer.valueOf(128);
    System.out.println("e == f: " + (e == f));

运行程序,输出:

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

这里的执行结果和我们想象的结果有出入,有两点疑问:

  1. 为什么 new Integer(123) 和 Integer.valueOf(123) 的执行结果不一样?
  2. 为什么 Integer.valueOf(123) 和 Integer.valueOf(128) 的执行结果不一样?

带着这两个问题,我们来看看 Integer 类的源码,先看下 valueOf() 方法的源码。

public static Integer valueOf(int i) 
    if (i >= IntegerCache.low && i <= IntegerCache.high)
        return IntegerCache.cache[i + (-IntegerCache.low)];
    return new Integer(i);

IntegerCache 是什么?看看它的源码内容。

/**
 * Cache to support the object identity semantics of autoboxing for values b
 * -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.hig
        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() 

根据注释描述,我们知道 IntegerCache 是 Integer 的一个内部缓存池,默认缓存 -128 到 127 的整数,另外描述中还讲到自动装箱的概念,下面会提到。

我们再看 valueOf() 方法就知道了,它的实现比较简单,就是先判断值是否在缓存池中,如果在的话就直接返回缓存池的内容。

这样,上面的两个问题,你应该就知道原因了吧。

接下来,我们来看上面提到的自动封装的概念,下面的代码,大家一定不会陌生。

public static void main(String[] args) 
    Integer a = 1;
    System.out.println(a);

我们经常这样初始化 Integer 类型,编译器在把 int 类型的数据封装成 Integer 类型的操作就叫做自动装箱。

编译器会在自动装箱过程中会调用 valueOf() 方法,因此多个 Integer 实例使用自动装箱来创建并且值相同(范围:-128 ~ 127),那么就会引用相同的对象。

测试代码:

public static void main(String[] args) 
    Integer a = 123;
    Integer b = 123;
    System.out.println("a == b: " + (a == b));

运行程序,输出:

a == b: true

其他基本类型对应的引用类型是否也存在缓存池呢?它的缓存范围是多少呢?总结如下:

  • boolean values true and false
  • all byte values
  • short values between -128 and 127
  • int values between -128 and 127
  • char in the range \\u0000 to \\u007F

Integer 和 int 的比较

结合上面的源码分析,我们可以得出如下结论:

  1. 当 int 类型和它的引用类型 Integer 比较的时候,Integer 会自动拆箱,转换为 int 类型进行比较,所以可以直接使用 == 进行比较是否相等。

测试代码:

public static void main(String[] args) 
    int a = 200;
    Integer b = 200;
    Integer c = new Integer(200);
    System.out.println("a == b: " + (a == b));
    System.out.println("a == c: " + (a == c));

运行程序,输出:

a == b: true
a == c: true
  1. 当是两个引用类型 Integer 比较的时候,使用 equals 方法进行比较,否则容易出现意想不到的结果。

测试代码:

public static void main(String[] args) 
    Integer a = 127;
    Integer b = 127;
    System.out.println("a == b : " + (a == b));
    System.out.println("a.equals(b): " + a.equals(b));
    Integer c = 128;
    Integer d = 128;
    System.out.println("c == d: " + (c == d));
    System.out.println("c.equals(d): " + c.equals(d));
    Integer e = 127;
    Integer f = new Integer(127);
    System.out.println("e == f: " + (e == f));
    System.out.println("e.equals(f): " + e.equals(f));

运行程序,输出:

a == b : true
a.equals(b): true
c == d: false
c.equals(d): true
e == f: false
e.equals(f): true

总结

这种看似很小的问题也不能忽视,代码执行正确与否,很多时候在于细节的处理。

以上是关于Integer 和 int 的比较问题的主要内容,如果未能解决你的问题,请参考以下文章

《Java架构筑基》从Java基础讲起——Int和Integer深入分析

Java中int和Integer的区别

经典面试题:Integer类型 ==比较问题

java里Integer类在-128和127之间为啥能直接用==比较,好像还只能在自动装箱的时候是吗?求详解,谢谢啦!

java int 和 Integer

java int 和 Integer