常量池

1:常量池指的是在編譯期被確定,並被保存在已編譯的.class文件中的一些數據。除了包含代碼中所定義的各種基本類型(如int、long等等)和對象型(如String及數組)的常量值(final)還包含一些以文本形式出現的符號引用:
◆類和接口的全限定名;
◆字段的名稱和描述符;
◆方法和名稱和描述符
2:基本類型和基本類型的包裝類。基本類型有:byteshortcharintlongboolean。基本類型的包裝類分別是:ByteShortCharacterIntegerLongBoolean。注意區分大小寫。二者的區別是:基本類型體現在程序中是普通變量,基本類型的包裝類是類,體現在程序中是引用變量。因此二者在內存中的存儲位置不同:基本類型存儲在棧中,而基本類型包裝類存儲在堆中。上邊提到的這些包裝類都實現了常量池技術,String類型也實現了常量池技術
例子:

public class Test1 {
             public static void main(String[] args) {
        objPoolTest();
    }

    public static void objPoolTest() {
        int i = 40;
        int i0 = 40;
        Integer i1 = 40;
        Integer i2 = 40;
        Integer i3 = 0;
        Integer i4 = new Integer(40);
        Integer i5 = new Integer(40);
        Integer i6 = new Integer(0);
        Double d1=1.0;
        Double d2=1.0;

        System. out.println( "i=i0\t" + (i == i0));                      true
        System. out.println( "i1=i2\t" + (i1 == i2));                    true
        System. out.println( "i1=i2+i3\t" + (i1 == i2 + i3));            true
        System. out.println( "i4=i5\t" + (i4 == i5));                    false
        System. out.println( "i4=i5+i6\t" + (i4 == i5 + i6));            true
        System. out.println( "d1=d2\t" + (d1==d2));                      false

        System. out.println();
    }
}
結果分析:
1: ii0均是普通類型(int)的變量,所以數據直接存儲在棧中,而棧有一個很重要的特性:棧中的數據可以共享。當我們定義了int i = 40;,再定義int i0 = 40;這時候會自動檢查棧中是否有40這個數據,如果有,i0會直接指向i40,不會再添加一個新的40
2: i1i2均是引用類型,在棧中存儲指針,因爲Integer是包裝類。由於Integer包裝類實現了常量池技術,因此i1i240均是從常量池中獲取的,均指向同一個地址,因此i1=12。(是直接賦值所以可以再常量池中找
3: java的數學運算都是在棧中進行的Java會自動對i1、i2進行拆箱操作轉化成整型,因此i1在數值上等於i2+i3。(理解:做運算時轉換成了數值的運算)
4: .i4i5均是引用類型,在棧中存儲指針,因爲Integer是包裝類。但是由於他們各自都是new出來的,因此不再從常量池尋找數據,而是從堆中各自new一個對象,然後各自保存指向對象的指針,所以i4i5不相等,因爲他們所存指針不同,所指向對象不同。
5:同理3 轉換成int型數值操作
6: d1d2均是引用類型,在棧中存儲指針,因爲Double是包裝類。但Double包裝類沒有實現常量池技術,因此Doubled1=1.0;相當於Double d1=new Double(1.0);,是從堆new一個對象,d2同理。因此d1d2存放的指針不同,指向的對象不同,所以不相等。
總結:
1:以上提到的幾種基本類型包裝類均實現了常量池技術,但他們維護的常量僅僅是【-128至127這個範圍內的常量,如果常量值超過這個範圍,就會從堆中創建對象,不再從常量池中取。比如,把上邊例子改成Integer i1 = 400; Integer i2 = 400;,很明顯超過了127,無法從常量池獲取常量,就要從堆中new新的Integer對象,這時i1i2就不相等了。
2: String類型也實現了常量池技術,但是稍微有點不同。String型是先檢測常量池中有沒有對應字符串,如果有,則取出來;如果沒有,則把當前的添加進去。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章