在java編程中字符串屬于對象晚顷,StringBuilder飘千、 StringBuffer、 String是java中常用的對字符串操作的類,那么他們什么不同呢菠剩?
String
String 類以及它的value都是final修飾的,表明String類是無法被繼承的族阅,value是無法被改寫的东跪,不存在擴容。String由于它的不可變性鸣哀,對其進行拼接架忌、截取等操作都會產(chǎn)生新的對象,頻繁操作字符串效率低下我衬,因中間對象太多叹放,造成內(nèi)存空間浪費(JDK8開始饰恕,String的操作會被編譯成StringBuilder)。
創(chuàng)建一個字符串時井仰,首先會檢查常量池中是否有值相同的字符串對象埋嵌,如果有就直接返回引用,不會創(chuàng)建字符串對象俱恶,如果沒有則新建字符串對象雹嗦,返回對象引用,并且將新創(chuàng)建的對象放入池中合是。但是通過new方法創(chuàng)建的String對象是直接在堆中創(chuàng)建新對象了罪。
例:
String str = "abdc";
執(zhí)行以上代碼,會先檢查在字符串常量池里是否有"abdc"對象聪全,如果有str直接指向該引用泊藕,如果
沒有就創(chuàng)建一個"abdc"對象,再將str指向該引用荔烧。
str = "hello";
這時str的值改變了吱七,這里的改變是str指向的引用變了,首先會檢查字符串常量池中是否有"hello"
對象鹤竭,沒有就創(chuàng)建一個該對象踊餐,然后將str指向該引用
String str1 = new String(“abdc”);
執(zhí)行以上代碼臀稚,會生成兩個對象吝岭,一個是會檢查常量池中是否有"abdc"的對象,沒有就創(chuàng)建一個并
放入常量池吧寺,另一個是會在堆中創(chuàng)建一個"abdc"對象窜管,str1就指向堆中的"abdc"對象。
java為解決String類大量操作字符串效率低下問題稚机,引入率StringBuilder和StringBuffer兩個類幕帆。
StringBuilder
StringBuilder類內(nèi)部維護的是可變長度的char[],存在擴容赖条,其append拼接字符串方法內(nèi)部調(diào)用System的native方法失乾,進行數(shù)組的拷貝,不會重新生成新的StringBuilder對象纬乍。它是非線程安全的字符串操作類碱茁,其每次調(diào)用toString方法而重新生成的String對象,不會共享StringBuilder對象內(nèi)部的char[]仿贬,會進行一次char[]的copy操作纽竣。
StringBuffer 類內(nèi)部維護可變長度char[],基本上與String一致,區(qū)別在于其是線程安全的字符串操作類蜓氨,大部分方法都采用了Synchronized關鍵字修改聋袋,以此來實現(xiàn)在多線程下的字符串操作的安全性。其toString方法而重新生成的String對象语盈,會共享StringBuffer對象中的toStringCache屬性舱馅,但是每次的StringBuffer對象修改,都會置空該屬性的值刀荒。
繼承關系
String實現(xiàn)了CharSequence和Serializable
StringBuffer和StringBuilder都繼承AbstractStringBuilder代嗤,而AbstractStringBuilder
實現(xiàn)了CharSequence和Appendable
相關知識
==和equals對比
== :
基本數(shù)據(jù)類型(byte,short缠借,char干毅,int,float泼返,double硝逢,long,boolean):比較的是值
是否相同
引用數(shù)據(jù)類型:比較的是地址值是否相同
equals的作用:
引用類型默認比較的是地址值绅喉,但是在一些類庫中已經(jīng)重寫了該方法渠鸽,重寫該方法一般用來比較對象
的成員變量值是否相同,如String柴罐, Integer徽缚, Date等類中,所以它們不再是比較類在堆中的地址了革屠。
例:
String str1 = new String(”fd”);
String str2 = new String(”fd”);
str1==str2;的值是false凿试,因為==比較的是對象的地址,他們的地址是不同的似芝,值相同那婉。
String str1 = ”fd”;
String str2 = ”fd”;
str1==str2;的值是true,因為他們都是指向字符串常量池中同一個對象党瓮,所以是相同的地址详炬。