首頁 Java java教程 String使用equals方法和==分別比較的是什麼

String使用equals方法和==分別比較的是什麼

Dec 16, 2016 am 09:38 AM
equals

equals方法和==的差別

  首先大家知道,String既可以當作一個物件來使用,又可以當作一個基本型別來使用。這裡指的作為一個基本型別來使用只是指使用方法上的,例如String s = "Hello",它的使用方法如同基本型別int一樣,如int i = 1;,而作為一個物件來使用,則是指透過new關鍵字來建立一個新對象,例如String s = new String("Hello")。但是它的內部動作其實還是創造了一個對象,這點稍後會說到。

        其次,對String物件的比較方法有待了解。 Java裡物件之間的比較有兩種概念,這裡拿String物件來說:一種是用"=="來比較,這種比較是針對兩個String類型的變數的引用,也就是說如果兩個String類型的變數,它們所引用同一個String物件(即指向同一塊記憶體堆),則"=="比較的結果是true。另一種是用Object物件的equals()方法來比較,String物件繼承自Object,並且對equals()方法進行了重寫。兩個String物件透過equals()方法來比較時,其實就是對String物件所封裝的字串內容進行比較,也就是說如果兩個String物件所封裝的字串內容相同(包括大小寫相同),則equals()方法將傳回true。

現在開始將對String物件的建立做具體的分析:

1、/////////////////////////////// //////////////////////////////////////////

String s1 = new String( "Hello");

String s2 = new String("Hello");

System.out.println(s1 == s2);

System.out.println(s1.equals(s2));以上程式碼段的列印結果是:

false

tru​​e

        這個結果相信大家很好理解,兩個String類型的變數s1和s2都透過new關鍵字分別創造了一個新的String對象,這個new字為創建的每個物件分配一塊新的、獨立的記憶體堆。因此當透過"=="來比較它們所引用的是否是同一個物件時,將會傳回false。而透過equals()方法來比較時,則傳回true,因為這兩個物件所封裝的字串內容是完全相同的。

2、/////////////////////////////////////////////// ////////////////////////////////////

String s1 = new String("Hello");

String s2 = s1;

System.out.println(s1 == s2);

System.out.println(s1.equals(s2));

true

        這個結果應該更好理解,變數s1還是透過new關鍵字來創建了一個新的String對象,但這裡s2並沒有透過new關鍵字來創建一個新的String對象,而是直接把s1賦值給了s2,也就是把s1的引用賦值給了s2,所以s2所引用的物件其實就是s1所引用的物件。所以透過"=="來比較時,回傳true。既然它們所引用的都是同一個對象,那麼透過equals()方法來比較時,肯定也回傳true,這裡equals()方法其實在對同一個物件進行比較,自己一定等於自己咯。

3、/////////////////////////////////////////////// ////////////////////////////////

String s1 = "Hello";

String s2 = "Hello";

System.out.println(s1 == s2);

System.out.println(s1.equals(s2));

結果?那麼來分析一下。首先這兩個String物件都是作為一個基本類型來使用的,而不是透過new關鍵字來建立的,因此虛擬機器不會為這兩個String物件分配新的記憶體堆,而是到String緩衝池中來尋找。

        先為s1尋找String緩衝池內是否有與"Hello"相同值的String物件存在,此時String緩衝池內是空的,沒有相同值的String物件存在,所以虛擬機會在String緩衝池內建立此String物件,其動作就是new String("Hello");。然後把此String物件的引用賦值給s1。

        接著為s2尋找String緩衝池內是否有與"Hello"相同值的String物件存在,此時虛擬機器找到了一個與其相同值的String對象,這個String物件其實就是為s1所建立的String物件。既然找到了一個相同值的對象,那麼虛擬機器就不在為此創建一個新的String對象,而是直接把存在的String物件的參考賦值給s2。

        這裡既然s1和s2所引用的是同一個String對象,也就是自己等於自己,所以以上兩種比較方法都會回到ture。

        到這裡,對String物件的基本概念應該都已經被理解了。現在我來小結一下:

針對String作為一個基本型別來使用:

1。如果String作為一個基本類型來使用,那麼我們視此String物件是String緩衝池所擁有的。

2。如果String是作為一個基本類型來使用,並且此時String緩衝池內不存在與其指定值相同的String對象,那麼此時虛擬機將為此建立新的String對象,並存放在String緩衝池內。

3。如果String是作為一個基本類型來使用,並且此時String緩衝池內存在與其指定值相同的String對象,那麼此時虛擬機將不會為此建立新的String對象,而直接傳回已存在的String物件的參考。

針對String作為一個物件來使用:

1。如果String作為一個物件來使用,那麼虛擬機將為此創建一個新的String對象,即為此對象分配一塊新的記憶體堆,並且它並不是String緩衝池所擁有的,即它是獨立的。

理解了以上內容後,請看以下程式碼段:

4、/////////////////////////////// /////////////////////////////////////////////

String s1 = "Hello";

String s2 = new String("Hello");

System.out.println(s1 == s2);

System.out.println(s1.equals(s2));;程式碼段的印刷結果是:

false

tru​​e

        依照上面的小結來進行分析。第一行是把String當作一個基本型別來使用的,因此s1所引用的物件是屬於String緩衝池內的。且此時String緩衝池內並沒有與其值相同的String物件存在,因此虛擬機會為此建立一個新的String對象,即new String("Hello");。第二行是把String當作一個物件來使用的,因此s2所引用的物件不屬於String緩衝池內的,即它是獨立的。透過new關鍵字,虛擬機會為此建立一個新的String對象,即為它分配了一塊新的記憶體堆。因此"=="比較後的結果是false,因為s1和s2所引用的並不是同一個對象,它們是獨立存在的。而equals()方法所傳回的是true,因為這兩個物件所封裝的字串內容是完全相同的。

        現在,我相信大家已經完全弄清楚String物件是怎麼一回事了:)但到此並沒有結束,因為String物件還有更深層的應用。

        這裡我將分析String物件的intern()方法的應用:

intern()方法將傳回一個字串物件的規格表示法,即一個同該字串內容相同的字串,但是來自於唯一字串的String緩衝池。這聽起來有點拗口,其實它的機制有如以下程式碼區段:

String s = new String("Hello");

s = s.intern();

以上程式碼段的功能實作可以簡單的看成如下程式碼段:

String s = "Hello";

        你一定又開始懷疑了?那你可以先看第二個程式碼段。第二個程式碼段的意思就是從String緩衝池內取出一個與其值相同的String物件的引用賦值給s。如果String緩衝池內沒有與其相同值的String物件存在,則在其內為此建立一個新的String物件。那麼第一段程式碼的意思又是什麼呢?我們知道透過new關鍵字所建立的對象,虛擬機會為它分配一塊新的記憶體堆。如果平凡地創建相同內容的對象,虛擬機器同樣會為此分配許多新的記憶體堆,雖然它們的內容是完全相同的。拿String物件來說,如果連續建立10個相同內容的String物件(new String("Hello")),那麼虛擬機器就會為此分配10個獨立的記憶體堆。假設所建立的String物件的字串內容十分大,假設一個Stirng物件封裝了1M大小的字串內容,那麼如果我們建立10個此相同String物件的話,我們將會毫無意義的浪費9M的記憶體空間。我們知道String是final類,它所封裝的是字串常數,因此String物件在建立後其內部(字串)值不能改變,也因此String物件可以被共用。所以對於剛才提到的假設,我們所創建的10個相同內容的String對象,其實我們只需為此創建一個String對象,然後被其它String變數所共享。要實現這種機制,唯一的、簡單的方法就是使用String緩衝池,因為String緩衝池內不會存在相同內容的String物件。而intern()方法就是使用這種機制的途徑。在一個已實例化的String物件上呼叫intern()方法後,虛擬機會在String緩衝池內尋找與此Stirng物件所封裝的字串內容相同值的String對象,然後把引用賦值給引用原來的那個String對象的String類型變數。如果String緩衝池內沒有與此String物件所封裝的字串內容相同值的String物件存在,那麼虛擬機會為此建立一個新的String對象,並把其引用賦值給引用原來的那個String物件的String類型變數。這樣就達到了共享同一個String物件的目的,而原先那個透過new關鍵字建立出來的String物件將被拋棄並被垃圾回收器回收。這樣不但降低了記憶體的使用消耗,提高了性能,在String物件的比較上也同樣更方便了,因為相同的String物件將被共享,所以要判斷兩個String物件是否相同,則只需要使用" =="來比較,而無需再使用equals()方法來比較,這樣不但使用起來更方便,而且也提高了性能,因為String對象的equals()方法將會對字符串內容拆解,然後逐個進行比較,如果字串內容十分大的話,那麼這個比較動作則大大降低了效能。

        說到此,大家可能對具體應用還有點模糊,那麼我來舉個簡單的示例,以便闡述以上概念:

        假設有一個類,它有一個記錄消息的方法,這個方法記錄用戶傳來的訊息(假設訊息內容可能較大,且重複率較高),並且把訊息依接收順序記錄在一個清單中。我想有些朋友會這樣設計:

import java.util.*;

public class Messages {

ArrayList messages = new ArrayList();

public void record(String msg) {new ArrayList();

public void record(String msg) {anessages. );

}

public List getMessages() {

return messages;

}

}

        這個設計方案好嗎?假設我們重複的傳送給record()方法同一個訊息(訊息來自不同的用戶,所以可以視每個訊息為一個new String("...")),而且訊息內容較大,那麼這個設計將會大大浪費記憶體空間,因為訊息列表中記錄的都是新建立的、獨立的String對象,雖然它們的內容都相同。那麼怎麼樣可以對其進行最佳化呢,其實很簡單,請看如下優化後的範例:

import java.util.*;

public class Messages {

ArrayList messages = new ArrayList();public

ArrayList messages = new ArrayList();public

ArrayList messages = new ArrayList();public

ArrayList messages = new ArrayList();public

ArrayList messages = new ArrayList();public

ArrayList messages = new ArrayList();public

void record(String msg) {

messages.add(msg.intern());

}

public List getMessages() {

return messages;

} ,原先record()方法中的messages.add(msg);程式碼段變成了messages.add(msg.intern());,僅僅對msg參數呼叫了intern()方法,這樣將對重複的訊息進行共享機制,從而降低了記憶體消耗,提高了效能。


這個例子的確有點牽強,但是這裡只是為了闡述以上概念!

至此,String物件的迷霧都被消除了,大家只要牢記這些概念,以後再複雜的String應用都可以建立在此基礎上來進行分析。



🎜更多String使用equals方法和==分別比較的是什麼相關文章請關注PHP中文網! 🎜🎜🎜🎜
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

<🎜>:泡泡膠模擬器無窮大 - 如何獲取和使用皇家鑰匙
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
北端:融合系統,解釋
3 週前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

熱門話題

Java教學
1664
14
CakePHP 教程
1423
52
Laravel 教程
1318
25
PHP教程
1268
29
C# 教程
1248
24
公司安全軟件導致應用無法運行?如何排查和解決? 公司安全軟件導致應用無法運行?如何排查和解決? Apr 19, 2025 pm 04:51 PM

公司安全軟件導致部分應用無法正常運行的排查與解決方法許多公司為了保障內部網絡安全,會部署安全軟件。 ...

如何將姓名轉換為數字以實現排序並保持群組中的一致性? 如何將姓名轉換為數字以實現排序並保持群組中的一致性? Apr 19, 2025 pm 11:30 PM

將姓名轉換為數字以實現排序的解決方案在許多應用場景中,用戶可能需要在群組中進行排序,尤其是在一個用...

如何使用MapStruct簡化系統對接中的字段映射問題? 如何使用MapStruct簡化系統對接中的字段映射問題? Apr 19, 2025 pm 06:21 PM

系統對接中的字段映射處理在進行系統對接時,常常會遇到一個棘手的問題:如何將A系統的接口字段有效地映�...

IntelliJ IDEA是如何在不輸出日誌的情況下識別Spring Boot項目的端口號的? IntelliJ IDEA是如何在不輸出日誌的情況下識別Spring Boot項目的端口號的? Apr 19, 2025 pm 11:45 PM

在使用IntelliJIDEAUltimate版本啟動Spring...

如何優雅地獲取實體類變量名構建數據庫查詢條件? 如何優雅地獲取實體類變量名構建數據庫查詢條件? Apr 19, 2025 pm 11:42 PM

在使用MyBatis-Plus或其他ORM框架進行數據庫操作時,經常需要根據實體類的屬性名構造查詢條件。如果每次都手動...

Java對像如何安全地轉換為數組? Java對像如何安全地轉換為數組? Apr 19, 2025 pm 11:33 PM

Java對象與數組的轉換:深入探討強制類型轉換的風險與正確方法很多Java初學者會遇到將一個對象轉換成數組的�...

如何利用Redis緩存方案高效實現產品排行榜列表的需求? 如何利用Redis緩存方案高效實現產品排行榜列表的需求? Apr 19, 2025 pm 11:36 PM

Redis緩存方案如何實現產品排行榜列表的需求?在開發過程中,我們常常需要處理排行榜的需求,例如展示一個�...

電商平台SKU和SPU數據庫設計:如何兼顧用戶自定義屬性和無屬性商品? 電商平台SKU和SPU數據庫設計:如何兼顧用戶自定義屬性和無屬性商品? Apr 19, 2025 pm 11:27 PM

電商平台SKU和SPU表設計詳解本文將探討電商平台中SKU和SPU的數據庫設計問題,特別是如何處理用戶自定義銷售屬...

See all articles