一光年

[Java-基础] int和Integer比较用==还是equals,傻傻分不清

2019.06.18

使用int或Integer进行比较时,常常==和equals都可以使用,结果也往往是正确的。直到遇到以下情况:

  int a = 128;
  Integer b = 128;
  if (a == b) {
    ...
  }

为什么if条件判断返回false呢?什么情况下又会返回true呢?这里的==操作符,涉及到了3个知识点。

1.包装类

一般来讲,==操作符只适用于基本类型的比较,equals操作符适用于对象类型的比较。但对于int和Integer、float和Float等的变量之间,也可以用前者来进行比较。

包装类在比较时如果使用了==,则会自动拆箱为基本类型进行比较。所以以下比较,语法上也是可以的。

  Integer a = new Integer(10);
  Integer b = new Integer(11);
  if (a == b) {
    ...
  }

2.常量缓存

对于一个类或一个方法,在运行时类或方法中定义的常量都是保存在缓存区的。如果是一个基本类型,如:

  int a = 10;
  int b = 10;
  int c = 10;

对于10这个常量,它只在缓存区保存在一个地址,abc这3个变量分别指向这个缓存地址即可。

如果是对象类型,如:

  Integer a = 10;
  Integer b = 10;
  Integer c = new Integer(10);

  a == b;       // TRUE (对象类型,比较的是地址,同一地址)
  a == c;       // FALSE(对象类型,比较的是地址,不同地址)
  a.equals(c);  // TRUE

a和b同样指向了同一个缓存地址,这个地址保存了常量10,c则指向了一个Integer常量的新地址。所以他们如果相互比较,则结果如上。

3.缓存限制

如果基本类型的常量都是缓存在同一地址,那为何在比较int(128)和Integer(128)时又返回false了呢?

原因在于Integer作为常量时,只有8位范围内的才会作为基本常量保存在缓存区中,8位的带符号数范围刚好是[-128, 127]。如果超过这个范围,即使定义如:

  Integer a = 128;
  Integer b = new Integer(128);

系统也会自动new一个Integer对象来保存a这个常量,和b的声明没有区别。

小测验

声明判断结果
int a = 8;
Integer b = 8;
a == b
int a = 8;
Integer b = new Integer(8);
a == b
Integer a = 8;
Integer b = 8;
a == b
Integer a = new Integer(8);
Integer b = new Integer(8);
a == b
Integer a = 8;
Integer b = 8;
a.equals(b)
Integer a = 128;
Integer b = 128;
a == b
Integer a = 128;
Integer b = 128;
a.equals(b)
int a = 128;
Integer b = 128;
a == b