【圖文詳解系列】String,StringBuffer與StringBuilder的區別

一、Java String 類——String字符串常量

String 類實現了 CharSequence 接口。

字符串廣泛應用 在Java 編程中,在 Java 中字符串屬於對象,Java 提供了 String 類來創建和操作字符串。

需要注意的是,String的值是不可變的,這就導致每次對String的操作都會生成新的String對象,這樣不僅效率低下,而且大量浪費有限的內存空間。

我們來看一下這張對String操作時內存變化的圖:

我們可以看到,初始String值爲“hello”,然後在這個字符串後面加上新的字符串“world”,這個過程是需要重新在棧堆內存中開闢內存空間的,最終得到了“hello world”字符串也相應的需要開闢內存空間,這樣短短的兩個字符串,卻需要開闢三次內存空間,不得不說這是對內存空間的極大浪費。

對String的內存解析

@Test
public void stringTest(){
        /*
         * str1和str2地址指向字符串常量池
         * 解析: str1 在字符串常量池中創建出java 地址例如爲:0x456 
         * str2建立時會去常量池中找是否有java 有的話賦值 str2地址爲0x456
         * str3和str4地址指向堆空間
         * str在對空間創建,Stringvalue屬性指向字符串常量池,存在賦值給其內部屬性 value地址爲0x456 而對於創建的空間而言 也是有自己的地址爲0x789
         * 所以str3爲0x789 
         * ==判斷地址
         * equals判斷內容 同爲字符串常量池中的java 所以相等
         */
        String str1="java";
        String str2="java";
        String str3=new String("java");
        String str4=new String("java");
        System.out.println(str1==str2);//true  同指向字符串常量池中所以值和地址都相同
        System.out.println(str1.equals(str2));//true 
        System.out.println(str1==str3);//false   地址不同 str3有自己獨有的地址
        System.out.println(str1.equals(str3));//true
        System.out.println(str3==str4);//false   地址不同
        System.out.println(str3.equals(str4));//true str3和str4中的value屬性(用來保存字符串的)也是指向字符串常量池中的0x456所以值是相等的
    }

爲了應對經常性的字符串相關的操作,就需要使用Java提供的其他兩個操作字符串的類——StringBuffer類和StringBuild類來對此種變化字符串進行處理。

二、StringBuffer 和 StringBuilder 類——StringBuffer、StringBuilder字符串變量

當對字符串進行修改的時候,需要使用 StringBuffer 和 StringBuilder 類。

和 String 類不同的是,StringBuffer 和 StringBuilder 類的對象能夠被多次的修改,並且不產生新的未使用對象。

StringBuilder 類在 Java 5 中被提出,它和 StringBuffer 之間的最大不同在於 StringBuilder 的方法不是線程安全的(不能同步訪問)。

由於 StringBuilder 相較於 StringBuffer 有速度優勢,所以多數情況下建議使用 StringBuilder 類。然而在應用程序要求線程安全的情況下,則必須使用 StringBuffer 類。

三者的繼承結構:

三者的區別:

(1)字符修改上的區別(主要)

String:不可變字符串;

StringBuffer:可變字符串、效率低、線程安全;

StringBuilder:可變字符序列、效率高、線程不安全;

(2)初始化上的區別,String可以空賦值,後者不行,報錯

①String

StringBuffer s = null;

StringBuffer s = “abc”;

②StringBuffer

StringBuffer s = null; //結果警告:Null pointer access: The variable result can only be null at this location

StringBuffer s = new StringBuffer();//StringBuffer對象是一個空的對象

StringBuffer s = new StringBuffer(“abc”);//創建帶有內容的StringBuffer對象,對象的內容就是字符串”

小結:

(1)如果要操作少量的數據用 String;

(2)多線程操作字符串緩衝區下操作大量數據 StringBuffer;

(3)單線程操作字符串緩衝區下操作大量數據 StringBuilder(推薦使用)。

總結

三者區別可參照下表:

參考資料

https://blog.csdn.net/qian520ao/article/details/79118474
https://blog.csdn.net/weixin_41101173/article/details/79677982
https://www.cnblogs.com/bweird-java/p/5221596.html


Kotlin開發者社區

專注分享 Java、 Kotlin、Spring/Spring Boot、MySQL、redis、neo4j、NoSQL、Android、JavaScript、React、Node、函數式編程、編程思想、"高可用,高性能,高實時"大型分佈式系統架構設計主題。

High availability, high performance, high real-time large-scale distributed system architecture design

分佈式框架:Zookeeper、分佈式中間件框架等
分佈式存儲:GridFS、FastDFS、TFS、MemCache、redis等
分佈式數據庫:Cobar、tddl、Amoeba、Mycat
雲計算、大數據、AI算法
虛擬化、雲原生技術
分佈式計算框架:MapReduce、Hadoop、Storm、Flink等
分佈式通信機制:Dubbo、RPC調用、共享遠程數據、消息隊列等
消息隊列MQ:Kafka、MetaQ,RocketMQ
怎樣打造高可用系統:基於硬件、軟件中間件、系統架構等一些典型方案的實現:HAProxy、基於Corosync+Pacemaker的高可用集羣套件中間件系統
Mycat架構分佈式演進
大數據Join背後的難題:數據、網絡、內存和計算能力的矛盾和調和
Java分佈式系統中的高性能難題:AIO,NIO,Netty還是自己開發框架?
高性能事件派發機制:線程池模型、Disruptor模型等等。。。

合抱之木,生於毫末;九層之臺,起於壘土;千里之行,始於足下。不積跬步,無以至千里;不積小流,無以成江河。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章