淺談String、StringBuffer和StringBuilder之間的區(qū)別
一. String
String 類是不可變類,即一旦一個String對象被創(chuàng)建以后,包含在這個對象中的字符序列是不可改變的,直至這個對象被銷毀。
String的實例化方式
通過字面量方式實例化
String str ="abc";
通過new+構(gòu)造器的方式實例化
String str = newString("abc");
區(qū)別:
- 通過字面量方式為字符串賦值時,此時的字符串存儲在方法區(qū)的字符串常量池中;
- 通過new+構(gòu)造器方式實例化字符串時,字符串對象存儲在堆中,但是字符串的值仍然存儲在方法區(qū)的常量池中。
String字符串具有不可變性,當(dāng)字符串重新賦值時,不管是對字符串進(jìn)行拼接,還是調(diào)用String的replace()方法修改指定的字符或字符串,都不會在原來的內(nèi)存地址進(jìn)行修改,而是重新分配新的內(nèi)存地址進(jìn)行賦值
二. StringBuffer
StringBuffer對象代表一個字符序列可變的字符串,當(dāng)一個StringBuffer被創(chuàng)建以后,通StringBuffer提供的append()、insert()、reverse()、setCharAt()、setLength()等方法可以改變這個字符串對象的字符序列,但都不會產(chǎn)生新的對象。通過StringBuffer生成的字符串,可以調(diào)用toString()方法將其轉(zhuǎn)換為一個String對象。
StringBuffer是線程安全的
StringBuffer類中實現(xiàn)的方法,StringBuffer是如何實現(xiàn)線程安全的呢?
@Override public synchronized int length() { return count; } @Override public synchronized int capacity() { return value.length; } @Override public synchronized void ensureCapacity(int minimumCapacity) { super.ensureCapacity(minimumCapacity); } /** * @since 1.5 */ @Override public synchronized void trimToSize() { super.trimToSize(); }
從源碼中可以看到,StringBuffer類中的方法都添加了synchronized關(guān)鍵字,也就是給這個方法添加了一個鎖,用來保證線程安全。
三. StringBuilder
StringBuilder類也代表可變字符串對象。實際上,StringBuilder和StringBuffer基本相似,他們的原理與操作一樣,兩個類的構(gòu)造器和方法也基本相同。
不同的是:StringBuffer是線程安全的,而StringBuilder則沒有實現(xiàn)線程安全功能,所以性能略高。
四. 總結(jié)
String、StringBuffer和StringBuilder三者的異同?
- String :不可變的字符序列;底層使用 byte[] 存儲。
- StringBuffer :可變的字符序列;線程安全的,效率低;底層使用 byte[] 存儲。
- StringBuilder :可變的字符序列;jdk5.0新增的,線程不安全的,效率高;底層使用 byte[] 存儲。
從代碼角度驗證三者的效率對比
接下我們來測試下拼接10000條數(shù)據(jù)的各自所耗的時間
package com.scg.springcloudordercenter.controller; /** * @author gf * @date 2023/2/21 */ public class StringTest { public static void main(String[] args) { long startTime; long endTime; String str1 = ""; StringBuffer str2 = new StringBuffer(""); StringBuilder str3 = new StringBuilder(""); // 1.拼接str1,計算String所耗時間 startTime = System.currentTimeMillis(); for(int i= 1;i<=10000;i++){ str1 += i; } endTime = System.currentTimeMillis(); System.out.println("String所耗時間為:" + (endTime-startTime) + "毫秒"); // 2.拼接str2,計算StringBuffer所耗時間 startTime = System.currentTimeMillis(); for(int i= 1;i<=10000;i++){ str2.append(i); } endTime = System.currentTimeMillis(); System.out.println("StringBuffer所耗時間為:" + (endTime-startTime) + "毫秒"); // 3.拼接str3,計算StringBuilder所耗時間 startTime = System.currentTimeMillis(); for(int i= 1;i<=10000;i++){ str3.append(i); } endTime = System.currentTimeMillis(); System.out.println("StringBuilder所耗時間為:" + (endTime-startTime) + "毫秒"); } }
結(jié)果:
String所耗時間為:745毫秒
StringBuffer所耗時間為:4毫秒
StringBuilder所耗時間為:1毫秒
Process finished with exit code 0
很明顯,我們拼接一萬次字符串操作就可以對比出三者的效率:StringBuilder>StringBuffer>String
到此這篇關(guān)于淺談String、StringBuffer和StringBuilder之間的區(qū)別的文章就介紹到這了,更多相關(guān)String、StringBuffer和StringBuilder區(qū)別內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
IntelliJ IDEA設(shè)置顯示內(nèi)存指示器和設(shè)置內(nèi)存大小的方法
這篇文章主要介紹了IntelliJ IDEA設(shè)置顯示內(nèi)存指示器和設(shè)置內(nèi)存大小的方法,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-04-04Java打包之后讀取Resources下的文件失效原因及解決方法
這篇文章主要給大家介紹了Java打包之后讀取Resources下的文件失效的問題分析和解決方法,文中通過代碼示例和圖文結(jié)合給大家講解非常詳細(xì),需要的朋友可以參考下2023-12-12Java 線程池_動力節(jié)點(diǎn)Java學(xué)院整理
系統(tǒng)啟動一個新線程的成本是比較高的,因為它涉及到與操作系統(tǒng)的交互。在這種情況下,使用線程池可以很好的提供性能,尤其是當(dāng)程序中需要創(chuàng)建大量生存期很短暫的線程時,更應(yīng)該考慮使用線程池2017-05-05MyBatis的各種查詢功能結(jié)果接收類型的選擇(推薦)
文章介紹了MyBatis中查詢結(jié)果的不同接收方式,包括單條數(shù)據(jù)和多條數(shù)據(jù)的處理方法,以及MyBatis的默認(rèn)類型別名,感興趣的朋友跟隨小編一起看看吧2024-11-11詳解 Java Maximum redirects (100) exceeded
這篇文章主要介紹了詳解 Java Maximum redirects (100) exceeded的相關(guān)資料,需要的朋友可以參考下2017-05-05SpringBoot使用Druid數(shù)據(jù)源的配置方法
這篇文章主要介紹了SpringBoot使用Druid數(shù)據(jù)源的配置方法,文中代碼實例相結(jié)合的形式給大家介紹的非常詳細(xì),需要的朋友參考下吧2018-04-04