Java中equals()和==的异同

本文结合实例分析了Java中equals和==操作符的异同,参考了诸多文献,并给出了相应的实例程序。

In Java, all variables are either primitive types or references.
Java中所有变量均为直接数据类型或引用

==: 比较引用是否指向同一个对象。
.equals(): 比较引用所指向对象的内容(值)是否相同(不同类可自定义重写该方法)。

== operator checks if the references of both the objects are the same.
equals method compares values for equality.
Java中equals和==的区别 值类型是存储在内存中的堆栈(简称栈),而引用类型的变量在栈中仅仅是存储引用类型变量的地址,而其本身则存储在堆中。
==操作比较的是两个变量的值是否相等,对于引用型变量表示的是两个变量在堆中存储的地址是否相同,即栈中的内容是否相同。
equals操作表示的两个变量是否是对同一个对象的引用,即堆中的内容是否相同。

Java中默认类的equals方法为继承自Object类,其原始定义为直接调用==进行引用是否指向相同对象的比较,代码如下:

1
2
3
public boolean equals(Object obj){
return (this == obj);
}

重要:对于未重写equals方法的类而言,==与equals的结果是相同的,其均为比较两个引用是否指向相同的对象。

实例说明

声明:==比较的是2个对象的地址,而equals比较的是2个对象的内容。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class TestString {   
public static void main(String[] args) {
String s1 = "Monday";
String s2 = new String("Monday");
if (s1 == s2)
System.out.println("s1 == s2");
else
System.out.println("s1 != s2");
if (s1.equals(s2))
System.out.println("s1 equals s2");
else
System.out.println("s1 not equals s2");
}
}

程序运行结果为:

1
2
s1 != s2
s1 equals s2

实例分析

s1为指向字符串常量的引用,s2为指向堆中对象的引用,二者指向对象不同,故==返回为false;二者内容相同,则equals返回为true。

关于String类的==和equals方法的补充

String类中equals方法的实现:
String.equals() Details

字符串缓冲池

测试程序如下:

1
2
3
4
5
6
7
8
9
10
   public class TestString {   
public static void main(String[] args) {
String s1 = "Monday";
String s2 = "Monday";
if (s1 == s2) //here is true
System.out.println("s1 == s2");
else
System.out.println("s1 != s2");
}
}

原来,程序在运行的时候会创建一个字符串缓冲池
当使用 s2 = “Monday” 这样的表达是创建字符串的时候,程序首先会在这个String缓冲池中寻找相同值的对象,在上述程序中,s1先被放到了池中,所以在s2被创建的时候,程序找到了具有相同值的s1,将 s2引用s1所引用的对象”Monday” .
最终程序输出结果为:

s1 == s2

Intern方法

测试代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class TestString {   
public static void main(String[] args) {
String s1 = "Monday";
String s2 = new String("Monday");
s2 = s2.intern();
if (s1 == s2)
System.out.println("s1 == s2");
else
System.out.println("s1 != s2");
if (s1.equals(s2))
System.out.println("s1 equals s2");
else
System.out.println("s1 not equals s2");
}
}

程序输出:

s1 == s2
s1 equals s2 

String.Intern()所进行的特殊工作

java.lang.String的intern()方法:检查字符串池里是否存在”Monday”这个字符串,如果存在,就返回池里的字符串的引用;如果不存在,该方法会把”Monday”添加到字符串池中,然后再返回它的引用。

总结

Every variable in Java is either primitive types or references.

参考

  1. java-string-equals-versus
  2. ==, .equals(), compareTo(), and compare()
  3. java中equals和==的区别
  4. Java中Object类的equals()和hashCode()方法深入解析