1、==
先来聊聊双等号int a = 10;int b = 20;int c = 10;// falseSystem.out.println(a == b);// trueSystem.out.println(a == c);
。
它是 Java 程序语言中的运算符,隶属于比较运算符,其用于判断两个变量或者常量的大小,比较的结果是一个布尔值(true 或 false)。
比较时会出现两种情况:
- 基本类型比较
- 引用类型比较
基本类型比较:对于基本类型,那比较的就是值了。
int a = 10; int b = 20; int c = 10; // false System.out.println(a == b); // true System.out.println(a == c);
上述代码结果表明,用 == 比较基本类型变量时,只有变量的值相同时,才返回 true。
引用类型比较:引用类型,比较的是引用所指向的地址。
User user01 = new User(); User user02 = new User(); User user03 = user01; // false System.out.println(user01 == user02); // true System.out.println(user01 == user03); // 地址 // cn.baiqi.myjava.methods.User@dfd3711 System.out.println(user01); // cn.baiqi.myjava.methods.User@42d3bd8b System.out.println(user02); // cn.baiqi.myjava.methods.User@dfd3711 System.out.println(user03);
上述代码结果表明,user01 和 user03 的引用地址相同,所以 == 比较才返回 true,user01 和 user02 引用地址不同,所以才返回 false。
对于双等号比较引用类型还有一个特例,看下面代码。
// 定义三个引用类型变量 Integer integer01 = 10; Integer integer02 = 100; Integer integer03 = 10; // false System.out.println(integer01 == integer02); // true System.out.println(integer01 == integer03); // 打印出变量地址 // java.lang.Integer@a System.out.println(integer01.getClass().getName() + '@' + Integer.toHexString(integer01.hashCode())); // java.lang.Integer@64 System.out.println(integer02.getClass().getName() + '@' + Integer.toHexString(integer02.hashCode())); // java.lang.Integer@a System.out.println(integer03.getClass().getName() + '@' + Integer.toHexString(integer03.hashCode()));
结果和上一个案例又有点不一样了,好像对于这种引用类型,双等号比较的是值,而不是其所指向的引用地址一样。
其实其内部还是比较的地址,只不过 Integer 类型内部有一个缓存数组,它会缓存 -128 - 127 之间的数值。如果创建的 Integer 类型变量值符合其区间,那么引用变量所指向的地址都是该区间的值,不会另外创建。
Integer 内部缓存数值的代码。
2、equals
再来聊聊 equals。equals 是 Object 类中的一个方法,又因为 Object 是一个超类,所以任何对象都是可以调用该方法。在不重写该方法的情况下,其功能是比较两个对象的引用是否相等。
Object 类中 equals 方法源码。
很明显其底层比较的是两个引用类型所指向的地址是否相等,案例如下。
User user01 = new User(); User user02 = new User(); User user03 = user01; // false System.out.println(user01.equals(user02)); // true System.out.println(user01.equals(user03)); // 地址 // cn.baiqi.myjava.methods.User@dfd3711 System.out.println(user01); // cn.baiqi.myjava.methods.User@42d3bd8b System.out.println(user02); // cn.baiqi.myjava.methods.User@dfd3711 System.out.println(user03);
在 Java 中,String 和 Integer 类型内部重写了 equals 方法,其调用 equals 方法比较的就是值是否相等,源码如图:
示例代码如下。
String str01 = "J3-西行"; String str02 = "混迹互联网圈子的程序员"; String str03 = new String("J3-西行"); // false System.out.println(str01.equals(str02)); // true System.out.println(str01.equals(str03));
结果表明,String 类型重写 equals 方法后,只会比较值是否相等与内存地址无关。
通常,我们自己在重写 equals 方法时也是要遵循一定条件的,如下:
- 自反性:对任意 x ,x.equals( x ) 一定返回 true。
- 对称性:对任意 x 和 y ,如果 y.equals( x ) 返回 true ,则 x.equals( y ) 也返回 true
- 传递性:对任意的 x,y,z,如果 x.equals( y ) 返回 true,y.equals( z ) 返回 true 则 x.equals( z ) 一定返回 true。
- 一致性:对任意 x 和 y ,如果对象中用于等价比较的信息没有改变,那么无论调用 x.equals( y ) 多少次,返回的结果应该保持一致,要么一直是 true,要么一直是 false。
- 非空性:对任何不是 null 的 x,x.equals( null ) 一定返回 false。
3、两者对比
根据上面 1、2 节的内容,我们归纳对比出如下结果:
两者都是返回布尔类型结果(true 或 false)。
== 是 Java 提供的操作符,equals 是 Object 超类的一个方法。
== 在比较引用类型和基本数据类型时,功能不一样(一个比较地址,一个比较值)。
equals 在未重写的情况下是用来比较两个对象地址是否相等,本质上和 == 比较引用类型效果一样。
4、我的面试答案
面试官你好,我先说一下我对 == 的理解:
== 是 Java 程序语言定义的一个运算符,用于比较两者是否相等,返回一个布尔类型值(true 或 false)。如果 == 两边比较的是基本数据类型的话,则比较变量的值,两者相等返回 true 反之返回 false;如果两边比较的引用类型,则比较的是引用变量所指的是否是同一个内存地址,是则返回 true 反之 false。
对于 equals 的理解是:
equals 是 Object 超类的一个方法,其功能是比较两个对象内存地址是否相等。
Java中包装类型都重写了 equals 方法,将其实现成值比较,而不是地址比较,因为对于包装类型我们对值的比较实用性大于对地址的比较。
在重写 equals 方法时我们也应该遵循其自反性、对称性、传递性、一致性和为空性,才能说是一个合格的 equals 方法。
最后在说一下两者最大的一个区别可以说是一个为运算符,一个为方法,并且 == 既可以比较引用类型对象也可以比较基本类型,而 equals 只能比较引用类型对象。
到这里,内心窃喜,没有被难道。
今天的内容到这里就结束了,关注我,我们下期见