欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java基礎(chǔ)教程之String深度分析

 更新時(shí)間:2019年06月30日 09:47:41   作者:工匠初心  
這篇文章主要給大家介紹了關(guān)于Java基礎(chǔ)教程之String的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

前言

String可以說(shuō)是Java中使用最多最頻繁、最特殊的類(lèi),因?yàn)橥瑫r(shí)也是字面常量,而字面常量包括基本類(lèi)型、String類(lèi)型、空類(lèi)型。

一. String的使用

1. String的不可變性

/**
 * The {@code String} class represents character strings. All
 * string literals in Java programs, such as {@code "abc"}, are
 * implemented as instances of this class.
 * <p>
 * Strings are constant; their values cannot be changed after they
 * are created. String buffers support mutable strings.
 * Because String objects are immutable they can be shared. For example:
 * ...
 */

public final class String { 
 private final char value[];
}

String對(duì)象一旦在堆中創(chuàng)建出來(lái),就無(wú)法再修改。因?yàn)镾tring對(duì)象放在char數(shù)組中,該數(shù)組由final關(guān)鍵字修飾,不可變。

2. 定義一個(gè)字符串

/**
 * 定義一個(gè)字符串
 */
String str1 = "helloworld";
String str2 = "helloworld";
//也可以,但基本不這樣寫(xiě)
String str3 = new String("helloworld");
System.out.println(str1 == str2);
System.out.println(str1 == str3);

//運(yùn)行結(jié)果 true, false

上面三句代碼怎么理解呢?這里需要先引入一個(gè)概念,字符串常量池。

字符串常量池是一塊特殊的獨(dú)立內(nèi)存空間,放在Java Heap中 { 在Jdk7.0之前字符串常量池存放在PermGen中,Jdk7.0的時(shí)候移動(dòng)到了Java Heap(在堆中仍然是獨(dú)立的),Jdk8.0的時(shí)候去掉了PermGen,用Metaspace進(jìn)行取代 } ,Java內(nèi)存模型不是本章討論的重點(diǎn)。

str1和str2引用的字符串字面量就在字符串常量池中,而str3引用的對(duì)象在Java Heap中。

怎么,還不太好理解?舉個(gè)例子

工作一天,到下班時(shí)間了,準(zhǔn)備看會(huì)兒金瓶.,算了,《三國(guó)演義》,打開(kāi)小說(shuō)網(wǎng)站,在線閱讀;過(guò)了半個(gè)小時(shí),女票回家了,看《三國(guó)演義》也是她想做的事兒,我看網(wǎng)址發(fā)給她,好,她也開(kāi)始看了,再過(guò)半個(gè)小時(shí),我爸回來(lái)了,他也是三國(guó)迷,但是他不喜歡在線看,因此在書(shū)店買(mǎi)了一本看。

上面提到的小說(shuō)網(wǎng)站就是一個(gè)字符串常量池,包含了很多字符串字面量,如《三國(guó)演義》、《西游記》、《紅樓夢(mèng)》等,每個(gè)字符串字面量在常量池中保持獨(dú)一份,無(wú)論誰(shuí)進(jìn)網(wǎng)站看《三國(guó)演義》都是同樣的網(wǎng)址和同樣的內(nèi)容。

我和女票就是str1和str2,我們看的都是同一個(gè)網(wǎng)站的《三國(guó)演義》,不僅內(nèi)容一樣,引用的地址也一樣(字符串常量池中保留了唯一的“helloworld”),因此str1 == str2 運(yùn)行結(jié)果為true

而我爸就是str3,與我和女票都不一樣,雖然看的內(nèi)容也是《三國(guó)演義》,但是通過(guò)實(shí)體書(shū)籍來(lái)看,引用地址不一樣,同時(shí)一本書(shū)籍不支持多個(gè)人同時(shí)看(字符串對(duì)象在java heap中,且每次new都會(huì)新建一個(gè)對(duì)象),因此str1 == str3 運(yùn)行結(jié)果為false。

一個(gè)字符串字面量總是引用String類(lèi)的同一個(gè)實(shí)例,因?yàn)楸籗tring.intern()方法限定了,同樣我們可以調(diào)用該方法將堆中的String對(duì)象放到字符串常量池中,這樣做可以提升內(nèi)存使用效率,同時(shí)可以讓所用使用者共享唯一的實(shí)例。

