在Java開發中有一個看似簡單,但在網路上有大量關於話題和問題,就是equals() 和== 運算子有什麼差別
今日內容介紹,大約花費9分鐘
圖片
為了更好地理解這個區別,讓我們來看一個例子:
String str1 = new String("Hello");String str2 = new String("Hello");System.out.println(str1.equals(str2)); // 输出 trueSystem.out.println(str1 == str2); // 输出 false
範例中,雖然兩個字串的內容相同,但它們在記憶體中的位址是不同的。因此,使用.equals()方法比較它們的內容會回傳true,而使用"=="運算子比較它們的位址會傳回false
學習過Java基礎的,應該知道Java所有類別都預設繼承Obejct類,Object類別中有一個.equals()方法
public boolean equals(Object obj) {return (this == obj);}
從程式碼大家可以發現.equals( )方法預設採用==運算子比較,如果子類別沒有重寫equals()方法,那麼就使用==運算子和equals()方法結果完全一樣--用來比較兩個物件記憶體位址是否相等。
但是實際情況是,有很多類別重寫equals()方法,這是因為記憶體位址比較要求比較嚴格,不太符合現實中所有的場景需求,例如String類,進行比較時,大多只想判斷內容是否相等,並不太想知道記憶體位址是否相等(是否為物件)。
在深入研究Java字串常數池的文章中,我們已經了解到Java虛擬機器為了優化記憶體利用和提升效能而專門為字串分配了一個獨立的空間-字串常數池。
建議優先使用 String s = "Hello" 這種方式建立字串對象,而不是使用 new 關鍵字,因為 new 需要額外在堆上分配記憶體空間。
Jdk11的String類別的equals()方法
public boolean equals(Object anObject) { //如果是同一个对象(即两个引用指向内存中的同一块地址),则直接返回trueif (this == anObject) {return true;} //如果是String类型的实例if (anObject instanceof String) { //Object类型的对象强制转换为String类型String aString = (String)anObject;//如果当前字符串对象和传入的字符串对象的编码方式相同if (coder() == aString.coder()) { //如果当前字符串和传入的字符串都是Latin1编码,则调用StringLatin1类的equals方法进行比较;如果其中一个或两个字符串是UTF16编码,则调用StringUTF16类的equals方法进行比较return isLatin1() ? StringLatin1.equals(value, aString.value): StringUTF16.equals(value, aString.value);}}return false;}
特別說明:Latin1(也稱為ISO 8859-1)和UTF-16(Unicode轉換格式16位元)是兩種不同的字元編碼方式
Latin1和UTF-16雖然是兩種編碼方式,但是差別不大,就拿UTF-16 的來的equals()方法來看
@HotSpotIntrinsicCandidatepublic static boolean equals(byte[] value, byte[] other) {if (value.length == other.length) {int len = value.length >> 1;for (int i = 0; i
注意:Java8和Java11的equals()方法原始碼是有區別的JDK8的equals()方法
public boolean equals(Object anObject) {// 如果是同一个对象(即两个引用指向内存中的同一块地址),则直接返回trueif (this == anObject) {return true;}// 如果是String类型的实例if (anObject instanceof String) {////Object类型的对象强制转换为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;}
範例一:
new String("hello").equals("hello")
輸出結果是什麼?
String類別的equals方法比較的是字串物件的內容是否相等,因為都是"Hello",所以結果是true
範例二:
new String("hello") == "hello";
輸出結果是什麼?
==運算子比較的物件地址是否相等,==左邊是堆中建立對象,右邊是字串常數池對象,雖然內容相等,但是地址不相等,所以結果是false
範例三:
new String("hello") == new String("hello");
輸出結果是什麼?
#new 出來的物件一定是完全不同的記憶體位址,所以結果是false
範例四:
"hello" == "h"+"ello"
輸出結果是什麼?
h和ello都在字串常數池,所以編譯器在遇到操作符的時候將其自動最佳化為hello,所以結果是true
範例五:
new String("hello").intern() == "hello"
輸出結果是什麼?
new String("hello")在執行的時候,會先在字串常數池中創建對象,然後再在堆中創建對象;執行intern() 方法的時候發現字符串常數池中已經有了'hello'這個對象,所以就直接返回字串常數池中的物件引用了,那再與字串常數池中的'hello'比較,所以結果是true
深入解析String.intern()已經介紹過原因
除了.equals()方法和"=="運算子外,還有一些其他比較方法可以使用:
Objects.equals("Hello", new String("Hello")); // 返回 true
String str = "Hello";StringBuffer buffer = new StringBuffer("Hello");System.out.println(str.contentEquals(buffer)); // 输出 true
以上是Java中的equals()與==的差異與用法的詳細內容。更多資訊請關注PHP中文網其他相關文章!