Java中String和StringBuffer及StringBuilder?有什么區(qū)別
前言:
String 是 Java 語(yǔ)言非?;A(chǔ)和重要的類(lèi),提供了構(gòu)造和管理字符串的各種基本邏輯。它是典型的 Immutable 類(lèi),被聲明成為 final class,所有屬性也都是 final 的。也由于它的不可變性,類(lèi)似拼接、裁剪字符串等動(dòng)作,都會(huì)產(chǎn)生新的 String 對(duì)象。由于字符串操作的普遍性,所以相關(guān)操作的效率往往對(duì)應(yīng)用性能有明顯影響。 StringBuffer 是為解決上面提到拼接產(chǎn)生太多中間對(duì)象的問(wèn)題而提供的一個(gè)類(lèi),我們可以用 append 或者 add 方法,把字符串添加到已有序列的末尾或者指定位置。StringBuffer 本質(zhì)是一個(gè)線(xiàn)程安全的可修改字符序列,它保證了線(xiàn)程安全,也隨之帶來(lái)了額外的性能開(kāi)銷(xiāo),所以除非有線(xiàn)程安全的需要,不然還是推薦使用它的后繼者,也就是 StringBuilder。 StringBuilder 是 Java 1.5 中新增的,在能力上和 StringBuffer 沒(méi)有本質(zhì)區(qū)別,但是它去掉了線(xiàn)程安全的部分,有效減小了開(kāi)銷(xiāo),是絕大部分情況下進(jìn)行字符串拼接的首選。
String類(lèi)為什么是immutable(不可變的)
不可變類(lèi)指的是對(duì)象一旦創(chuàng)建成功,就無(wú)法改變對(duì)象的值。JDK中很多類(lèi)設(shè)計(jì)為不可變的Integer,Long和String等。相對(duì)應(yīng)的改法中大多是可變類(lèi),創(chuàng)建成功后可以動(dòng)態(tài)修改成員變量的屬性值;
如何保證不可變
- 類(lèi)添加final修飾符,保證類(lèi)是不可以被繼承的;類(lèi)繼承會(huì)破壞類(lèi)的不可變機(jī)制,只要覆蓋父類(lèi)的成員方法,并且在里面修改成員變量的值,那么所有子類(lèi)以父類(lèi)的形式出現(xiàn)的地方,類(lèi)的屬性都會(huì)被修改掉
- 類(lèi)成員屬性設(shè)置為private,final的;這樣可以保證成員屬性是不可變的,但是僅僅這樣還不夠,因?yàn)槿绻蓡T變量是引用對(duì)象的話(huà),可以改變引用對(duì)象的成員變量;通過(guò)第四點(diǎn)可以避免這一點(diǎn);
- 不提供修改成員變量的方法,比如setter;
- 通過(guò)構(gòu)造器構(gòu)造對(duì)象,并進(jìn)行深拷貝;如果是直接通過(guò)引用傳入的對(duì)象直接賦值給成員,還是可以通過(guò)修改外部引用變量導(dǎo)致改變內(nèi)部變量的值;
String的源碼如下:
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
/** The value is used for character storage. */
private final char value[];
/** Cache the hash code for the string */
private int hash; // Default to 0
/** use serialVersionUID from JDK 1.0.2 for interoperability */
private static final long serialVersionUID = -6849794470754667710L;
/**
* Class String is special cased within the Serialization Stream Protocol.
*
* A String instance is written into an ObjectOutputStream according to
* <a href="{@docRoot}/../platform/serialization/spec/output.html" rel="external nofollow" >
* Object Serialization Specification, Section 6.2, "Stream Elements"</a>
*/
private static final ObjectStreamField[] serialPersistentFields =
new ObjectStreamField[0];
/**
* Initializes a newly created {@code String} object so that it represents
* an empty character sequence. Note that use of this constructor is
* unnecessary since Strings are immutable.
*/
public String() {
this.value = "".value;
}
/**
* Initializes a newly created {@code String} object so that it represents
* the same sequence of characters as the argument; in other words, the
* newly created string is a copy of the argument string. Unless an
* explicit copy of {@code original} is needed, use of this constructor is
* unnecessary since Strings are immutable.
*
* @param original
* A {@code String}
*/
public String(String original) {
this.value = original.value;
this.hash = original.hash;
}
/**
* Allocates a new {@code String} so that it represents the sequence of
* characters currently contained in the character array argument. The
* contents of the character array are copied; subsequent modification of
* the character array does not affect the newly created string.
*
* @param value
* The initial value of the string
*/
public String(char value[]) {
this.value = Arrays.copyOf(value, value.length);
}通過(guò)源碼可以看出來(lái)String是如何保證不可變的:
- String類(lèi)是finaly的,不允許繼承
- 成員變量value是private,final的
- value沒(méi)有setter方法
- 構(gòu)造方法,是通過(guò)克隆的方式來(lái)構(gòu)造的
- 返回value時(shí),通過(guò)克隆的方式返回
string類(lèi)為不可變對(duì)象的好處
字符串常量池的需要:
String aaa= "someString"; String bbb = "someString"; 這兩個(gè)對(duì)象指向同一個(gè)內(nèi)存,字符串常量池的好處是,在大量使用字符串的時(shí)候,可以節(jié)省內(nèi)存,提供效率;如果String是可變對(duì)象,那么修改了一個(gè),其他引用的地方全部發(fā)生變化了。
線(xiàn)程安全的考慮:
在并發(fā)場(chǎng)景下,多個(gè)線(xiàn)程同時(shí)讀一個(gè)資源,不會(huì)引發(fā)競(jìng)爭(zhēng),但是同時(shí)寫(xiě)操作會(huì)引發(fā)競(jìng)爭(zhēng),string的不可變特點(diǎn),所以線(xiàn)程安全的。
支持hash緩存:
因?yàn)樽址遣豢勺兊?,所以?chuàng)建的時(shí)候hash被緩存下來(lái)了,不需要重新計(jì)算,使得字符串很適合做Map的鍵,處理速度要快過(guò)其他的對(duì)象。
到此這篇關(guān)于Java中String和StringBuffer及StringBuilder 有什么區(qū)別的文章就介紹到這了,更多相關(guān)Java String 內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Java字符處理之char、String、StringBuilder和StringBuffer詳解
- Java中的char、String、StringBuilder與StringBuffer全方面解析
- Java字符串四大類(lèi)之String、StringBuffer、StringBuilder、StringJoiner詳解
- Java中String、StringBuffer和StringBuilder底層實(shí)現(xiàn)深入剖析
- Java中String、StringBuffer和StringBuilder的區(qū)別
- Java中StringBuilder與StringBuffer的區(qū)別
- Java中StringBuilder與StringBuffer使用及源碼解讀
- 淺析Java中StringBuffer和StringBuilder的使用
- 詳解Java中String,StringBuffer和StringBuilder的使用
- Java 中 String、StringBuffer、StringBuilder 的區(qū)別
相關(guān)文章
Java實(shí)現(xiàn)通過(guò)IP計(jì)算分析歸屬地實(shí)例分享
文章介紹了如何通過(guò)IP地址進(jìn)行歸屬地分析,包括IP地址的兩種類(lèi)型(IPV4和IPV6)以及計(jì)算歸屬地的方法,對(duì)于不精準(zhǔn)的需求,推薦使用開(kāi)源的字典庫(kù)如GeoIP2;對(duì)于高精度需求,可以購(gòu)買(mǎi)專(zhuān)業(yè)的IP網(wǎng)段數(shù)據(jù)并實(shí)時(shí)更新數(shù)據(jù)庫(kù),在設(shè)計(jì)項(xiàng)目時(shí)應(yīng)提前規(guī)劃數(shù)據(jù)結(jié)構(gòu),以避免數(shù)據(jù)清洗問(wèn)題2025-05-05
Maven如何構(gòu)建可執(zhí)行的jar包(包含依賴(lài)jar包)
這篇文章主要介紹了Maven如何構(gòu)建可執(zhí)行的jar包(包含依賴(lài)jar包) ,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-11-11
SpringBoot中添加監(jiān)聽(tīng)器及創(chuàng)建線(xiàn)程的代碼示例
這篇文章主要介紹了SpringBoot中如何添加監(jiān)聽(tīng)器及創(chuàng)建線(xiàn)程,文中有詳細(xì)的代碼示例,具有一定的參考價(jià)值,需要的朋友可以參考下2023-06-06
解決springboot啟動(dòng)成功,但訪(fǎng)問(wèn)404的問(wèn)題
這篇文章主要介紹了解決springboot啟動(dòng)成功,但訪(fǎng)問(wèn)404的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-07-07
淺談Storm在zookeeper上的目錄結(jié)構(gòu)
這篇文章主要介紹了淺談Storm在zookeeper上的目錄結(jié)構(gòu)的相關(guān)內(nèi)容,涉及storm使用zookeeper的操作以及詳細(xì)結(jié)構(gòu)圖,具有一定參考價(jià)值,需要的朋友可以了解下。2017-10-10
MyBatis自定義攔截器實(shí)現(xiàn)優(yōu)化SQL日志輸出
這篇文章主要介紹了優(yōu)化MyBatisPlus SQL日志輸出的方案,針對(duì)默認(rèn)日志格式存在的不足,例如缺少時(shí)間、可讀性差、存儲(chǔ)成本高等,希望對(duì)大家有所幫助2026-03-03

