# Java == 与 equals() 的区别
# 一、== 运算符
# 1.1 基本类型的 == 运算
对于基本数据类型来说,== 比较的是值
public class Main {
public static void main(String[] args) {
int a = 10;
int b = 20;
int c = 10;
System.out.println(a == b); // output: false
System.out.println(a == c); // output: true
}
}
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
# 1.2 引用类型的 == 运算
对于引用数据类型来说,== 比较的是对象的内存地址。
# 1.2.1 普通对象的 == 运算
public class Book {
private String bookName;
private String bookAuthor;
public Book() {
}
public String getBookName() {
return this.bookName;
}
public void setBookName(String bookName) {
this.bookName = bookName;
}
public String getBookAuthor() {
return this.bookAuthor;
}
public void setBookAuthor(String bookAuthor) {
this.bookAuthor = bookAuthor;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class Main {
public static void main(String[] args) {
Book book1 = new Book();
book1.setBookName("西游记");
book1.setBookAuthor("吴承恩");
Book book2 = new Book();
book1.setBookName("西游记");
book1.setBookAuthor("吴承恩");
System.out.println(book1); // output: Book@16b98e56
System.out.println(book2); // output: Book@7ef20235
System.out.println(book1 == book2); // output: false
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
即使 book1 与 book2 对象的属性值相同,他们 == 的结果还是 false,就是因为内存地址不同。
# 1.2.2 String 对象的 == 运算
- new 方式
String a = new String("yunhu");
String b = new String("yunhu");
System.out.println(a == b); // output: false
1
2
3
2
3
因为 a 和 b 都是 String 的对象引用,即使内容相同,但是指向的是不同的内存地址。
- 直接赋值方式
String aa = "yunhu";
String bb = "yunhu";
System.out.println(aa == bb); // output: true
1
2
3
2
3
直接赋值,对象存储在常量池中。 虚拟机会在常量池中寻找是否已经有与将要创建的值相同的对象,如果有直接赋值给当前的引用,如果没有,新建一个 String 对象。
# 二、equals()
equals() 只判断对象是否相等,没有重写 equals()
函数的话,判断的依据是对象的地址是否相同。
# 2.1 没有重写 equals()
Book book1 = new Book();
book1.setBookName("西游记");
book1.setBookAuthor("吴承恩");
Book book2 = new Book();
book2.setBookName("西游记");
book2.setBookAuthor("吴承恩");
System.out.println(book1.equals(book2)); // output: false
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
判断对象地址,当然不同。
# 2.2 重写 equals()
这边为了方便,没有重写 hashCode
方法, 不过不影响理解。
public class Book {
private String bookName;
private String bookAuthor;
public String getBookName() {
return bookName;
}
public void setBookName(String bookName) {
this.bookName = bookName;
}
public String getBookAuthor() {
return bookAuthor;
}
public void setBookAuthor(String bookAuthor) {
this.bookAuthor = bookAuthor;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
// 判断 obj 对象是不是 Book 类的
if (!(obj instanceof Book)) {
return false;
}
Book book = (Book)obj;
if(book == null) {
return false;
}
if (this.bookName.equals(book.getBookName()) && this.bookAuthor.equals(book.getBookAuthor())) {
// 属性值相同,认为是同一个对象
return true;
}else {
return false;
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
Book book1 = new Book();
book1.setBookName("西游记");
book1.setBookAuthor("吴承恩");
Book book2 = new Book();
book2.setBookName("西游记");
book2.setBookAuthor("吴承恩");
System.out.println(book1.equals(book2)); // output: true
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# 2.3 String 的 equals()
String a = new String("yunhu");
String b = new String("yunhu");
System.out.println(a.equals(b)); // output: true
1
2
3
2
3
想了想,这不对啊,a、b 是对象引用,equals 比较的是地址,这两个地址不同啊,怎么会返回 true。
String 确实是对象,但是它特殊处理了,重写了 equal 函数,变成比较值,而不是内存地址。
String equals 方法的源码:
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
return (anObject instanceof String aString)
&& (!COMPACT_STRINGS || this.coder == aString.coder)
&& StringLatin1.equals(value, aString.value);
}
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
再看下 StringLatin1
类的 equals 源码:
@IntrinsicCandidate
public static boolean equals(byte[] value, byte[] other) {
if (value.length == other.length) {
for (int i = 0; i < value.length; i++) {
if (value[i] != other[i]) {
return false;
}
}
return true;
}
return false;
}
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
循环比较值。