一、== 运算符
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);
System.out.println(a == c);
}
}
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;
}
}
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);
System.out.println(book2);
System.out.println(book1 == book2);
}
}
即使 book1 与 book2 对象的属性值相同,他们 == 的结果还是 false,就是因为内存地址不同。
1.2.2 String 对象的 == 运算
-
new 方式 String a = new String("yunhu");
String b = new String("yunhu");
System.out.println(a == b);
因为 a 和 b 都是 String 的对象引用,即使内容相同,但是指向的是不同的内存地址。 -
直接赋值方式 String aa = "yunhu";
String bb = "yunhu";
System.out.println(aa == bb);
直接赋值,对象存储在常量池中。 虚拟机会在常量池中寻找是否已经有与将要创建的值相同的对象,如果有直接赋值给当前的引用,如果没有,新建一个 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));
判断对象地址,当然不同。
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;
}
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;
}
}
}
Book book1 = new Book();
book1.setBookName("西游记");
book1.setBookAuthor("吴承恩");
Book book2 = new Book();
book2.setBookName("西游记");
book2.setBookAuthor("吴承恩");
System.out.println(book1.equals(book2));
2.3 String 的 equals()
String a = new String("yunhu");
String b = new String("yunhu");
System.out.println(a.equals(b));
想了想,这不对啊,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);
}
再看下 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;
}
确实是在比较值。
|