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

溫馨提示×

溫馨提示×

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

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

為什么Java中String是不可變的

發布時間:2021-12-02 18:41:48 來源:億速云 閱讀:138 作者:柒染 欄目:大數據

為什么Java中String是不可變的,針對這個問題,這篇文章詳細介紹了相對應的分析和解答,希望可以幫助更多想解決這個問題的小伙伴找到更簡單易行的方法。

前言

String 是 Java 語言非常基礎和重要的類,提供了構造和管理字符串的各種基本邏輯。它是典型的 Immutable 類,被聲明成為 final class,所有屬性也都是 final 的(hashCode方法除外)。也由于它的不可變性,類似拼接、裁剪字符串等動作,都會產生新的 String 對象。

一·什么是不可變對象

不可變對象是指一旦創建完成就不能再被修改的對象。也就說一旦一個對象被賦值了,這個對象的引用或者內部狀態都不能被修改,對象所暴露的public方法不允許你修改

二·為什么使用不可變對象

使用不可變對象有四個優點:緩存,安全,同步,性能。使用不可變對象可以省去很多不必要的麻煩,而且很對場景下只能使用不可變對象(例如緩存結果)。對于可變對象傳參或者賦值的時候,必須要copy這個可變參數的值,因為我們不知道這個可變對象的值何時會被修改。但如果使用的是final類型,就只需要copy這個變量的引用。因為Java確保了final類型的值不會被修改。

三·String的不可變

1.String的底層數據結構

String使用一個聲明為final的字符數組value來存儲值,value一旦賦值后所指向的地址就不能再被修改。雖然數組的值可以修改,但是String類本身并沒有提供能夠修改value數組值的方法。

    /** The value is used for character storage. */
   private final char value[];

補充一下:當使用final修飾基本類型變量時,不能對基本類型變量重新賦值,因此基本類型變量不能被改變;但對于引用類型的變量,JDK保證的是變量指向的地址不會被改變(即指向的始終是同一個對象),至于地址的值(對象的值)是可以改變的。

2.字符串常量池

在前文中指出使用String這種不可變對象便于緩存,而jdk就為String提供了字符串常量池。字符串是最常使用的數據結構,緩存String并重復使用可以極大的節省Heap空間,因為相同的String變量指向了常量池中相同地址的值。例如以下代碼只在字符串常量池中創建一個String對象

String string1 = "abcd";
String string2 = "abcd";
System.out.println(string1 == string2);
//代碼輸出結果為true

為什么Java中String是不可變的

如圖所示,如果String是可變的,那修改string1變量所指向的地址的內容,就會導致string2的內容也被修改了

3.安全

String在Java應用中被大量用于存儲敏感信息(用戶名,密碼,URL等),也被JVM Class Loader用于加載類信息,因此十分有必要保證String的安全

void criticalMethod(String userName) {
   // 1.安全檢查
   if (!isAlphaNumeric(userName)) {
       throw new SecurityException();
   }
   
  // 2.更新DB
   connection.executeUpdate("UPDATE Customers SET Status = 'Active' " +
     " WHERE UserName = '" + userName + "'");
}

如上代碼片段,方法傳入一個userName的變量,第一步先檢查改變量是否都是字母數字,然后執行sql 假設String是可變的,且方法已經執行過代碼1還未執行代碼2的時候,這時候上游調用方還持有參數userName的引用,如果調用方此時修改了userName的值,那就相當于混過了代碼1出的安全檢查。那么SQL注入的風險就會增加了

4.同步

“不可變”保證在并發編程模型中,不同Thread不能修改String的值,如果某個Thread修改了一個String值,這個值就會被緩存到StringPool中,也就是說對于String的引用是安全的。

5.Hashcode緩存

JDK提供了很多hash操作的數據結構:HashMap,HashTable,HashSet等,當在這些類上操作的時候,hashCode()方法就會被頻繁的調用。“不可變”保證了String對象的值不會被修改,所以hash值也就不會被修改。對于不變的值就可以緩存起來以便之后調用hasCode()方法的時候就可以直接取出緩存中的值 JDK源碼中String代碼片段如下:

 /** Cache the hash code for the string */
private int hash; // Default to 0


   /**
    * Returns a hash code for this string. The hash code for a
    * {@code String} object is computed as
    * <blockquote><pre>
    * s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
    * </pre></blockquote>
    * using {@code int} arithmetic, where {@code s[i]} is the
    * <i>i</i>th character of the string, {@code n} is the length of
    * the string, and {@code ^} indicates exponentiation.
    * (The hash value of the empty string is zero.)
    *
    * @return  a hash code value for this object.
    */
   public int hashCode() {
       int h = hash;
       if (h == 0 && value.length > 0) {
           char val[] = value;

           for (int i = 0; i < value.length; i++) {
               h = 31 * h + val[i];
           }
           hash = h;
       }
       return h;
   }

可以看到String對象有一個屬性hash用于緩存hasCode()第一次計算的結果,之后調用hashCode()方法就直接從緩存中取出來

關于為什么Java中String是不可變的問題的解答就分享到這里了,希望以上內容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關注億速云行業資訊頻道了解更多相關知識。

向AI問一下細節

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

AI

肇庆市| 裕民县| 巩留县| 山西省| 扬州市| 岐山县| 称多县| 金湖县| 北票市| 安阳市| 井冈山市| 拉萨市| 双柏县| 都匀市| 茶陵县| 宁德市| 彰化县| 东方市| 民权县| 平陆县| 龙陵县| 鹿泉市| 宾川县| 彩票| 枣庄市| 喀喇| 密山市| 青岛市| 兴宁市| 宝兴县| 封开县| 泸定县| 稻城县| 临湘市| 雷山县| 宁德市| 兖州市| 栾川县| 顺昌县| 临夏市| 沙湾县|