Java中String和StringBuffer及StringBuilder?有什么區(qū)別
前言:
String 是 Java 語言非常基礎和重要的類,提供了構造和管理字符串的各種基本邏輯。它是典型的 Immutable 類,被聲明成為 final class,所有屬性也都是 final 的。也由于它的不可變性,類似拼接、裁剪字符串等動作,都會產生新的 String 對象。由于字符串操作的普遍性,所以相關操作的效率往往對應用性能有明顯影響。 StringBuffer 是為解決上面提到拼接產生太多中間對象的問題而提供的一個類,我們可以用 append 或者 add 方法,把字符串添加到已有序列的末尾或者指定位置。StringBuffer 本質是一個線程安全的可修改字符序列,它保證了線程安全,也隨之帶來了額外的性能開銷,所以除非有線程安全的需要,不然還是推薦使用它的后繼者,也就是 StringBuilder。 StringBuilder 是 Java 1.5 中新增的,在能力上和 StringBuffer 沒有本質區(qū)別,但是它去掉了線程安全的部分,有效減小了開銷,是絕大部分情況下進行字符串拼接的首選。
String類為什么是immutable(不可變的)
不可變類指的是對象一旦創(chuàng)建成功,就無法改變對象的值。JDK中很多類設計為不可變的Integer,Long和String等。相對應的改法中大多是可變類,創(chuàng)建成功后可以動態(tài)修改成員變量的屬性值;
如何保證不可變
- 類添加final修飾符,保證類是不可以被繼承的;類繼承會破壞類的不可變機制,只要覆蓋父類的成員方法,并且在里面修改成員變量的值,那么所有子類以父類的形式出現(xiàn)的地方,類的屬性都會被修改掉
- 類成員屬性設置為private,final的;這樣可以保證成員屬性是不可變的,但是僅僅這樣還不夠,因為如果成員變量是引用對象的話,可以改變引用對象的成員變量;通過第四點可以避免這一點;
- 不提供修改成員變量的方法,比如setter;
- 通過構造器構造對象,并進行深拷貝;如果是直接通過引用傳入的對象直接賦值給成員,還是可以通過修改外部引用變量導致改變內部變量的值;
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); }
通過源碼可以看出來String是如何保證不可變的:
- String類是finaly的,不允許繼承
- 成員變量value是private,final的
- value沒有setter方法
- 構造方法,是通過克隆的方式來構造的
- 返回value時,通過克隆的方式返回
string類為不可變對象的好處
字符串常量池的需要:
String aaa= "someString"; String bbb = "someString"; 這兩個對象指向同一個內存,字符串常量池的好處是,在大量使用字符串的時候,可以節(jié)省內存,提供效率;如果String是可變對象,那么修改了一個,其他引用的地方全部發(fā)生變化了。
線程安全的考慮:
在并發(fā)場景下,多個線程同時讀一個資源,不會引發(fā)競爭,但是同時寫操作會引發(fā)競爭,string的不可變特點,所以線程安全的。
支持hash緩存:
因為字符串是不可變的,所以創(chuàng)建的時候hash被緩存下來了,不需要重新計算,使得字符串很適合做Map的鍵,處理速度要快過其他的對象。
到此這篇關于Java中String和StringBuffer及StringBuilder 有什么區(qū)別的文章就介紹到這了,更多相關Java String 內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
- Java中String、StringBuffer和StringBuilder的區(qū)別
- Java中的String、StringBuilder、StringBuffer三者的區(qū)別詳解
- Java中StringBuilder與StringBuffer的區(qū)別
- Java中StringBuilder與StringBuffer使用及源碼解讀
- 淺析Java中StringBuffer和StringBuilder的使用
- Java StringBuffer與StringBuilder有什么區(qū)別
- 詳解Java中String,StringBuffer和StringBuilder的使用
- Java源碼深度分析String與StringBuffer及StringBuilder詳解
- Java詳細分析String類與StringBuffer和StringBuilder的使用方法
- Java中String、StringBuffer和StringBuilder的區(qū)別與使用場景
相關文章
Java 多線程并發(fā)AbstractQueuedSynchronizer詳情
這篇文章主要介紹了Java 多線程并發(fā)AbstractQueuedSynchronizer詳情,文章圍繞主題展開想象的內容介紹,具有一定的參考價值,感興趣的小伙伴可以參考一下2022-06-06springboot如何使用redis的incr創(chuàng)建分布式自增id
這篇文章主要介紹了springboot如何使用redis的incr創(chuàng)建分布式自增id,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-11-11springboot使用小工具之Lombok、devtools、Spring Initailizr詳解
這篇文章主要介紹了springboot使用小工具之Lombok、devtools、Spring Initailizr詳解,Lombok可以代替手寫get、set、構造方法等,需要idea裝插件lombok,本文通過示例代碼給大家介紹的非常詳細,需要的朋友可以參考下2022-10-10Spring3 整合MyBatis3 配置多數(shù)據(jù)源動態(tài)選擇SqlSessionFactory詳細教程
這篇文章主要介紹了Spring3 整合MyBatis3 配置多數(shù)據(jù)源動態(tài)選擇SqlSessionFactory詳細教程,需要的朋友可以參考下2017-04-04