【Java_基礎】java中的常量池


1.java常量池的介紹

java中的常量池,通常指的是運行時常量池,它是方法區的一部分,一個jvm實例只有一個運行常量池,各線程間共享該運行常量池。

java常量池簡介:java常量池中保存了一份在編譯期間就已確定的數據。它里面包括final常量的值(包括成員常量、局部常量和引用常量)、以及對象字面量的值。

在編譯期間,每當給常量賦值它就會去檢測常量池中是否存在該值,若存在直接返回該值的地址給常量,若不存在則先在常量池中創建該值,再返回該值的地址給常量。因此常量池中不可能出現相等的數據。

2.final常量

一切經final關鍵字修飾的變量均為常量,final常量必須在定義時就賦初值,否則編譯不通過。

3.對象字面量

對象字面量是指直接以一常量給對象賦值,而不是在堆空間new出一個對象實例。

常見的兩種對象字面量:基本類型的包裝類對象字面量、String對象字面量。

3.1基本類型的包裝類對象字面量

java中基本類型的包裝類大都實現了常量池技術,即Byte,Short,Integer,Long,Character,Boolean。這5種包裝類默認創建了數值[-128,127]的相應類型的緩存數據,但是超出此范圍仍然會去創建新的對象。 兩種浮點數類型的包裝類Float,Double並沒有實現常量池技術。

包裝類型Integer與常量池

Integer i1 = 40;
Integer i2 = 40;
Integer i3 = 0;
Integer i4 = new Integer(40);
Integer i5 = new Integer(40);
Integer i6 = new Integer(0);

System.out.println("i1=i2   " + (i1 == i2));
System.out.println("i1=i2+i3   " + (i1 == i2 + i3));
System.out.println("i1=i4   " + (i1 == i4));
System.out.println("i4=i5   " + (i4 == i5));
System.out.println("i4=i5+i6   " + (i4 == i5 + i6));  
System.out.println("40=i5+i6   " + (40 == i5 + i6));


i1=i2   true
i1=i2+i3   true
i1=i4   false
i4=i5   false
i4=i5+i6   true
40=i5+i6   true

解釋:

  • Integer i1=40;直接以字面量給對象賦值,它會先去檢查常量池中是否存在該值,若存在直接返回該值的地址,若不存在則現在常量池中創建該值,再返回該值的地址。
  • Integer i1 = new Integer(40);這種情況會在堆空間創建新的對象。
  • 語句i4 == i5 + i6,因為+這個操作符不適用於Integer對象,首先i5和i6進行自動拆箱操作,進行數值相加,即i4 == 40。然后Integer對象無法與數值進行直接比較,所以i4自動拆箱轉為int值40,最終這條語句轉為40 == 40進行數值比較。

3.2String對象字面量

String str1 = "abcd";
String str2 = new String("abcd");
System.out.println(str1==str2);//false

String str1 = "str";
String str2 = "ing";
String str3 = "str" + "ing";
String str4 = str1 + str2;
System.out.println("string" == "str" + "ing");// true
System.out.println(str3 == str4);//false

String str5 = "string";
System.out.println(str3 == str5);//true

解釋:

  • 引用str1指向常量池中字符串"abcd"的地址,是在常量池中拿對象,new String("abcd")是直接在堆內存空間創建一個新的對象。只要使用new方法,便需要創建新的對象。
  • 連接表達式 +,只有使用引號包含文本的方式創建的String對象之間使用“+”連接產生的新對象才會被加入常量池中。
  • 對於字符串變量的“+”連接表達式,它所產生的新對象都不會被加入字符串池中,其屬於在運行時創建的字符串,具有獨立的內存地址,所以不引用自同一String對象。

(3)String.intern()方法強制將字符串放入常量池中

public static void main(String[] args) {
  String s1 = new String("計算機");
  String s2 = s1.intern();
  String s3 = "計算機";
  System.out.println("s1 == s2? " + (s1 == s2));
  System.out.println("s3 == s2? " + (s3 == s2));
}

s1 == s2? false
s3 == s2? true

解釋:String的intern()方法會查找在常量池中是否存在一份equal相等的字符串,如果有則返回該字符串的引用,如果沒有則添加自己的字符串進入常量池。

注意:final常量必須在定義時就賦初值,但對象字面量可以先定義后賦值。

4. 常量池的好處

常量池是為了避免頻繁的創建和銷毀對象而影響系統性能,實現了常量池中的內容由對象共享。例如字符串常量池,在編譯階段就把所有的字符串文字放到一個常量池中。

  • 節省內存空間:常量池中所有相同的字符串常量被合並,只占用一個空間。
  • 節省運行時間:比較字符串時,==比equals()快。對於兩個引用變量,只用==判斷引用是否相等,也就可以判斷實際值是否相等。

注:==號比較基本數據類型是值比較,但比較引用類型則是引用所指向的地址比較。

參考的博文:java常量池技術


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM