- 本文已参与「新人创作礼」活动,一起开启掘金创作之路。
大家好,我是卷心菜,可以叫我菜菜(名副其实了属于是,哈哈~),大二学生一枚。本篇主要讲解一道java面试题:==操作符和equals()的知识点。如果您看完文章有所收获,可以三连支持博主哦~,嘻嘻。
一、前言
要想理解它们之间的区别,首先要了解一下它们的定义。
- 当比较引用数据类型时,
==
比较的是变量的内存地址是否相同,即是否指向同一个对象,是真正意义上的指针操作。 equals()
比较的是两个对象的内容是否相同,由于所有的类都是继承java.lang.Object
类的,所以适用于所有对象,如果没有对该方法进行覆盖的话,调用的仍然是Object类中的方法,而Object中的equals方法返回的却是==
的判断。- 也就是说
==
是一个指针操作,用来比较数值相等,而equals则是一个方法,在Object类中equals方法中使用其实就是==
,如果子类不重写equals方法,两者则并没有什么不同。
二、源码解析
先看看Object类中的源码: 从源码中可以看出,两者比较的是地址值。
再来看看String类中的源码: 从源码中可以看出,String类重写了Object类的equals方法,首先判断两者的地址,如果相等,就直接返回true;不然,就接着判断参数是否是String类型的,如果是,就逐一比较每一个字符内容,最终返回结果。
最后再看看Integer类的源码: 从源码中可以知道,首先判断参数是否是Integer类型的;如果是,就会调用intValue(),获取该参数的数值,最后两者进行比较;简单的来说,他们最终比较的是数值。
三、基本数据类型比较
对于基本数据类型的比较,只有==
操作符,因为基本数据类型不是对象,没有继承Object类,自然也不能重写equals方法。需要注意的是,在使用==
操作符时,会出现自动类型转换,看看如下代码:
public void test1() {
int i = 10;
int j = 10;
double d = 10.0;
System.out.println(i == j);//true
System.out.println(i == d);//true
boolean b = true;
// System.out.println(i == b);编译就会出现错误
char c = 10;
System.out.println(i == c);//true
System.out.println(c == d);//true
char c1 = 'A';
char c2 = 65;
System.out.println(c1 == c2);//true
}
四、引用数据类型比较
在引用数据类型的使用过程中,最常用的就是String类了,那么我们就来看看如下代码,尝试自己想一想运行的结果:
public void test2() {
String s1 = "hello";
String s2 = "hello";
System.out.println(s1 == s2);
System.out.println(s1.equals(s2));
String str1 = new String("hello");
String str2 = new String("hello");
System.out.println(str1 == str2);
System.out.println(str1.equals(str2));
System.out.println(s1 == str1);
System.out.println(s1.equals(str1));
}
最终的运行结果是:true
、true
、false
、true
、false
、true
- 首先看代码的前半部分,
s1 == s2
的结果是true,是因为字符串的值是final,其值不可变,在内存中只有一份,所以s1和s2的地址值是一样的。 - 最后看代码的后半部分,因为str1和str2使用了关键字new,即在内存中开辟了两块空间,他们的地址值不相同,所以str1 == str2 的结果是false。
让我们看最后一组代码:
public void test3() {
int a = 10;
Integer b = new Integer(10);
Integer c = new Integer(10);
System.out.println(b == c);
System.out.println(a == c);
System.out.println(b.equals(c));
System.out.println(c.equals(a));
}
运行结果是:false
、true
、true
、true
- 对于
a==c
这个为什么返回的也是true呢?难道变量a和c存放的内存地址是一样的吗?这显然不正确,毕竟a是基本数据类型,存放的地址是栈中的地址,而c是引用数据类型,存放的地址应当指向对中的地址。这是因为当Integer与int进行==
比较时,Integer就会拆箱成一个int类型,所以还是相当于两个int类型进行比较,这里的Integer,不管是直接赋值,还是new创建的对象,只要跟int比较就会拆箱为int类型,所以就是相等的。其实所有的包装类在和其基本数据类型==
比较时都会自动拆箱。
五、自定义实现equals方法
那么问题来了,如果我们要自己写的类,也想要重写equals方法该怎么办呢?其实很简单,使用Alt+insert
后选择如图即可:
写个代码测试:
public void test4() {
Person person1 = new Person("cabbage",20);
Person person2 = new Person("cabbage",20);
System.out.println(person1.equals(person2));
}
如果运行结果返回true,那么恭喜你,成功了~
六、小结
- 当用equals()方法进行比较时,对类File、String、Date及包装类来说,是比较类型及内容而不考虑引用的是否是同一个对象;是因为在这些类中都重写了Object类的equals()方法。
- 最后给一个参考答案:
感谢阅读,一起进步,嘻嘻~