Java中 equal 和 == 的区别
在学C和C++语言的时候,用来比较的运算符就是==
,而在Java中,如果依然使用==
来比较,就不行,比如:
public class Test1 {
public static void main(String[] args){
String str1 = "Hello World";
String str2 = new String("Hello World");
String str3 = str2;
String str4 = str1;
String str5 = "Hello World";
String str6 = new String("Hello World");
//打印结果
System.out.println("str1 == str2:"+(str1 == str2));
System.out.println("str1 == str3:"+(str1 == str3));
System.out.println("str1 == str4:"+(str1 == str4));
System.out.println("str1 == str5:"+(str1 == str5));
System.out.println("str2 == str3:"+(str2 == str3));
System.out.println("str2 == str6:"+(str2 == str6));
}
}
这段代码的执行结果为:
str1 == str2:false
str1 == str3:false
str1 == str4:true
str1 == str5:true
str2 == str3:true
str2 == str6:false
从这里我们可以看出:
- 虽然,str1和str2的值都是
Hello World
,但是这两个用==
作比较,结果是false; - str1和str3做比较,结果也是false,还是可以理解的,因为str3是通过str2赋值得到的,所以两个的比较结果应该一致;
- str1和str4比较结果为true,可以理解,因为str4是通过str1赋值得到的;
- str1和str5比较,结果也为true,那str1和str5有什么一样的吗?
- 相同第一处:值都是
Hello World
; - 相同第二处:都不是通过new的方式赋值,而str2是通过new的方式赋值的;
- 相同第一处:值都是
- str2和str3比较结果为true,这个跟前面说到的一样,因为是通过赋值得到的,所以结果应该是一致的;
- str2和str6做比较,结果为false,这是为什么?用
==
比较的结果为false- 相同第一处:值都是
Hello World
; - 相同第二处:都是通过new的方式赋值;
- 相同第一处:值都是
看到这里,可能有读者会发现,这个new
关键字有问题,似乎只要new
一下,再用==
比较,结果就为false。
那为什么会这样呢?从内存角度来说,一般会把对象的引用放在栈,对象则放在堆,那么就变成下面这样:
建议看看JVM
哦!所以说不能用==
来比较值是否一样了,那么可以用什么呢?可能有人会说用String的equal()
方法,那我们试试咯:
public class Test1 {
public static void main(String[] args){
String str1 = "Hello World";
String str2 = new String("Hello World");
String str3 = str2;
String str4 = str1;
String str5 = "Hello World";
String str6 = new String("Hello World");
//打印结果
System.out.println("str1.equals(str2):"+str1.equals(str2));
System.out.println("str1.equals(str4):"+str1.equals(str4));
System.out.println("str1.equals(str5):"+str1.equals(str5));
System.out.println("str2.equals(str6):"+str2.equals(str6));
}
}
结果:
str1.equals(str2):true
str1.equals(str4):true
str1.equals(str5):true
str2.equals(str6):true
那么,是不是意味着,我们以后需要比较对象的值是否一致就用equals()
方法就好了?那么,我们试下下面这种用法:
public class Test1 {
public static void main(String[] args){
//1,这里主要是为了看是否引用了同个对象
Student stu1 = new Student(10, "小明");
Student stu2 = stu1;
System.out.println("stu1:"+ stu1);
System.out.println("stu2:"+ stu2);
System.out.println("stu1.age:"+stu1.getAge() +" and stu1.name:" + stu1.getName());
System.out.println("stu2.age:"+stu2.getAge() +" and stu2.name:" + stu2.getName());
System.out.println("stu1 == stu2:"+ (stu1 == stu2));
System.out.println("stu1 equals stu2:"+ stu1.equals(stu2));
//2,这里是想看,对一个引用的对象进行修改,另一个引用的对象的值会不会跟着修改,对上面所讲内容的实践检测
stu2.setAge(20);
stu2.setName("小王");
System.out.println("stu1.age:"+stu1.getAge() +" and stu1.name:" + stu1.getName());
System.out.println("stu2.age:"+stu2.getAge() +" and stu2.name:" + stu2.getName());
System.out.println("stu1 == stu2:"+ (stu1 == stu2));
System.out.println("stu1 equals stu2:"+ stu1.equals(stu2));
//3,这里是为了验证equals是否能用来比较自定义对象的内容的值
Student stu3 = new Student(20, "小王");
System.out.println("stu2:"+ stu2);
System.out.println("stu3:"+ stu3);
System.out.println("stu2.age:"+stu2.getAge() +" and stu2.name:" + stu2.getName());
System.out.println("stu3.age:"+stu3.getAge() +" and stu3.name:" + stu3.getName());
System.out.println("stu2 == stu3:"+ (stu2 == stu3));
System.out.println("stu2 equals stu3:"+ stu2.equals(stu3));
}
}
class Student{
private int age;
private String name;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Student(int age, String name) {
super();
this.age = age;
this.name = name;
}
}
这段代码的执行结果为:
stu1:firstreview.Student@1540e19d
stu2:firstreview.Student@1540e19d
stu1.age:10 and stu1.name:小明
stu2.age:10 and stu2.name:小明
stu1 == stu2:true
stu1 equals stu2:true
stu1.age:20 and stu1.name:小王
stu2.age:20 and stu2.name:小王
stu1 == stu2:true
stu1 equals stu2:true
stu2:firstreview.Student@1540e19d
stu3:firstreview.Student@677327b6
stu2.age:20 and stu2.name:小王
stu3.age:20 and stu3.name:小王
stu2 == stu3:false
stu2 equals stu3:false
从结果可以看到,stu1和stu2引用的是同一个对象,值也相同,所以用==
和equals()
比较的结果都为true,而且,修改一个stu2引用对象的值之后,stu1引用对象的值也跟着变了,验证结果正确。new
了stu3之后,可以看到的是,stu3和stu2引用的对象不是同一个,而且值得注意的是,stu2和stu3==
的比较结果为false,这个我们理解,因为==
比较的是引用的对象是否是同一个,很明显是不同对象。但是为什么equals()
比较的结果也为false呢?
这里我们可以看下equals()
的源码:
/* @param obj the reference object with which to compare.
* @return {@code true} if this object is the same as the obj
* argument; {@code false} otherwise.
* @see #hashCode()
* @see java.util.HashMap
*/
public boolean equals(Object obj) {
return (this == obj);
}
这段源码的大概意思是:equals()
方法比较的是2个引用的对象是否是同一个。
但是我们上面说了equals()
是可以用来比较对象的值的,但是这里的源码所表示的却是说,它的功能和==
是一样的。
我们看下这个equals()
方法所属的类,可以看到,是Object
类的,Object是最基础的类,所有new出来的类都继承自它,所以说这里的equals()
源码是最基础的,难道是之前用的String
类重写了该方法???
/* @return {@code true} if the given object represents a {@code String}
* equivalent to this string, {@code false} otherwise
*
* @see #compareTo(String)
* @see #equalsIgnoreCase(String)
*/
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
确实!源码都长得不一样了。所以说,比较对象的内容是否相等,是需要重写equals()
方法的,那至于怎么写,就得根据大家的业务需要自行重写了。