最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

JAVA中的字符串常量池使用操作代碼

 更新時間:2022年12月27日 08:51:41   作者:JAVA旭陽  
Java中的字符串常量池是Java堆中的一塊特殊存儲區(qū)域,用于存儲字符串。它的實現(xiàn)是為了提高字符串操作的性能并節(jié)省內(nèi)存,這篇文章主要介紹了JAVA中的字符串常量池,需要的朋友可以參考下

前言

研究表明,Java堆中對象占據(jù)最大比重的就是字符串對象,所以弄清楚字符串知識很重要,本文主要重點聊聊字符串常量池。Java中的字符串常量池是Java堆中的一塊特殊存儲區(qū)域,用于存儲字符串。它的實現(xiàn)是為了提高字符串操作的性能并節(jié)省內(nèi)存。它也被稱為String Intern PoolString Constant Pool。那讓我來看看究竟是怎么一回事吧。

理解字符串常量池

當(dāng)您從在類中寫一個字符串字面量時,JVM將首先檢查該字符串是否已存在于字符串常量池中,如果存在,JVM 將返回對現(xiàn)有字符串對象的引用,而不是創(chuàng)建新對象。我們通過一個例子更好的來理解。

比如下面的代碼:

String s1 = "Harry Potter";
String s2 = "The Lord of the Rings";
String s3 = "Harry Potter";

在這段代碼中,JVM 將創(chuàng)建一個值為“Harry Potter”的字符串對象,并將其存儲在字符串常量池中。s1和s3都將是對該單個字符串對象的引用。

如果s2的字符串內(nèi)容“The Lord of the Rings”不存在于池中,則在字符串池中生成一個新的字符串對象。

兩種創(chuàng)建字符串方式

Java 編程語言中有兩種創(chuàng)建 String 的方法。第一種方式是使用String Literal字符串字面量的方式,另一種方式是使用new關(guān)鍵字。他們創(chuàng)建的字符串對象是都在常量池中嗎?

字符串字面量的方式創(chuàng)建

String s1 = "Harry Potter";
String s2 = "The Lord of the Rings";
String s3 = "Harry Potter";

new關(guān)鍵字創(chuàng)建

String s4 = new String("Harry Potter");
String s5 = new String("The Lord of the Rings");

我們來比較下他們引用的是否是同一個對象:

s1==s3 //真
s1==s4 //假
s2==s5 //假

使用 == 運算符比較兩個對象時,它會比較內(nèi)存中的地址。

正如您在上面的圖片和示例中看到的,每當(dāng)我們使用new運算符創(chuàng)建字符串時,它都會在 Java 堆中創(chuàng)建一個新的字符串對象,并且不會檢查該對象是否在字符串常量池中。

那么我現(xiàn)在有個問題,如果是字符串拼接的情況,又是怎么樣的呢?

字符串拼接方式

前面講清楚了通過直接用字面量的方式,也就是引號的方式和用new關(guān)鍵字創(chuàng)建字符串,他們創(chuàng)建出的字符串對象在堆中存儲在不同的地方,那么我們現(xiàn)在來看看用+這個運算符拼接會怎么樣。

例子1

public static void test1() {
      // 都是常量,前端編譯期會進行代碼優(yōu)化
      // 通過idea直接看對應(yīng)的反編譯的class文件,會顯示 String s1 = "abc"; 說明做了代碼優(yōu)化
      String s1 = "a" + "b" + "c";  
      String s2 = "abc"; 
  
      // true,有上述可知,s1和s2實際上指向字符串常量池中的同一個值
      System.out.println(s1 == s2); 
  }

常量與常量的拼接結(jié)果在常量池,原理是編譯期優(yōu)化。

例子2

public static void test5() {
    String s1 = "javaEE";
    String s2 = "hadoop";

    String s3 = "javaEEhadoop";
    String s4 = "javaEE" + "hadoop";    
    String s5 = s1 + "hadoop";
    String s6 = "javaEE" + s2;
    String s7 = s1 + s2;

    System.out.println(s3 == s4); // true 編譯期優(yōu)化
    System.out.println(s3 == s5); // false s1是變量,不能編譯期優(yōu)化
    System.out.println(s3 == s6); // false s2是變量,不能編譯期優(yōu)化
    System.out.println(s3 == s7); // false s1、s2都是變量
    System.out.println(s5 == s6); // false s5、s6 不同的對象實例
    System.out.println(s5 == s7); // false s5、s7 不同的對象實例
    System.out.println(s6 == s7); // false s6、s7 不同的對象實例
}

