91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

java.lang.String類不可變性的示例分析

發布時間:2021-06-28 10:46:41 來源:億速云 閱讀:128 作者:小新 欄目:開發技術

這篇文章主要為大家展示了“java.lang.String類不可變性的示例分析”,內容簡而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領大家一起研究并學習一下“java.lang.String類不可變性的示例分析”這篇文章吧。

1. 字符串 String 的不可變性

什么是不可變類?

這樣理解:
        一個對象在創建完成后,不能去改變它的狀態,不能改變它的成員變量(如果成員變量包含基本數據類型,那么這個基本數據類型的值不能改變;如果包含引用類型,那么這個引用類型的變量不能指向別的對象)

不可變類只是其實例不能被修改的類。每個實例中包含的所有信息都必須在創建該實例的時候就提供,并且在對象的整個生命周期內固定不變。為了使類不可變,要遵循下面五條規則:

  • 不要提供任何會修改對象狀態的方法

  • 保證類不會被擴展。 一般的做法是讓這個類稱為 final 的,防止子類化,破壞該類的不可變行為

  • 使所有的域都是 final 的

  • 使所有的域都成為私有的。 防止客戶端獲得訪問被域引用的可變對象的權限,并防止客戶端直接修改這些對象

  • 確保對于任何可變性組件的互斥訪問。 如果類具有指向可變對象的域,則必須確保該類的客戶端無法獲得指向這些對象的引用

翻閱 API 文檔:

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    // value 數組被 final 修飾
    private final char value[];
    ...
}

String 類代表字符串。Java 程序中的所有字符串字面值(如 “abc” )都作為此類的實例來實現。 這些字面值都是直接存儲在“方法區”的 字符串常量池

字符串是常量;它們的值在創建之后 不能改變,所以可以共享它們。例如:

String str = "abc";

這時就有人疑惑了:為什么 String 不可變?但我的代碼中經常改變 String 啊,如下:

String str = "HELLO";
str = "WORLD";
System.out.println(str);    // WORLD

這樣操作,不就是將 “HELLO” 對象改變成了 “WORLD” 對象了嗎?

雖然字符串的內容看上去從“HELLO” 變成了“WORLD”,但實際上,這已經是生成了一個新的字符串了:

String str = "HELLO";
System.out.println(str.hashCode());  // 68624562
str = "WORLD";
System.out.println(str.hashCode());  // 82781042

變量 str 前后的 hashCode 值不一樣,說明了 str 在改變前后,指向了不同的對象。所以,變量 str 只是指向了不同對象,字符串 “HELLO”對象本身沒有被改變。

變量 str 的指向如下圖所示(jdk1.8:字符串常量位于堆中):

java.lang.String類不可變性的示例分析

我們也可以使用 javap 命令來查看 class 的常量池:

javap -c -v StringTest.class

執行后,常量池信息如下:

java.lang.String類不可變性的示例分析

從常量池中可以看出,確實有兩個字符串對象:HELLO、WORLD

【總結】:一旦一個 String 對象堆中被創建出來,它就無法被修改。而且,String 類的所有 API 方法都沒有改變字符串本身的值,都是返回了一個新的字符串對象。

2. String 設計成不可變類的好處

在了解了“String 是不可變”的之后,大家是不是很疑惑:為什么要把 String 設計成不可變的呢?這樣做又有什么好處呢?

主要從以下幾個角度考慮:

  • 安全可靠性:字符串在 Java 應用程序中應用廣泛(存儲敏感信息,如:用戶名、密碼、連接 url、網絡連接等);JVM類加載器在加載類的時也廣泛地使用它。因此,保護 String 類對于提升整個應用程序的安全性至關重要。

  • 緩存:字符串是使用最廣泛的數據結構,大量的字符串的創建是非常耗費資源的。JVM 中專門開辟了一部分空間來存儲 Java 字符串,那就是字符串常量池。通過字符串常量池,兩個內容相同的字符串變量,可以從池中指向同一個字符串對象,從而節省了關鍵的內存資源

  • 線程安全:不可變會自動使字符串成為線程安全的,因為當從多個線程訪問它們時,它們不會被更改

  • hashcode 緩存:字符串也被廣泛地用于哈希實現,如 HashMap、HashTable、HashSet 等。在對這些散列實現進行操作時,經常調用鍵的hashCode() 方法。不可變性保證了字符串的值不會改變,因此,hashCode() 方法在 String 類中被重寫,以方便緩存。這樣,在第一次hashCode() 調用期間計算和緩存散列,并從那時起返回相同的值。

3. 面試題

// 生成兩個對象:一個在常量池中;一個中堆中,且都是 hello 對象
String s = new String("hello");

那么,下面會生成幾個對象呢?

// 只會在字符串常量池中生成一個對象:helloworld。
String s3 = "hello" + "world";

這種字面量用“+”拼接,編譯器在編譯期間會直接進行優化。

// 這個會生成4個對象。2個在常量池中:hello、world
// 2個在堆中:StringBuilder、helloworld對象
String s = "hello";
String s2 = s + "world";

編譯后,使用反編譯軟件 ------ jad 進行查看:

String s1 = "hell0";
String s2 = (new StringBuilder()).append(s1).append("world").toString();

發現:使用“+”將變量和字面量進行拼接的結果是:將 String 轉成了StringBuilder 后,使用其 append() 方法進行處理的

查看 StringBuilder.toString() 方法源碼:

@Override
public String toString() {
	// char[] value; value 是 StringBuilder 類的成員變量
    return new String(value, 0, count);
}

最后調用 toString() 方法時,會創建一個 String 對象。這個字符串對象只會在堆中創建,并不會在字符串常量池中創建。所以,會創建4個對象(hello 和 world 會直接在字符串常量池中創建)。

以上是“java.lang.String類不可變性的示例分析”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

东宁县| 太仆寺旗| 天水市| 长岛县| 泗水县| 夹江县| 谢通门县| 精河县| 车致| 贡觉县| 两当县| 图木舒克市| 台北市| 阿拉善右旗| 焦作市| 长垣县| 枣阳市| 泰州市| 屯留县| 麻江县| 南丹县| 乌兰浩特市| 沈阳市| 莫力| 清远市| 巴林左旗| 油尖旺区| 安顺市| 南涧| 牡丹江市| 马山县| 辛集市| 五台县| 昭觉县| 类乌齐县| 广灵县| 安多县| 陕西省| 华坪县| 云浮市| 施秉县|