摘要:方法就是擴充常量池的一個方法當一個實例調用方法時,會查找當前常量池中是否已有相同的字符串常量,如果有就返回其引用,如果沒有就在常量池中添加對應的字符串,并返回對應字符串常量的引用。
常量池:在編譯被確定,并保存在.class文件中的一些數據。jvm為每個類維護一個常量池,常量池就是該類型所用到的常量的一個有序集合。在程序執行的時候,常量池存儲在方法區中。存在于.class文件中的常量池,在運行期被jvm裝載,并且可以擴充。
String.intern()方法就是擴充常量池的一個方法
當一個string實例調用intern方法時,會查找當前常量池中是否已有相同的字符串常量,如果有就返回其引用,如果沒有就在常量池中添加對應的字符串,并返回對應字符串常量的引用。
String str0 = "hello world!"; String str1 = new String("hello world!"); String str2 = "hello" + " world!"; //可確定字符串常量池中有3個string字符串常量 "hello" "world!" "hello world!" Stirng str3 = "hello" + new String("world!"); //常量池1(hello) + 堆2(world + hello world),這是由于String的不可變性所致 System.out.println(str0 == str1); //false System.out.println(str0 == str2); //true System.out.println(str0 == str3); //false str1.intern(); str11 = str1.intern(); //常量池中存在該常量,直接返回其引用 System.out.println(str1 == str11); //false str1在堆中,str11在常量池中 System.out.println(str0 == str11); //true
補充:String的不可變性
//String的實例一旦生成就不會再改變,比如 String str = "he" + "is" + "string";
其中有5個字符串常量:"he", "is", "string", "heis", "heisstring"
因為Stirng 的不可變性產生了很多的臨時變量,所以這種情況一般使用StringBuffer或者StringBuider。
jvm優化
jvm會對“+”號連接的字符串常量優化為連接后的值
String str1 = "aaa"; String str2 = "bbb"; String str3 = "aaabbb"; String str4 = "aaa" + "bbb"; String str5 = "aaa" + str2; System.out.println(str3 == str4); //true System.out.println(str3 == str5); //false
對于str5,由于字符串的連接有引用存在,而引用的值在編譯期是無法確定的,只有在程序運行的時候動態分配并將其連接后的新引用返回,其實,str3指向常量池,而str5指向堆,所以 str3 == str5 為false
String ab1 = "aaabbb"; final String b = "bbb"; String ab2 = "aaa" + b; System.out.println(ab1 == ab2); //true
final修飾string就可以確保此時b的值不能被改變,所以jvm也可以對其進行優化。所以歸納一句話為:當String連接符兩邊是不能被改變的,那在編譯時jvm就可以進行優化。final使得b只能指向“bbb”,而“bbb”又是在常量區中(常量區中的常量不能被改變),所以b是不能被改變的,如果上例去掉final,那么b就可以指向其他的地方,表明b是可以被改變的,所以jvm在編譯時不進行優化。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/64760.html
摘要:注意運行時常量池存在于方法區中。一個在堆中,一個在字符串常量池中。注意,是把這個對象添加到字符串常量池。內存中有一個基本類型封裝類的常量池。需要注意的是,和這兩個類并沒有對應的常量池。 在寫之前我們先來看幾個問題,假如你對這些問題已經很懂了的話,那大可不用看這篇文章,如果不大懂的話,那么可以看看我的想法。 問題1: public static void main(String[] ar...
作為最基礎的引用數據類型,Java 設計者為 String 提供了字符串常量池以提高其性能,那么字符串常量池的具體原理是什么,我們帶著以下三個問題,去理解字符串常量池: 字符串常量池的設計意圖是什么? 字符串常量池在哪里? 如何操作字符串常量池? 字符串常量池的設計思想 字符串的分配,和其他的對象分配一樣,耗費高昂的時間與空間代價,作為最基礎的數據類型,大量頻繁的創建字符串,極大程度地影響程...
摘要:那方法區里都存著什么呢先拋結論靜態變量常量類信息構造方法接口定義運行時常量池存在方法區中。動態常量池運行時常量池是方法區的一部分,是一塊內存區域。文件常量池將在類加載后進入方法區的運行時常量池中存放。 一、方法區與永久代 這兩個是非常容易混淆的概念,永久代的對象放在方法區中,就會想當然地認為,方法區就等同于持久代的內存區域。事實上兩者是這樣的關系: 《Java虛擬機規范》只是規定了有方...
摘要:為了減少在中創建的字符串的數量,字符串類維護了一個字符串常量池。但是當執行了方法后,將指向字符串常量池中的那個字符串常量。由于和都是字符串常量池中的字面量的引用,所以。究其原因,是因為常量池要保存的是已確定的字面量值。 String,是Java中除了基本數據類型以外,最為重要的一個類型了。很多人會認為他比較簡單。但是和String有關的面試題有很多,下面我隨便找兩道面試題,看看你能不能...
摘要:常量池探秘每個文件編譯為文件后,都將產生當前類獨有的常量池,我們稱之為靜態常量池。文件中的常量池包含兩部分字面值和符號引用。方法的調用成員變量的訪問最終都是通過運行時常量池來查找具體地址的。其中,表示將一個常量加載到操作數棧。 java中講的常量池,通常指的是運行時常量池,它是方法區的一部分,一個jvm實例只有一個運行常量池,各線程間共享該運行常量池。 java內存模型中將內存分為堆和...
閱讀 660·2021-11-11 16:55
閱讀 2165·2021-11-11 16:55
閱讀 1956·2021-11-11 16:55
閱讀 2347·2021-10-25 09:46
閱讀 1608·2021-09-22 15:20
閱讀 2291·2021-09-10 10:51
閱讀 1711·2021-08-25 09:38
閱讀 2623·2019-08-30 12:48