System.out.println(str1 == str3.intern());
//運(yùn)行結(jié)果為true

那么該方法的實(shí)現(xiàn)邏輯是怎么樣的呢,我們看一下源碼

/** 
 * Returns a canonical representation for the string object. 
 * <p> 
 * A pool of strings, initially empty, is maintained privately by the 
 * class {@code String}. 
 * <p> 
 * When the intern method is invoked, if the pool already contains a 
 * string equal to this {@code String} object as determined by 
 * the {@link #equals(Object)} method, then the string from the pool is 
 * returned. Otherwise, this {@code String} object is added to the 
 * pool and a reference to this {@code String} object is returned. 
 * <p> 
 * It follows that for any two strings {@code s} and {@code t}, 
 * {@code s.intern() == t.intern()} is {@code true} 
 * if and only if {@code s.equals(t)} is {@code true}. 
 * <p> 
 * All literal strings and string-valued constant expressions are 
 * interned. String literals are defined in section 3.10.5 of the 
 * <cite>The Java&trade; Language Specification</cite>. 
 * 
 * @return a string that has the same contents as this string, but is 
 *  guaranteed to be from a pool of unique strings. 
 */
 public native String intern();

我們發(fā)現(xiàn)這是一個(gè)native方法,看一下注釋?zhuān)l(fā)現(xiàn)str3.intern()方法大致流程是:

當(dāng)執(zhí)行intern()時(shí),會(huì)先判斷字符串常量池中是否含有相同(通過(guò)equals方法)的字符串字面量,如果有直接返回字符串字面量;如果不含,則將該字符串對(duì)象添加到字符串常量池中,同時(shí)返回該對(duì)象在字符串常量池的引用。

返回的引用需要賦值才可,否則還是會(huì)指向堆中的地址,即:

String str4 = new String("helloChina");
System.out.println(str4.intern() == str4);//false
str4 = str4.intern();
String str5 = "helloChina";
String str6 = "helloZhonghua"
System.out.println(str4 == str5);//true

下面我們看一下內(nèi)存結(jié)構(gòu)


3. 再次賦值給已定義的字符串

str6 = "helloHuaxia";

我們開(kāi)始已經(jīng)說(shuō)了String是由final關(guān)鍵字修飾,不可變,那么此時(shí)在內(nèi)存中如何體現(xiàn)呢?

4. String 對(duì) “+” 的處理

String str7 = "good good" + " study";
String str8 = "good good study";
system.out.println(str7 == str8);

通過(guò)編譯工具后得到

String str7 = "good good study";
String str8 = "good good study";

因此我們可以發(fā)現(xiàn)編譯器在編譯期間就是進(jìn)行變量合并,而不會(huì)在常量池中創(chuàng)建三個(gè)對(duì)象 “good good”,“ study”,"good good study"。str7 == str8 運(yùn)行結(jié)果 true。

但如果這樣

String str9 = "good good ";
String str10 = str9 + "study";
system.out.println(str8 == str10);//false

這時(shí)運(yùn)行結(jié)果為false,通過(guò)String變量 + 字符常量方式得到的結(jié)果會(huì)在堆中,不在常量池中,當(dāng)然可以通過(guò)intern()方法放進(jìn)常量池中,同時(shí)不僅“+”如此,調(diào)用substring(),toUpperCase(),trim()等返回的都是String在堆中的地址。

5. String常用的方法

//str1 == "hello,world ";

//獲取長(zhǎng)度
str1.length()//12;

//截取位置2到5之間的字符串(包括位置2,不包括位置5,從0開(kāi)始)
str1.substring(2,5);//"llo"

//判斷是否含有字符串“ello”
str1.contains("ello");//true,通過(guò)indexOf實(shí)現(xiàn)

//獲取ello在str1中的開(kāi)始位置
str1.indexOf("ello");//1

//將字符串轉(zhuǎn)化為字符串?dāng)?shù)據(jù)
str1.split(",");//["hello","world"]

//去掉字符串兩側(cè)空格
str1.trim();//"hello,world"

二. 總結(jié)

本文從String的不可變性,String創(chuàng)建時(shí)字面量和String對(duì)象的不同,字符串字面量常量池,字符串的內(nèi)存結(jié)構(gòu),常用的String相關(guān)方法的描述,若有不對(duì)之處,請(qǐng)批評(píng)指正,望共同進(jìn)步,謝謝!

好了,以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對(duì)腳本之家的支持。

相關(guān)文章

  • JAVA中HTTP基本認(rèn)證(Basic Authentication)實(shí)現(xiàn)

    JAVA中HTTP基本認(rèn)證(Basic Authentication)實(shí)現(xiàn)

    HTTP 基本認(rèn)證是一種簡(jiǎn)單的認(rèn)證方法,本文主要介紹了JAVA中HTTP基本認(rèn)證(Basic Authentication),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2024-07-07
  • 找不到正確的java_home路徑報(bào)錯(cuò)解決

    找不到正確的java_home路徑報(bào)錯(cuò)解決

    本文主要介紹了找不到正確的java_home路徑報(bào)錯(cuò)解決,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-07-07
  • Java中的synchronized重量級(jí)鎖解析

    Java中的synchronized重量級(jí)鎖解析

    這篇文章主要介紹了Java中的synchronized重量級(jí)鎖解析,內(nèi)核需要去申請(qǐng)這個(gè)互斥量,必須要進(jìn)入內(nèi)核態(tài),也就是這里需要用戶態(tài),內(nèi)核態(tài)的切換,狀態(tài)的切換,開(kāi)銷(xiāo)是比較大的,這就是重型鎖的一個(gè)弊端,需要的朋友可以參考下
    2024-01-01
  • 一篇文章帶你搞定SpringBoot不重啟項(xiàng)目實(shí)現(xiàn)修改靜態(tài)資源

    一篇文章帶你搞定SpringBoot不重啟項(xiàng)目實(shí)現(xiàn)修改靜態(tài)資源

    這篇文章主要介紹了一篇文章帶你搞定SpringBoot不重啟項(xiàng)目實(shí)現(xiàn)修改靜態(tài)資源,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09
  • SpringSecurity6自定義JSON登錄的實(shí)現(xiàn)

    SpringSecurity6自定義JSON登錄的實(shí)現(xiàn)

    目前最新版的Spring Boot已經(jīng)到了3.0.5了,隨之而來(lái)Spring Security 目前的版本也到了6.0.2了,Spring Security寫(xiě)法的變化特別多,本文就來(lái)介紹下,感興趣的可以了解一下
    2023-12-12
  • Java語(yǔ)法基礎(chǔ)之循環(huán)結(jié)構(gòu)語(yǔ)句詳解

    Java語(yǔ)法基礎(chǔ)之循環(huán)結(jié)構(gòu)語(yǔ)句詳解

    這篇文章主要為大家詳細(xì)介紹了Java語(yǔ)法基礎(chǔ)之循環(huán)結(jié)構(gòu)語(yǔ)句,感興趣的小伙伴們可以參考一下
    2016-09-09
  • Java內(nèi)省之Introspector解讀

    Java內(nèi)省之Introspector解讀

    這篇文章主要介紹了Java內(nèi)省之Introspector解讀,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-11-11
  • IDEA中Maven爆紅以及依賴(lài)下載失敗的最全解決方案

    IDEA中Maven爆紅以及依賴(lài)下載失敗的最全解決方案

    這篇文章主要介紹了IDEA中Maven爆紅,依賴(lài)下載失敗的最全解決方案,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-08-08
  • java hasNext()使用實(shí)例解析

    java hasNext()使用實(shí)例解析

    這篇文章主要介紹了java hasNext()使用實(shí)例解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-09-09
  • SpringBoot集成SwaggerUi以及啟動(dòng)時(shí)遇到的錯(cuò)誤

    SpringBoot集成SwaggerUi以及啟動(dòng)時(shí)遇到的錯(cuò)誤

    這篇文章主要介紹了SpringBoot集成SwaggerUi以及啟動(dòng)時(shí)遇到的錯(cuò)誤,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-06-06

最新評(píng)論