JAVA String、StringBuffer火焰、StringBuilder類解讀
字符串廣泛應(yīng)用 在 Java 編程中劲装,在 Java 中字符串屬于對象,Java 提供了 String 類來創(chuàng)建和操作字符串昌简。
Java 可以通過最簡單的String str = "this is string"
,來創(chuàng)建字符串占业;
也可以通過構(gòu)造函數(shù)創(chuàng)建字符串String str2 = new String("this is string")
來創(chuàng)建字符串。
兩者的區(qū)別
首先明白一個事纯赎,java存在一個常量池谦疾,可以用來存儲字符串常量。先知概念:
①【常量池constant pool】管理在編譯時被確定并保存在已編譯的.class文件中的一些數(shù)據(jù)犬金,包括關(guān)于類念恍、方法、接口中的常量晚顷,和字符串常量峰伙。
②【字符串常量池(String pool, String intern pool, String保留池)】 是Java堆內(nèi)存中一個特殊的存儲區(qū)域, 當(dāng)創(chuàng)建一個String對象時,假如此字符串值已經(jīng)存在于常量池中,則不會創(chuàng)建一個新的對象,而是引用已經(jīng)存在的對象。
當(dāng)使用new String(“hello”)
時该默,JVM會先使用常量池來管理“hello”直接量瞳氓,再調(diào)用String類的構(gòu)造器來創(chuàng)建一個新的String對象,新創(chuàng)建的對象被保存在堆內(nèi)存中栓袖。即new String(“hello”)
一共產(chǎn)生了兩個字符串對象匣摘。
問題:
//代碼1
String sa=new String("Hello world");
String sb=new String("Hello world");
System.out.println(sa==sb); // false
//代碼2
String sc="Hello world";
String sd="Hello world";
System.out.println(sc==sd);
// true
JVM為了提升性能和減少內(nèi)存開銷,避免字符串的重復(fù)創(chuàng)建裹刮,維護了一塊特殊的內(nèi)存空間——字符串常量池音榜。
String賦值的兩種方式。
1必指、String str = "test";
以這種方式賦值時囊咏,JVM會先從字符串常量池中查詢是否存在"test"這個對象,
如果存在塔橡,直接把常量池中"test"的地址返回給str梅割。如果不存在,則會在常量池中創(chuàng)建"test"對象葛家,并把該對象的地址返回給str户辞。
所以通過==比較是,str1癞谒,str2指向的是同一地址底燎,所以返回true刃榨;
2、String str = new String("test");
以這種方式賦值時双仍,JVM會先從字符串常量池中查詢是否存在"test"這個對象枢希,
若不存在則會在常量池中創(chuàng)建"test"對象,同時調(diào)用String類的構(gòu)造器在堆中創(chuàng)建"test"這個對象朱沃,然后將堆中的這個對象的地址返回賦給引用str苞轿。
若常量池存在則直接調(diào)用String類的構(gòu)造器在堆中創(chuàng)建"test"這個對象琅坡,然后將堆中的這個對象的地址返回賦給引用str错沃。
這時str1和str2分別指向堆中不同的地址,所以返回false违寞;
String為什么是不可變的翎卓?
答:最流行的Java面試題之一就是:什么是不可變對象(immutable object)契邀,不可變對象有什么好處,在什么情況下應(yīng)該用失暴,或者更具體一些坯门,Java的String類為什么要設(shè)成immutable類型? 不可變對象锐帜,顧名思義就是創(chuàng)建后不可以改變的對象田盈,典型的例子就是Java中的String類。
String s = "ABC"; s.toLowerCase();
如上s.toLowerCase()并沒有改變“ABC“的值缴阎,而是創(chuàng)建了一個新的String類“abc”允瞧,然后將新的實例的指向變量s。 相對于可變對象蛮拔,不可變對象有很多優(yōu)勢:
1).不可變對象可以提高String Pool的效率和安全性述暂。如果你知道一個對象是不可變的,那么需要拷貝這個對象的內(nèi)容時建炫,就不用復(fù)制它的本身而只是復(fù)制它的地址畦韭,復(fù)制地址(通常一個指針的大小)需要很小的內(nèi)存效率也很高肛跌。對于同時引用這個“ABC”的其他變量也不會造成影響艺配。
2).不可變對象對于多線程是安全的,因為在多線程同時進行的情況下衍慎,一個可變對象的值很可能被其他進程改變转唉,這樣會造成不可預(yù)期的結(jié)果,而使用不可變對象就可以避免這種情況稳捆。 當(dāng)然也有其他方面原因赠法,但是Java把String設(shè)成immutable最大的原因應(yīng)該是效率和安全。
當(dāng)對字符串進行修改的時候乔夯,需要使用 StringBuffer 和 StringBuilder 類砖织。
和 String 類不同的是款侵,StringBuffer 和 StringBuilder 類的對象能夠被多次的修改,并且不產(chǎn)生新的未使用對象侧纯。
在使用 StringBuffer 類時新锈,每次都會對 StringBuffer 對象本身進行操作,而不是生成新的對象茂蚓,所以如果需要對字符串進行修改推薦使用 StringBuffer壕鹉。
StringBuilder 類在 Java 5 中被提出剃幌,它和 StringBuffer 之間的最大不同在于 StringBuilder 的方法不是線程安全的(不能同步訪問)聋涨。如果一個StringBuffer對象在字符串緩沖區(qū)被多個線程使用時,StringBuffer中很多方法可以帶有synchronized關(guān)鍵字负乡,所以可以保證線程是安全的牍白,但StringBuilder的方法則沒有該關(guān)鍵字,所以不能保證線程安全抖棘,有可能會出現(xiàn)一些錯誤的操作茂腥。
由于 StringBuilder 相較于 StringBuffer 有速度優(yōu)勢,所以多數(shù)情況下建議使用 StringBuilder 類切省。
運行速度快慢為:StringBuilder > StringBuffer > String
總結(jié)
String:適用于少量的字符串操作的情況
StringBuilder:適用于單線程下在字符緩沖區(qū)進行大量操作的情況
StringBuffer:適用多線程下在字符緩沖區(qū)進行大量操作的情況
參考文獻(xiàn):
①https://blog.csdn.net/u010887744/article/details/50844525
②https://www.cnblogs.com/weibanggang/p/9455926.html
③https://blog.csdn.net/qq_33417486/article/details/82787598
如有侵權(quán)最岗,告知必刪。