欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java 基礎(chǔ)面試真題:String 為什么是不可變的?

 更新時(shí)間:2025年01月27日 09:22:12   作者:思wu邪  
本文主要介紹了String、StringBuffer和StringBuilder的區(qū)別,以及String不可變的原因,String不可變的原因是其內(nèi)部使用final修飾的char數(shù)組保存字符串,同時(shí)String類沒(méi)有提供修改字符串的方法,在Java9之后,String的底層實(shí)現(xiàn)由char[]改成了byte[],這是為了節(jié)省內(nèi)存空間

今天來(lái)分享一道群友去阿里云面試遇到的 Java 基礎(chǔ)面試真題:“StringStringBuffer、StringBuilder 的區(qū)別?String 為什么是不可變的?”。

網(wǎng)站很多文章都把 String 不可變的原因講錯(cuò)了,建議你重點(diǎn)關(guān)注一下。另外,本文還提到了 :“Java 9 為何要將 String 的底層實(shí)現(xiàn)由 char[] 改成了 byte[] ?”

下面是正文。

可變性

簡(jiǎn)單的來(lái)說(shuō):String 類中使用 final 關(guān)鍵字修飾字符數(shù)組來(lái)保存字符串,所以String 對(duì)象是不可變的。×

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

?? 修正 :我們知道被 final 關(guān)鍵字修飾的類不能被繼承,修飾的方法不能被重寫(xiě),修飾的變量是基本數(shù)據(jù)類型則值不能改變,修飾的變量是引用類型則不能再指向其他對(duì)象。因此,final 關(guān)鍵字修飾的數(shù)組保存字符串并不是 String 不可變的根本原因,因?yàn)檫@個(gè)數(shù)組保存的字符串是可變的(final 修飾引用類型變量的情況)。

String 真正不可變有下面幾點(diǎn)原因:

保存字符串的數(shù)組被 final 修飾且為私有的,并且String 類沒(méi)有提供/暴露修改這個(gè)字符串的方法。

String 類被 final 修飾導(dǎo)致其不能被繼承,進(jìn)而避免了子類破壞 String 不可變。

相關(guān)閱讀:如何理解 String 類型值的不可變?- 知乎提問(wèn)[1]

補(bǔ)充(來(lái)自issue 675[2]):在 Java 9 之后,StringStringBuilderStringBuffer 的實(shí)現(xiàn)改用 byte 數(shù)組存儲(chǔ)字符串。

Java 9 為何要將 String 的底層實(shí)現(xiàn)由 char[] 改成了 byte[] ?

新版的 String 其實(shí)支持兩個(gè)編碼方案:Latin-1 和 UTF-16。如果字符串中包含的漢字沒(méi)有超過(guò) Latin-1 可表示范圍內(nèi)的字符,那就會(huì)使用 Latin-1 作為編碼方案。Latin-1 編碼方案下,byte 占一個(gè)字節(jié)(8 位),char 占用 2 個(gè)字節(jié)(16),byte 相較 char 節(jié)省一半的內(nèi)存空間。

如果字符串中包含的漢字超過(guò) Latin-1 可表示范圍內(nèi)的字符,bytechar 所占用的空間是一樣的。

這是官方的介紹:https://openjdk.java.net/jeps/254 。

StringBuilderStringBuffer 都繼承自 AbstractStringBuilder 類,在 AbstractStringBuilder 中也是使用字符數(shù)組保存字符串,不過(guò)沒(méi)有使用 finalprivate 關(guān)鍵字修飾,最關(guān)鍵的是這個(gè) AbstractStringBuilder 類還提供了很多修改字符串的方法比如 append 方法。

abstract class AbstractStringBuilder implements Appendable, CharSequence {
    char[] value;
    public AbstractStringBuilder append(String str) {
        if (str == null)
            return appendNull();
        int len = str.length();
        ensureCapacityInternal(count + len);
        str.getChars(0, len, value, count);
        count += len;
        return this;
    }
   //...
}

線程安全性

String 中的對(duì)象是不可變的,也就可以理解為常量,線程安全。AbstractStringBuilderStringBuilderStringBuffer 的公共父類,定義了一些字符串的基本操作,如 expandCapacity、append、insert、indexOf 等公共方法。StringBuffer 對(duì)方法加了同步鎖或者對(duì)調(diào)用的方法加了同步鎖,所以是線程安全的。StringBuilder 并沒(méi)有對(duì)方法進(jìn)行加同步鎖,所以是非線程安全的。

性能

每次對(duì) String 類型進(jìn)行改變的時(shí)候,都會(huì)生成一個(gè)新的 String 對(duì)象,然后將指針指向新的 String 對(duì)象。StringBuffer 每次都會(huì)對(duì) StringBuffer 對(duì)象本身進(jìn)行操作,而不是生成新的對(duì)象并改變對(duì)象引用。相同情況下使用 StringBuilder 相比使用 StringBuffer 僅能獲得 10%~15% 左右的性能提升,但卻要冒多線程不安全的風(fēng)險(xiǎn)。

對(duì)于三者使用的總結(jié):

  • 操作少量的數(shù)據(jù): 適用 String
  • 單線程操作字符串緩沖區(qū)下操作大量數(shù)據(jù): 適用 StringBuilder
  • 多線程操作字符串緩沖區(qū)下操作大量數(shù)據(jù): 適用 StringBuffer