只要其中有一個是變量,結(jié)果就在堆中, 變量拼接的底層原理其實是StringBuilder。

例子3:

public void test6(){
    String s0 = "beijing";
    String s1 = "bei";
    String s2 = "jing";
    String s3 = s1 + s2;
    System.out.println(s0 == s3); // false s3指向?qū)ο髮嵗瑂0指向字符串常量池中的"beijing"
    String s7 = "shanxi";
    final String s4 = "shan";
    final String s5 = "xi";
    String s6 = s4 + s5;
    System.out.println(s6 == s7); // true s4和s5是final修飾的,編譯期就能確定s6的值了
}
  • 不使用final修飾,即為變量。如s3行的s1和s2,會通過new StringBuilder進行拼接
  • 使用final修飾,即為常量。會在編譯器進行代碼優(yōu)化。

妙用String.intern() 方法

前面提到new關(guān)鍵字創(chuàng)建出來的字符串對象以及某些和變量進行拼接不會在字符串常量池中,而是直接在堆中新建了一個對象。這樣不大好,做不到復(fù)用,節(jié)約不了空間。那有什么好辦法呢?intern()就派上用場了,這個非常有用。

intern()方法的作用可以理解為主動將常量池中還沒有的字符串對象放入池中,并返回此對象地址。

String s6 = new String("The Lord of the Rings").intern();

s2==s6 //真
s2==s5 //假

字符串常量池有多大?

關(guān)于字符串常量池究竟有多大,我也說不上來,但是講清楚它底層的數(shù)據(jù)結(jié)構(gòu),也許你就明白了。

字符串常量池是一個固定大小的HashTable,哈希表,默認(rèn)值大小長度是1009。如果放進String PoolString非常多,就會造成Hash沖突嚴(yán)重,從而導(dǎo)致鏈表會很長,而鏈表長了后直接會造成的影響就是當(dāng)調(diào)用String.intern時性能會大幅下降。

使用-XX:StringTablesize可設(shè)置StringTable的長度

  • 在jdk6中StringTable是固定的,就是1009的長度,所以如果常量池中的字符串過多就會導(dǎo)致效率下降很快。StringTable Size設(shè)置沒有要求
  • 在jdk7中,StringTable的長度默認(rèn)值是60013StringTable Size設(shè)置沒有要求

● 在jdk8中,設(shè)置StringTable長度的話,1009是可以設(shè)置的最小值

字符串常量池的優(yōu)缺點

字符串池的優(yōu)點

  • 提高性能。由于 JVM 可以返回對現(xiàn)有字符串對象的引用而不是創(chuàng)建新對象,因此使用字符串池時字符串操作更快。
  • 共享字符串,節(jié)省內(nèi)存。字符串池允許您在不同的變量和對象之間共享字符串,通過避免創(chuàng)建不必要的字符串對象來幫助節(jié)省內(nèi)存。

字符串池的缺點

  • 它有可能導(dǎo)致性能下降。從池中檢索字符串需要搜索池中的所有字符串,這可能比簡單地創(chuàng)建一個新的字符串對象要慢。如果程序創(chuàng)建和丟棄大量字符串,則尤其如此,因為每次使用字符串時都需要搜索字符串池。

總結(jié)

其實在 Java 7 之前,JVM將 Java String Pool 放置在PermGen空間中,它具有固定大小——它不能在運行時擴展,也不符合垃圾回收的條件。在PermGen(而不是堆)中駐留字符串的風(fēng)險是,如果我們駐留太多字符串,我們可能會從 JVM 得到一個OutOfMemory錯誤。從 Java 7 開始,Java String Pool存放在Heap空間,由 JVM進行垃圾回收。這種方法的優(yōu)點是降低了OutOfMemory錯誤的風(fēng)險,因為未引用的字符串將從池中刪除,從而釋放內(nèi)存。

