[1] 先讨论一个面试题
int a = 1;
Integer b = 1;
Integer c = new Integer(1);
Integer d = Integer.valueOf(1);
int e = d;
int f = d.intValue();
请问以下式子的值?为什么?
a == b // true
a == c // true
b == c // false
[2] "=="与"equals"用法的不同
对于Java中的判断相等,有两种方法:
· 操作符==
· 方法equals
对于==操作符来说,区分是基本类型还是引用类型:
1、如果比较的数据是基本类型,则比较它们的值;
2、如果比较的是对象,则会比较对象的内存地址。
3、另外,如果一个是基本类型、一个是包装类型,在比较前会先把包装类型拆箱成基本类型,然后进行比较。
equals方法是用来判断其他的对象是否和该对象相等,equals()方法在Object类中定义如下:
public boolean equals(Object obj) {
return (this == obj);
}
很明显是对两个对象的地址值进行的比较(即比较引用是否相同)。但是我们知道,String 、Math、Integer、Double等这些封装类在使用equals()方法时,已经覆盖了object类的equals()方法。
所以对于equals来说,区分调用者是否重写了equals方法:
1、类没有重写equals()方法:通过equals()比较该类的两个对象时,等价于通过“==”比较这两个对象,使用的默认是Object类equals()方法,比较它们的地址值。
2、类重写了equals()方法:一般我们都重写equals()方法来比较两个对象中的属性是否相等;若它们的属性相等,则返回true(即认为这两个对象相等)。
【注意】
equals()不能用于判断基本数据类型的变量,只能用来判断两个对象是否相等。
[3] 基本类型和包装类型的区别
1、对于基本类与包装类的转换,Java提供了装箱、拆箱机制;
2、包装类的缓存机制。Byte , Short , Integer , Long这 4 种包装类默认创建了数值 [-128,127]的相应类型的缓存数据, Character创建了数值在[0,127]范围的缓存数据,Boolean直接返回 True or False ;
3、Java语言是面向对象的,但是Java的基本数据类型不是,将基本数据类型设计成类,可以增强Java面向对象的性质;
4、包装类可以用于泛型,而基本类型不可以;
5、基本类型在栈中直接存储的具体数值,而包装类型则存储的是堆中的引用。包装类型需要占用更多的内存空间。假如没有基本类型的话,对于数值这类经常使用到的数据来说,每次都要通过new一个包装类型就显得非常笨重。
[4] 3种创建基本类型的方式
以int为例,这里我们把参与比较的类型分为三种:int、直接new出来的Integer对象和自动装箱出来的Integer对象。分类细节如图:

[4.1] int
int a = 1;
Integer b = 1;
int e = b;
int f = b.intValue();
如上代码中,变量a、e、f的创建:
a属于直接创建;
e是对Integer类型进行自动拆箱,转化成int类型;
f是调用变量b的intValue()方法,可以理解为显式的拆箱。
[4.2] 直接new出来的Integer对象
Integer c = new Integer(1);
没啥好说的。包装类型存储的是堆中的引用。
[4.3] 自动装箱出来的Integer对象
Integer b = 1;
Integer c = 128;
Integer d = Integer.valueOf(1);
如上代码中,变量b、c的创建使用了自动装箱机制,自动装箱机制会调用指定包装类的valueOf方法,像变量d那样。
由于具有包装类自动装箱时具有缓存机制,而它就是通过valueOf方法实现的,其代码如下:
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
可以看到,在范围[-128,127]之间,包装类Integer自动装箱定义时会返回缓存中数据。
[5] 综上,我们回到面试题
int a = 1; // 直接定义,存在栈中
Integer b = 1; // 自动装箱,且1在[-128,127],b是缓存中数据
Integer c = new Integer(1); // new对象,存在堆中的引用
由于对于操作符==,如果一个是基本类型、一个是包装类型,在比较前会先把包装类型拆箱成基本类型,然后进行比较。所以a == b、a == c都为true。
对于同样是包装类型的变量b、c,操作符==比较的是它们的引用,而一个是缓存中数据,一个在堆中,所以b == c为false。
a == b // true
a == c // true
b == c // false
【注意】对于变量
b、c的比较,它们是引用类型了,我们应该使用equals()来判断它们的值是否相等,IDEA会有提示。而变量a、b,变量a、c之间的比较,不能用equals(),因为基本类型不可以使用equals()。



















