真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

為什么Java中String是不可變的

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

創(chuàng)新互聯(lián)公司主營(yíng)崇左網(wǎng)站建設(shè)的網(wǎng)絡(luò)公司,主營(yíng)網(wǎng)站建設(shè)方案,成都APP應(yīng)用開發(fā),崇左h5小程序定制開發(fā)搭建,崇左網(wǎng)站營(yíng)銷推廣歡迎崇左等地區(qū)企業(yè)咨詢

前言

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

一·什么是不可變對(duì)象

不可變對(duì)象是指一旦創(chuàng)建完成就不能再被修改的對(duì)象。也就說一旦一個(gè)對(duì)象被賦值了,這個(gè)對(duì)象的引用或者內(nèi)部狀態(tài)都不能被修改,對(duì)象所暴露的public方法不允許你修改

二·為什么使用不可變對(duì)象

使用不可變對(duì)象有四個(gè)優(yōu)點(diǎn):緩存,安全,同步,性能。使用不可變對(duì)象可以省去很多不必要的麻煩,而且很對(duì)場(chǎng)景下只能使用不可變對(duì)象(例如緩存結(jié)果)。對(duì)于可變對(duì)象傳參或者賦值的時(shí)候,必須要copy這個(gè)可變參數(shù)的值,因?yàn)槲覀儾恢肋@個(gè)可變對(duì)象的值何時(shí)會(huì)被修改。但如果使用的是final類型,就只需要copy這個(gè)變量的引用。因?yàn)镴ava確保了final類型的值不會(huì)被修改。

三·String的不可變

1.String的底層數(shù)據(jù)結(jié)構(gòu)

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

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

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

2.字符串常量池

在前文中指出使用String這種不可變對(duì)象便于緩存,而jdk就為String提供了字符串常量池。字符串是最常使用的數(shù)據(jù)結(jié)構(gòu),緩存String并重復(fù)使用可以極大的節(jié)省Heap空間,因?yàn)橄嗤腟tring變量指向了常量池中相同地址的值。例如以下代碼只在字符串常量池中創(chuàng)建一個(gè)String對(duì)象

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

為什么Java中String是不可變的

如圖所示,如果String是可變的,那修改string1變量所指向的地址的內(nèi)容,就會(huì)導(dǎo)致string2的內(nèi)容也被修改了

3.安全

String在Java應(yīng)用中被大量用于存儲(chǔ)敏感信息(用戶名,密碼,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 + "'");
}

如上代碼片段,方法傳入一個(gè)userName的變量,第一步先檢查改變量是否都是字母數(shù)字,然后執(zhí)行sql 假設(shè)String是可變的,且方法已經(jīng)執(zhí)行過代碼1還未執(zhí)行代碼2的時(shí)候,這時(shí)候上游調(diào)用方還持有參數(shù)userName的引用,如果調(diào)用方此時(shí)修改了userName的值,那就相當(dāng)于混過了代碼1出的安全檢查。那么SQL注入的風(fēng)險(xiǎn)就會(huì)增加了

4.同步

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

5.Hashcode緩存

JDK提供了很多hash操作的數(shù)據(jù)結(jié)構(gòu):HashMap,HashTable,HashSet等,當(dāng)在這些類上操作的時(shí)候,hashCode()方法就會(huì)被頻繁的調(diào)用?!安豢勺儭北WC了String對(duì)象的值不會(huì)被修改,所以hash值也就不會(huì)被修改。對(duì)于不變的值就可以緩存起來以便之后調(diào)用hasCode()方法的時(shí)候就可以直接取出緩存中的值 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
    *

    * s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
    *

    * using {@code int} arithmetic, where {@code s[i]} is the
    * ith 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對(duì)象有一個(gè)屬性hash用于緩存hasCode()第一次計(jì)算的結(jié)果,之后調(diào)用hashCode()方法就直接從緩存中取出來

關(guān)于為什么Java中String是不可變的問題的解答就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道了解更多相關(guān)知識(shí)。


新聞標(biāo)題:為什么Java中String是不可變的
標(biāo)題來源:http://weahome.cn/article/jgcijs.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部