簡體   English   中英

字符串池行為

[英]String Pool behavior

我讀了關於Java的字符串池的這個問題並理解了字符串池的基本概念,但仍然不理解這種行為。

第一:如果您直接分配值,則它可以工作,並且s1和s2都引用池中的同一對象

String s1 = "a" + "bc";
String s2 = "ab" + "c";
System.out.println("s1 == s2? " + (s1 == s2));

但是如果我改變字符串s1 + =“d”,那么池應該有一個字符串對象“abcd”? 那么當我更改s2 + =“d”時,它應該在池中找到字符串對象“abcd”,並將對象分配給s2? 但它沒有,它們不會被引用到同一個對象。 這是為什么?

String s1 = "abc";
String s2 = "abc";
System.out.println("s1 == s2? " + (s1 == s2));

s1 += "d";                  
s2 += "d";
System.out.println("s1 == s2? " + (s1 == s2));

當您在字符串上調用String.intern()時,可以保證字符串是池化的。

String s1 = "abcd".intern();
String s2 = "abc";
s2 += "d";
s2 = s2.intern();
s1 == s2 // returns true

當編譯器看到一個常量時,它足夠智能來優化和匯集字符串文字,即:

String s1 = "abcd";
String s2 = "abcd";
s1 == s2 // returns true

Java語言規范聲明:

每個字符串文字都是類String(第4.3.3節)的實例(第4.3.1節,第12.5節)的引用(第4.3節)。 String對象具有常量值。 字符串文字 - 或者更一般地說,作為常量表達式(第15.28節)的值的字符串 - 是“實例化”以便使用String.intern方法共享唯一實例。

所以在s2 += "d"的情況下,編譯器並不像你那樣聰明,只是匯集了"d"

我不確定這一點,所以這幾乎是猜測,但我懷疑在第一個例子中可能會有一些編譯器技巧(它是內聯的,非常明顯的是發生了什么),但它並不夠聰明。它在第二個例子中(它不是那么明顯)。

如果我是對的,要么編譯器看到"a" + "bc"並且只是在編譯時將其壓縮為"abc"或者它看到兩行並匯集字符串,因為它意識到它們將被使用。 我打賭前者..

並非所有字符串都必須匯總。

請參閱String #intern()的文檔。 最后一行指出:

所有文字字符串和字符串值常量表達式都是實體。

您的+=示例既不是文字字符串也不是字符串值常量表達式,因此它不會放在字符串池中。

編譯器可以執行常量求值,但不能在修改值的情況下執行

請嘗試關注並查看如果從任一變量中刪除final會發生什么。

final String s1 = "abc";
final String s2 = "abc";
System.out.println("s1 == s2? " + (s1 == s2));

String s3 = s1 + "d";                  
String s4 = s2 + "d";
System.out.println("s3 == s4? " + (s3 == s4));

這是我的猜測:

String s1 =“a”+“bc”; 字符串s2 =“ab”+“c”;

我認為這是編譯時間,這些是確定生成相同的字符串,因此只有一個對象。

但是當你向他們兩個添加“d”時,這是針對兩個字符串單獨完成的(因為它是在實時完成的,可能會有異常中斷它等等,所以它不能預先做它)所以它不會自動使它們引用一個對象。

我想這里發生的是:1。對於String s1 =“a”+“bc”; 字符串s2 =“ab”+“c”; Java編譯器足夠聰明,知道s1和s2的文字值是相同的,因此編譯器將它們指向字符串池中的相同文字值

  1. 對於s1 + =“d”;
    s2 + =“d”;

編譯器無法知道s1和s2是否會最終成為相同的值。在運行時,除非調用String.intern(),否則jvm將不檢查字符串文字池以查看該值是否已存在。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM