首頁 Java java教程 為何Java中String類別是不可變的(詳解)

為何Java中String類別是不可變的(詳解)

Jun 24, 2020 pm 01:27 PM
string 不可變

為何Java中String類別是不可變的(詳解)

為何Java中String類別是不可變的(詳解)

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    /** The value is used for character storage. */
    private final char value[];}
登入後複製

String類別的值是保存在value數組中的,並且是被private final修飾的

1、private修飾,表明外部的類是訪問不到value的,同時子類也訪問不到,當然String類不可能有子類,因為類別被final修飾了
2、final修飾,顯示value的引用是不會被改變的,而value只會在String的建構子中被初始化,而且沒有其他方法可以修改value數組中的值,保證了value的參考和值都不會改變

所以我們說String類別是不可變的。

而很多方法,如substring並不是在原來的String類別上進行操作,而是產生了新的String類別

public String substring(int beginIndex) {
	if (beginIndex < 0) {
		throw new StringIndexOutOfBoundsException(beginIndex);
	}
	int subLen = value.length - beginIndex;
	if (subLen < 0) {
		throw new StringIndexOutOfBoundsException(subLen);
	}
	return (beginIndex == 0) ? this : new String(value, beginIndex, subLen);}
登入後複製

為什麼String被設定為不可變的?

字串常數池

#Java有8種基本資料型別

#整數型態:byte,short,int,long。包裝類型為Byte,Short,Integer,Long
浮點類型:float、double。包裝類型為Float,Double
字元類型:char。包裝類型為Character
布林類型:boolean。包裝類型為Boolean

8種包裝類型中除了Float,Double沒有實作常數池,剩下的都實現了,當然都是透過享元模式實現的

String類別的常數池是在JVM層面實現的。

為什麼要有常數池?

常數池是為了避免頻繁的創建和銷毀物件而影響系統效能,其實現了物件的共享。

例如字串常數池,在編譯階段就把所有的字串文字放到一個常數池中。

  • 節省記憶體空間:常數池中所有相同的字串常數合併,只佔用一個空間。

  • 節省運行時間:比較字串時,== 比equals()快。對於兩個引用變量,只用==判斷引用是否相等,也就可以判斷實際值是否相等。

字串常數池放在哪裡?

jdk1.7之前的不討論,從jdk1.7開始,字串常數池就開始放在堆中,然後本文的所有內容都是基於jdk1.8的

下面這個程式碼還是常被問到的

String str1 = "abc";
String str2 = "abc";
String str3 = new String("abc");
String str4 = new String("abc");
// trueSystem.out.println(str1 == str2);
// falseSystem.out.println(str1 == str3);
// falseSystem.out.println(str3 == str4);
登入後複製

記憶體中的結構如下
為何Java中String類別是不可變的(詳解)
其中常數池中存的是引用

解釋一下上面程式碼的輸出,Java中有2種建立字串物件的方式

String str1 = "abc";
String str2 = "abc";
// trueSystem.out.println(str1 == str2);
登入後複製

以字面上值的方式建立一個字串時,JVM首先會去字串在池中尋找是否存在"abc"這個物件

如果不存在,則在字串池中建立"abc"這個對象,然後將池中"abc"這個物件的位址賦給str1,這樣str1會指向池中"abc"這個字串物件

如果存在,則不建立任何對象,直接將池中"abc"這個物件的位址傳回,賦給str2。因為str1、str2指向同一個字串池中的"abc"對象,所以結果為true。

String str3 = new String("abc");
String str4 = new String("abc");
// falseSystem.out.println(str3 == str4);
登入後複製

採用new關鍵字新建一個字串物件時,JVM首先在字串池中尋找有沒有"abc"這個字串對象,

如果沒有,則先在字串池中建立一個"abc"字串對象,然後再在堆中建立一個"abc"字串對象,然後將堆中這個"abc"字串物件的地址賦給str3​​

如果有,則不在池中再去創建"abc"這個對象了,直接在堆中創建一個"abc"字符串對象,然後將堆中的這個"abc"對象的地址賦給str4。這樣,str4就指向了堆中所建立的這個"abc"字串物件;

因為str3和str4指向的是不同的字串對象,結果為false。

快取HashCode

String類別在被建立的時候,hashcode就被快取到hash成員變數中,因為String類別是不可變的,所以hashcode是不會改變的。這樣每次想使用hashcode的時候直接取就行了,而不用重新計算,提高了效率

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {

    /** Cache the hash code for the string */
    private int hash; // Default to 0
	}
登入後複製

可以用作HashMap的key