到此這篇關(guān)于Java 基礎(chǔ)面試真題:String 為什么是不可變的?的文章就介紹到這了,更多相關(guān)String 為什么是不可變的?內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 3行代碼快速實(shí)現(xiàn)Spring Boot Oauth2服務(wù)功能

    3行代碼快速實(shí)現(xiàn)Spring Boot Oauth2服務(wù)功能

    oauthserver是一個(gè)基于Spring Boot Oauth2的完整的獨(dú)立的Oauth服務(wù)器。僅僅需要?jiǎng)?chuàng)建相關(guān)數(shù)據(jù)表,修改數(shù)據(jù)庫(kù)的連接信息,你就可以得到一個(gè)Oauth服務(wù)器。這篇文章給大家介紹3行代碼快速實(shí)現(xiàn)Spring Boot Oauth2服務(wù)功能,需要的朋友參考下吧
    2018-04-04
  • JAVA初級(jí)項(xiàng)目——實(shí)現(xiàn)圖書(shū)管理系統(tǒng)

    JAVA初級(jí)項(xiàng)目——實(shí)現(xiàn)圖書(shū)管理系統(tǒng)

    這篇文章主要介紹了JAVA如何實(shí)現(xiàn)圖書(shū)管理系統(tǒng),文中示例代碼非常詳細(xì),供大家參考和學(xué)習(xí),感興趣的朋友可以了解下
    2020-06-06
  • 詳解JAVA高質(zhì)量代碼之?dāng)?shù)組與集合

    詳解JAVA高質(zhì)量代碼之?dāng)?shù)組與集合

      在學(xué)習(xí)編程的過(guò)程中,我覺(jué)得不止要獲得課本的知識(shí),更多的是通過(guò)學(xué)習(xí)技術(shù)知識(shí)提高解決問(wèn)題的能力,這樣我們才能走在最前方,本文主要講述Java高質(zhì)量代碼之?dāng)?shù)組與集合
    2013-08-08
  • Map之computeIfAbsent使用解讀

    Map之computeIfAbsent使用解讀

    `computeIfAbsent`是Java 8引入的一個(gè)Map接口方法,用于簡(jiǎn)化在Map中獲取值的操作,如果指定的鍵不存在,它會(huì)調(diào)用提供的函數(shù)生成一個(gè)新的值,并將其與鍵關(guān)聯(lián),這種方法減少了手動(dòng)檢查和插入的樣板代碼,使代碼更加簡(jiǎn)潔和易讀
    2025-02-02
  • 使用SpringBoot根據(jù)配置注入接口的不同實(shí)現(xiàn)類(代碼演示)

    使用SpringBoot根據(jù)配置注入接口的不同實(shí)現(xiàn)類(代碼演示)

    使用springboot開(kāi)發(fā)時(shí)經(jīng)常用到@Autowired和@Resource進(jìn)行依賴注入,但是當(dāng)我們一個(gè)接口對(duì)應(yīng)多個(gè)不同的實(shí)現(xiàn)類的時(shí)候如果不進(jìn)行一下配置項(xiàng)目啟動(dòng)時(shí)就會(huì)報(bào)錯(cuò),那么怎么根據(jù)不同的需求注入不同的類型呢,感興趣的朋友一起看看吧
    2022-06-06
  • Java虛擬機(jī)GC日志分析

    Java虛擬機(jī)GC日志分析

    這篇文章主要介紹了Java虛擬機(jī)GC日志分析,分享了相關(guān)代碼示例,小編覺(jué)得還是挺不錯(cuò)的,具有一定借鑒價(jià)值,需要的朋友可以參考下
    2018-02-02
  • 圖解Java經(jīng)典算法冒泡排序的原理與實(shí)現(xiàn)

    圖解Java經(jīng)典算法冒泡排序的原理與實(shí)現(xiàn)

    冒泡排序是一種簡(jiǎn)單的排序算法,它也是一種穩(wěn)定排序算法。其實(shí)現(xiàn)原理是重復(fù)掃描待排序序列,并比較每一對(duì)相鄰的元素,當(dāng)該對(duì)元素順序不正確時(shí)進(jìn)行交換。一直重復(fù)這個(gè)過(guò)程,直到?jīng)]有任何兩個(gè)相鄰元素可以交換,就表明完成了排序
    2022-09-09
  • Java實(shí)現(xiàn)簡(jiǎn)單的掃雷小程序

    Java實(shí)現(xiàn)簡(jiǎn)單的掃雷小程序

    這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)簡(jiǎn)單的掃雷小程序,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-04-04
  • 利用Socket.io 實(shí)現(xiàn)消息實(shí)時(shí)推送功能

    利用Socket.io 實(shí)現(xiàn)消息實(shí)時(shí)推送功能

    這篇文章主要介紹了利用Socket.io 實(shí)現(xiàn)消息實(shí)時(shí)推送功能,需要的朋友可以參考下
    2017-12-12
  • java如何遠(yuǎn)程加載class文件

    java如何遠(yuǎn)程加載class文件

    這篇文章主要介紹了java如何遠(yuǎn)程加載class文件問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-01-01

最新評(píng)論