現(xiàn)在通過本文的學(xué)習(xí),你該知道如何更好的創(chuàng)建字符串對象了吧。

到此這篇關(guān)于JAVA中的字符串常量池的文章就介紹到這了,更多相關(guān)java字符串常量池內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • MyBatis反向生成Example類的使用方式

    MyBatis反向生成Example類的使用方式

    今天小編就為大家分享一篇MyBatis反向生成Example類的使用方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • Java上傳視頻實例代碼

    Java上傳視頻實例代碼

    本文通過實例代碼給大家講解了java上傳視頻功能,代碼分為頁面前臺和后臺,工具類,具體實例代碼大家通過本文學(xué)習(xí)吧
    2018-01-01
  • SpringBoot項目啟動時提示程序包不存在和找不到符號的處理方法

    SpringBoot項目啟動時提示程序包不存在和找不到符號的處理方法

    最近接手同事開發(fā)的一個Springboot工作項目,從svn上整體拉取下來后,構(gòu)建完成后,啟動的時候遇到了程序包找不到的情況,所以本文記錄了SpringBoot項目啟動時提示程序包不存在和找不到符號的處理方法,需要的朋友可以參考下
    2024-05-05
  • java 過濾器模式(Filter/Criteria Pattern)詳細(xì)介紹

    java 過濾器模式(Filter/Criteria Pattern)詳細(xì)介紹

    這篇文章主要介紹了java 過濾器模式(Filter/Criteria Pattern)詳細(xì)介紹的相關(guān)資料,需要的朋友可以參考下
    2016-10-10
  • 劍指Offer之Java算法習(xí)題精講二叉樹專題篇下

    劍指Offer之Java算法習(xí)題精講二叉樹專題篇下

    跟著思路走,之后從簡單題入手,反復(fù)去看,做過之后可能會忘記,之后再做一次,記不住就反復(fù)做,反復(fù)尋求思路和規(guī)律,慢慢積累就會發(fā)現(xiàn)質(zhì)的變化
    2022-03-03
  • SpringBoot項目打成War包部署的方法步驟

    SpringBoot項目打成War包部署的方法步驟

    這篇文章主要介紹了springboot項目如何打war包流程的方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12
  • java中類之間的數(shù)據(jù)傳遞方式

    java中類之間的數(shù)據(jù)傳遞方式

    這篇文章主要介紹了java中類之間的數(shù)據(jù)傳遞方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • Java獲取環(huán)境變量(System.getenv)的方法

    Java獲取環(huán)境變量(System.getenv)的方法

    本文主要介紹了Java獲取環(huán)境變量(System.getenv)的方法,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-05-05
  • 在Java8中構(gòu)建Stream流的多種方式詳解

    在Java8中構(gòu)建Stream流的多種方式詳解

    當(dāng)我們處理集合數(shù)據(jù)時,往往需要對其進行各種操作,如過濾、映射、排序、歸約等,在 Java 8 中引入的 Stream 流為我們提供了一種更加簡潔和靈活的方式來處理數(shù)據(jù),本文將介紹如何基于 Stream 構(gòu)建流,為你展示創(chuàng)建和操作流的多種方法
    2023-08-08
  • 基于spring實現(xiàn)websocket實時推送實例

    基于spring實現(xiàn)websocket實時推送實例

    這篇文章主要為大家詳細(xì)介紹了基于spring實現(xiàn)websocket實時推送實例,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-03-03

最新評論

贵定县| 鹤壁市| 镇原县| 武隆县| 米泉市| 芜湖市| 建昌县| 集贤县| 灯塔市| 阿鲁科尔沁旗| 曲松县| 肃宁县| 承德市| 错那县| 昆山市| 隆德县| 龙江县| 宜州市| 交城县| 陕西省| 班戈县| 临汾市| 双流县| 阳城县| 固始县| 筠连县| 富裕县| 太和县| 永嘉县| 晋中市| 黑水县| 泸定县| 固始县| 高安市| 琼海市| 拉孜县| 钟祥市| 铁岭县| 温泉县| 安化县| 内丘县|