## ##由於String類別不可變的特性,所以常被用作HashMap的key,如果String類別是可變的,內容改變,hashCode也會改變,當根據這個key從HashMap中取的時候有可能取不到value,或取到錯的value############線程安全性############不可變物件天生就是執行緒安全的,這樣可以避免在多執行緒環境下對String做同步操作。 ###

感謝大家的閱讀,希望大家收益多多。

本文轉自:https://blog.csdn.net/zzti_erlie/article/details/106872673

推薦教學:《java教學

以上是為何Java中String類別是不可變的(詳解)的詳細內容。更多資訊請關注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 尊渡假赌尊渡假赌尊渡假赌
Mandragora:巫婆樹的耳語 - 如何解鎖抓鉤
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教學
1665
14
CakePHP 教程
1424
52
Laravel 教程
1322
25
PHP教程
1270
29
C# 教程
1250
24
使用java的String.valueOf()函數將基本資料型別轉換為字串 使用java的String.valueOf()函數將基本資料型別轉換為字串 Jul 24, 2023 pm 07:55 PM

使用Java的String.valueOf()函數將基本資料型別轉換為字串在Java開發中,當我們需要將基本資料型別轉換為字串時,常見的方法是使用String類別的valueOf()函數。這個函數可以接受基本資料類型的參數,並傳回對應的字串表示。在本文中,我們將探討如何使用String.valueOf()函數進行基本資料型別轉換,並提供一些程式碼範例來

怎麼把char數組轉string 怎麼把char數組轉string Jun 09, 2023 am 10:04 AM

char陣列轉string的方法:可以透過賦值來實現,使用{char a[]=" abc d\0efg ";string s=a;}語法,讓char陣列對string直接賦值,執行程式碼即可完成轉換。

使用java的String.replace()函數替換字串中的字元(字串) 使用java的String.replace()函數替換字串中的字元(字串) Jul 25, 2023 pm 05:16 PM

使用Java的String.replace()函數替換字串中的字元(字串)在Java中,字串是不可變的對象,這意味著一旦創建了一個字串對象,就無法修改它的值。但是,你可能會遇到需要替換字串中的某些字元或字串的情況。這時候,我們可以使用Java的String類別中的replace()方法來實作字串的替換。 String類別的replace()方法有兩種重

使用java的String.length()函數取得字串的長度 使用java的String.length()函數取得字串的長度 Jul 25, 2023 am 09:09 AM

使用Java的String.length()函數取得字串的長度在Java程式設計中,字串是一種非常常見的資料類型,我們經常需要取得字串的長度,即字串中字元的個數。在Java中,我們可以使用String類別的length()函數來取得字串的長度。下面是一個簡單的範例程式碼:publicclassStringLengthExample{publ

2w字 詳解 String,yyds 2w字 詳解 String,yyds Aug 24, 2023 pm 03:56 PM

大家好,今天跟大家分享java基礎之String。 String類別的重要性就不必說了,可以說是我們後端開發用的最多的類,所以,很有必要好好聊聊它。

java的String類別如何使用 java的String類別如何使用 Apr 19, 2023 pm 01:19 PM

一、認識String1.JDK中的String首先我們看看JDK中的String類別源碼,它實作了很多接口,可以看到String類別被final修飾了,這就說明String類別不可以被繼承,String不存在子類,這樣所有使用JDK的人,用到的String類別都是同一個,如果String允許被繼承,每個人都可以對String進行擴展,每個人使用的String不是同一個版本,兩個不同的人使用相同的方法,表現出不同的結果,這就導致程式碼沒辦法進行開發了繼承和方法覆寫在帶來彈性的同時,也會帶來很多子類別行為不

使用java的String.toLowerCase()函數將字串轉換為小寫 使用java的String.toLowerCase()函數將字串轉換為小寫 Jul 24, 2023 pm 11:52 PM

String.toLowerCase()函數是Java中一個非常有用且常見的字串處理函數,它可以將一個字串轉換為小寫形式。在本文中,我們將介紹該函數的使用方法,並給出一些相關的程式碼範例。首先,讓我們來看看String.toLowerCase()函數的基本語法。它沒有任何參數,只需要呼叫它。下面是範例程式碼:Stringstr="Hel

Golang函數的byte、rune和string型轉換技巧 Golang函數的byte、rune和string型轉換技巧 May 17, 2023 am 08:21 AM

在Golang程式設計中,byte、rune和string類型是非常基礎、常見的資料型別。它們在處理字串、檔案流等資料操作時發揮著重要作用。而在進行這些資料操作時,我們通常需要對它們進行相互的轉換,這就需要掌握一些轉換技巧。本文將介紹Golang函數的byte、rune和string類型轉換技巧,旨在幫助讀者更好地理解這些資料類型,並能夠熟練地在程式設計實踐中應用

See all articles