摘要:閱讀原文面試別再問我了字符串廣泛應(yīng)用在編程中,在中字符串屬于對(duì)象,提供了類來創(chuàng)建和操作字符串。測(cè)試此字符串是否以指定的后綴結(jié)束。當(dāng)執(zhí)行此句時(shí),因?yàn)閷?duì)應(yīng)的實(shí)例已經(jīng)存在于字符串常量池中,所以會(huì)將此實(shí)例復(fù)制到會(huì)在堆中并返回引用地址。
閱讀原文:面試別再問我String了
字符串廣泛應(yīng)用 在Java 編程中,在 Java 中字符串屬于對(duì)象,Java 提供了 String 類來創(chuàng)建和操作字符串。
String 簡(jiǎn)介String定義:
public final class String implements java.io.Serializable, Comparable為什么設(shè)計(jì)為不可變類呢?, CharSequence {}
String設(shè)計(jì)為不可變類主要考慮到:效率和安全。
效率:1.在早期的JVM實(shí)現(xiàn)版本中,被final修飾的方法會(huì)被轉(zhuǎn)為內(nèi)嵌調(diào)用以提升執(zhí)行效率。而從Java SE5/6開始,就漸漸擯棄這種方式了。因此在現(xiàn)在的Java SE版本中,不需要考慮用final去提升方法調(diào)用效率。只有在確定不想讓該方法被覆蓋時(shí),才將方法設(shè)置為final。2.緩存hashcode,String不可變,所以hashcode不變,這樣緩存才有意義,不必重新計(jì)算。
安全:String常被作為網(wǎng)絡(luò)連接,文件操作等參數(shù)類型,倘若可改變,會(huì)出現(xiàn)意想不到的結(jié)果。
測(cè)試掌握程度為了不浪費(fèi)你的時(shí)間,請(qǐng)看下面的題目,若你一目了然,可以跳過本文了。
public class Test { public static void main(String[] args) { String str1 = "HelloFlyapi"; String str2 = "HelloFlyapi"; String str3 = new String("HelloFlyapi"); String str4 = "Hello"; String str5 = "Flyapi"; String str6 = "Hello" + "Flyapi"; String str7 = str4 + str5; System.out.println("str1 == str2 result: " + (str1 == str2)); System.out.println("str1 == str3 result: " + (str1 == str3)); System.out.println("str1 == str6 result: " + (str1 == str6)); System.out.println("str1 == str7 result: " + (str1 == str7)); System.out.println("str1 == str7.intern() result: " + (str1 == str7.intern())); System.out.println("str3 == str3.intern() result: " + (str3 == str3.intern())); } }String 的創(chuàng)建方式
從上面的題中你會(huì)知道,String的創(chuàng)建方式有兩種:
直接賦值
此方式在方法區(qū)中字符串常量池中創(chuàng)建對(duì)象
String str = "flyapi";構(gòu)造器
此方式在堆內(nèi)存創(chuàng)建對(duì)象
String str = new String();分析
要理解String,那么要了解JVM內(nèi)存中的棧(stack)、堆(heap)和方法區(qū)。簡(jiǎn)要圖如下:
str1 == str2
String str1 = "HelloFlyapi"; String str2 = "HelloFlyapi"; System.out.println(str1 == str2); // true
當(dāng)執(zhí)行第一句時(shí),JVM會(huì)先去常量池中查找是否存在HelloFlyapi,當(dāng)存在時(shí)直接返回常量池里的引用;當(dāng)不存在時(shí),會(huì)在字符創(chuàng)常量池中創(chuàng)建一個(gè)對(duì)象并返回引用。
當(dāng)執(zhí)行第二句時(shí),同樣的道理,由于第一句已經(jīng)在常量池中創(chuàng)建了,所以直接返回上句創(chuàng)建的對(duì)象的引用。
str1 == str3
String str1 = "HelloFlyapi"; String str3 = new String("HelloFlyapi"); System.out.println(str1 == str3); // false
執(zhí)行第一句,同上第一句。
執(zhí)行第二句時(shí),會(huì)在堆(heap)中創(chuàng)建一個(gè)對(duì)象,當(dāng)字符創(chuàng)常量池中沒有‘HelloFlyapi’時(shí),會(huì)在常量池中也創(chuàng)建一個(gè)對(duì)象;當(dāng)常量池中已經(jīng)存在了,就不會(huì)創(chuàng)建新的了。
str1 == str6
String str1 = "HelloFlyapi"; String str6 = "Hello" + "Flyapi"; System.out.println(str1 == str6); // true
由于"Hello"和"Flyapi"都是常量,編譯時(shí),第二句會(huì)被自動(dòng)編譯為‘String str6 = "HelloFlyapi";’
str1 == str7
String str1 = "HelloFlyapi"; String str4 = "Hello"; String str5 = "Flyapi"; String str7 = str4 + str5; System.out.println(str1 == str7); // false
其中前三句變量存儲(chǔ)的是常量池中的引用地址。
第四句執(zhí)行時(shí),JVM會(huì)在堆(heap)中創(chuàng)建一個(gè)以str4為基礎(chǔ)的一個(gè)StringBuilder對(duì)象,然后調(diào)用StringBuilder的append()方法完成與str5的合并,之后會(huì)調(diào)用toString()方法在堆(heap)中創(chuàng)建一個(gè)String對(duì)象,并把這個(gè)String對(duì)象的引用賦給str7。
常用方法下面是 String 類支持的方法,更多詳細(xì),參看 Java String API 文檔:
方法 | 描述 |
---|---|
char charAt(int index) | 返回指定索引處的 char 值。 |
int compareTo(Object o) | 把這個(gè)字符串和另一個(gè)對(duì)象比較。 |
int compareTo(String anotherString) | 按字典順序比較兩個(gè)字符串。 |
boolean endsWith(String suffix) | 測(cè)試此字符串是否以指定的后綴結(jié)束。 |
boolean equals(Object anObject) | 將此字符串與指定的對(duì)象比較。 |
boolean equalsIgnoreCase(String anotherString) | 將此 String 與另一個(gè) String 比較,不考慮大小寫。 |
byte[] getBytes() | 使用平臺(tái)的默認(rèn)字符集將此 String 編碼為 byte 序列,并將結(jié)果存儲(chǔ)到一個(gè)新的 byte 數(shù)組中。 |
byte[] getBytes(String charsetName) | 使用指定的字符集將此 String 編碼為 byte 序列,并將結(jié)果存儲(chǔ)到一個(gè)新的 byte 數(shù)組中。 |
int indexOf(int ch) | 返回指定字符在此字符串中第一次出現(xiàn)處的索引。 |
int indexOf(int ch, int fromIndex) | 返回在此字符串中第一次出現(xiàn)指定字符處的索引,從指定的索引開始搜索。 |
int indexOf(String str) | 返回指定子字符串在此字符串中第一次出現(xiàn)處的索引。 |
int indexOf(String str, int fromIndex) | 返回指定子字符串在此字符串中第一次出現(xiàn)處的索引,從指定的索引開始。 |
String intern() | 返回字符串對(duì)象的規(guī)范化表示形式。 |
int lastIndexOf(int ch) | 返回指定字符在此字符串中最后一次出現(xiàn)處的索引。 |
int lastIndexOf(int ch, int fromIndex) | 返回指定字符在此字符串中最后一次出現(xiàn)處的索引,從指定的索引處開始進(jìn)行反向搜索。 |
int lastIndexOf(String str) | 返回指定子字符串在此字符串中最右邊出現(xiàn)處的索引。 |
int lastIndexOf(String str, int fromIndex) | 返回指定子字符串在此字符串中最后一次出現(xiàn)處的索引,從指定的索引開始反向搜索。 |
int length() | 返回此字符串的長(zhǎng)度。 |
boolean matches(String regex) | 告知此字符串是否匹配給定的正則表達(dá)式。 |
String replace(char oldChar, char newChar) | 返回一個(gè)新的字符串,它是通過用 newChar 替換此字符串中出現(xiàn)的所有 oldChar 得到的。 |
String replaceAll(String regex, String replacement) | 使用給定的 replacement 替換此字符串所有匹配給定的正則表達(dá)式的子字符串。 |
String replaceFirst(String regex, String replacement) | 使用給定的 replacement 替換此字符串匹配給定的正則表達(dá)式的第一個(gè)子字符串。 |
String[] split(String regex) | 根據(jù)給定正則表達(dá)式的匹配拆分此字符串。 |
String[] split(String regex, int limit) | 根據(jù)匹配給定的正則表達(dá)式來拆分此字符串。 |
boolean startsWith(String prefix) | 測(cè)試此字符串是否以指定的前綴開始。 |
boolean startsWith(String prefix, int toffset) | 測(cè)試此字符串從指定索引開始的子字符串是否以指定前綴開始。 |
String substring(int beginIndex) | 返回一個(gè)新的字符串,它是此字符串的一個(gè)子字符串。 |
String substring(int beginIndex, int endIndex) | 返回一個(gè)新字符串,它是此字符串的一個(gè)子字符串。 |
char[] toCharArray() | 將此字符串轉(zhuǎn)換為一個(gè)新的字符數(shù)組。 |
String toLowerCase() | 使用默認(rèn)語言環(huán)境的規(guī)則將此 String 中的所有字符都轉(zhuǎn)換為小寫。 |
String toUpperCase() | 使用默認(rèn)語言環(huán)境的規(guī)則將此 String 中的所有字符都轉(zhuǎn)換為大寫。 |
String trim() | 返回字符串的副本,忽略前導(dǎo)空白和尾部空白。 |
由于String的不可變性導(dǎo)致,字符串變更時(shí)效率低下,在之后得JDK版本中出現(xiàn)了StringBuilder和StringBuffer.
類 | 可變性 | 線程安全 |
---|---|---|
String | 不可變 | 安全 |
StringBuffer | 可變 | 安全 |
StringBuilder | 可變 | 非安全 |
使用選擇
當(dāng)有少量連接操作時(shí),使用String
當(dāng)單線程下有大量連接操作時(shí),使用StringBuilder
當(dāng)多線程下有大量連接操作時(shí),使用StringBuffer
常見String面試題String str = new String("abc")創(chuàng)建了多少個(gè)實(shí)例?
這個(gè)問題其實(shí)是不嚴(yán)謹(jǐn)?shù)?,但面試一般?huì)遇到,所以我們要補(bǔ)充來說明。
類的加載和執(zhí)行要分開來講:
創(chuàng)建了兩個(gè)當(dāng)加載類時(shí),"abc"被創(chuàng)建并駐留在了字符創(chuàng)常量池中(如果先前加載中沒有創(chuàng)建駐留過)。
當(dāng)執(zhí)行此句時(shí),因?yàn)?abc"對(duì)應(yīng)的String實(shí)例已經(jīng)存在于字符串常量池中,所以JVM會(huì)將此實(shí)例復(fù)制到會(huì)在堆(heap)中并返回引用地址。
通過字節(jié)碼我們可以看到:
源碼:String str = new String("abc")
字節(jié)碼:
Code: 0: new #2 // class java/lang/String 3: dup 4: ldc #3 // String abc 6: invokespecial #4 // Method java/lang/String."":(Ljava/lang/String;) 9: astore_1 10: return
執(zhí)行時(shí)僅(#2)創(chuàng)建了一個(gè)對(duì)象。
關(guān)于這個(gè)面試題,可以看看一個(gè)超大牛的回答:http://rednaxelafx.iteye.com/...
本文優(yōu)先發(fā)布于微信公眾號(hào):碼上實(shí)戰(zhàn) 和 GitHub 上。
GitHub flyhero
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/73991.html
摘要:例如資源的獲取,支持多種消息例如的支持,對(duì)多了工具級(jí)別的支持等待。最上面的知道吧我就不講了。生命周期事件回調(diào)等。他支持不同信息源頭,支持工具類,支持層級(jí)容器,支持訪問文件資源,支持事件發(fā)布通知,支持接口回調(diào)等等。 廣義的 IOC IoC(Inversion of Control) 控制反轉(zhuǎn),即不用打電話過來,我們會(huì)打給你。 兩種實(shí)現(xiàn): 依賴查找(DL)和依賴注入(DI)。 IOC 和...
摘要:閱讀原文小而有料的想聽文章核心內(nèi)容語音對(duì)話版,請(qǐng)到微信公眾號(hào)碼上實(shí)戰(zhàn),閱讀原文這塊肉雖然小,但不可不知,因?yàn)椴粌H面試可能會(huì)問,實(shí)際中也常使用。參考書籍編程思想深入理解虛擬機(jī)更多精彩技術(shù)文章盡在微信公眾號(hào)碼上實(shí)戰(zhàn) 閱讀原文:小而有料的final(想聽文章核心內(nèi)容語音對(duì)話版,請(qǐng)到微信公眾號(hào)——碼上實(shí)戰(zhàn),閱讀原文) final這塊肉雖然小,但不可不知,因?yàn)椴粌H面試可能會(huì)問,實(shí)際中也常使用。就...
摘要:所以構(gòu)造函數(shù)里的指的就是將要被出來的新對(duì)象。希望看完這篇文章之后,再有人問指向的問題,你可以嘴角微微上揚(yáng),冷笑一聲不要再問我的指向問題了。 this的指向已經(jīng)是一個(gè)老生常談的問題,每逢面試都要去復(fù)習(xí)復(fù)習(xí),近來鞏固js的基礎(chǔ),決心徹底掌握這個(gè)知識(shí)點(diǎn),一勞永逸。說明一下,為了不影響大家的思考過程,下面的代碼都不會(huì)去注釋答案,想知道答案,只需要去控制臺(tái)執(zhí)行一下。 四類場(chǎng)景逐一擊破 首先,分析...
摘要:不過大多數(shù)講解還停留在對(duì)功能使用的層面,其底層的很多原理,很多人可能并不知曉。每個(gè)線程池里的線程就僅僅用于請(qǐng)求那個(gè)服務(wù)。 歡迎關(guān)注微信公眾號(hào):石杉的架構(gòu)筆記(id:shishan100) 每日更新!精品技術(shù)文章準(zhǔn)時(shí)送上! 目錄 一、業(yè)務(wù)場(chǎng)景介紹 二、Spring Cloud核心組件:Eureka 三、Spring Cloud核心組件:Feign 四、Spring Cloud核心組件:R...
摘要:不過大多數(shù)講解還停留在對(duì)功能使用的層面,其底層的很多原理,很多人可能并不知曉。每個(gè)線程池里的線程就僅僅用于請(qǐng)求那個(gè)服務(wù)。 歡迎關(guān)注微信公眾號(hào):石杉的架構(gòu)筆記(id:shishan100) 每日更新!精品技術(shù)文章準(zhǔn)時(shí)送上! 目錄 一、業(yè)務(wù)場(chǎng)景介紹 二、Spring Cloud核心組件:Eureka 三、Spring Cloud核心組件:Feign 四、Spring Cloud核心組件:R...
閱讀 2076·2021-09-07 09:59
閱讀 2595·2019-08-29 16:33
閱讀 3773·2019-08-29 16:18
閱讀 2936·2019-08-29 15:30
閱讀 1755·2019-08-29 13:52
閱讀 2124·2019-08-26 18:36
閱讀 604·2019-08-26 12:19
閱讀 765·2019-08-23 15:23