Java複習之Java深入解析五(包裝器類型的緩存、嵌套類)

1.Java中的八種基本數據類型不是對象,之所以這樣設計,是因爲其使用方便,效率高於對象類型。但是集合類並不支持對基本數據類型的操作。因此就引入了包裝器類。在JDK1.5之後加入了自動拆裝箱機制。裝箱時調用valueOf方法,這是個靜態方法,返回包裝器類型,值爲形參的值。拆箱時調用xxxvalue方法,返回基本數據類型。
包裝器類型參與運算時用到符合賦值運算可能會報錯:

Short sh1=Short.valueOf((short) 1);
Short sh2=2;
//sh1+=sh2;//相當於 sh1=(Short)(sh1+sh2);

第三行會報錯。相加時先拆箱,後提升至int類型,在轉化爲Integer類型。在將Integer類型強轉爲Short類型時出錯。因爲參與運算的類型時int類型,所以將Short類型轉換爲Integer時可以通過編譯。

Integer i1=1;
Integer i2=2;
i1+=i2;
System.out.println(i1);

先拆箱,後運算,再裝箱。
包裝類的緩存:在java中,String和包裝器類型都是有final修飾的。因此,對象一經創建後就不可修改。對此,String類提供了常量池,包裝器類提供了對象的緩存,具體實現是在類中預先創建頻繁使用的包裝類對象。當需要某個包裝類對象時,如果該對象的值在緩存的值的範圍內,就返回包裝類的對象,否則就創建新的並返回。緩存的優點:

  • 當頻繁使用包裝類對象時,可以直接返回緩存類中事先創建好的對象。節省創建對象的時間開銷。因爲包裝類是不可變的,因此,它的對象可以自由共享。

緩存的範圍:

  • 數字類型(Byte、Short、Integer、Long)都是-128~127;
  • Character類:0~127;
  • Boolean類:true和false都有;
  • 浮點類型(Float、Double):沒有緩存值。

Integer i1=127;//自動裝箱,調用Integer.valueOf()方法
Integer i2=127;//不能new,new會在堆上創建新對象。地址一定不一樣。這一點和字符串一樣

  public class Maintest extends Super{
    public static void main(String[] args) {
        Integer i1=127;//自動裝箱,調用Integer.valueOf()方法
        Integer i2=127;//不能new,new會在堆上創建新對象。地址一定不一樣。這一點和字符串一樣
        System.out.println("i1.equals(i2):"+i1.equals(i2));
        System.out.println("i1==i2:"+(i1==i2));
        Integer i3=128;
        Integer i4=128;
        System.out.println("i3.equals(i4):"+i3.equals(i4));
        System.out.println("i3==i4:"+(i3==i4));
    }
}

運行結果爲:

i1.equals(i2):true
i1==i2:true
i3.equals(i4):true
i3==i4:false

i1和i2沒有超過緩存的範圍,因此時同一個對象。i3和i4超過範圍了,因此會創建新對象。
Integer的緩存下限時-127,是固定的。但是上限是可以自己修改的。修改後的值不能小於127。如果小於,那麼修改無效。上限依然是127。
2.數組:在java中,數組也是一種類型,有成員變量和方法。多維數組中的元素爲低緯數組。Java中的數組可以不是矩陣數組。數組一經創建,其長度就不可改變。其內部的length時final修飾的。數組重寫了Object中的clone方法,x.clone()!=x。但是,數組的克隆是淺克隆,僅能保證clone()返回的數組與原數組的地址不同。如果數組中存放的是引用數據類型,那麼複製的數組中的元素依然指向相同的對象。

public class Maintest{
    public static void main(String[] args) {
        Super[] supers=new Super[2];
        supers[0]=new Super();
        supers[1]=new Super();
        Super[] supers1=supers.clone();
        System.out.println("supers1==supers:"+(supers1==supers));
        System.out.println("supers1[1]==supers[1]:"+(supers1[1]==supers[1]));
    }
}

運行結果:

supers1==supers:false//只保證引用的地址不一樣
supers1[1]==supers[1]:true//但內部的元素的引用都一樣。

高維數組複製時,內部元素的引用指向的對象(低緯數組)一樣。
數組輸出時,除了char類型以外,其餘都是調用了Object中的toString方法,輸出地址。
3.接口:接口中的方法都是abstract 修飾的,目的就是要類去實現它,實現多態調用。因此接口中不能聲明static修飾的方法,可以聲明static修飾的變量。如果有static修飾變量,那麼變量最好在聲明處賦初始值。當兩個接口中存在同名變量的時候,訪問時要加限定名稱。接口可以實現多繼承其他的接口,接口和接口之間不存在實現關係。綜上:

  • 繼承關係可以存在類和類、接口和接口(多繼承)之間。
  • 實現只能出現在類與接口之間。

4.嵌套類型:
靜態成員類:在類中定義了一個用static修飾的類,該類可以訪問外圍的private成員變量,但是如果是非靜態的,需要通過對象名來引用。

public class Maintest {
    private String string="內部類的成員變量";
    public static class staticclass{
        public static void main(String[] args) {
            System.out.println(new Maintest().string);//如果在類的內部,是可以直接通過對象名來訪問私有成員變量的
        }
    }
}

靜態類不依賴於外圍類的實例對象而存在。因爲是靜態,可以通過外圍類的類名來訪問。在訪問權限夠的情況下,靜態類可以繼承任何類,任何類也都可以繼承靜態類。
內部成員類:內部成員類必須通過對象來訪問,而靜態成員變量又是不需要對象可以直接通過類名來訪問。如果內部成員類中有靜態,會存在這樣的矛盾。因此內部成員類中不能聲明靜態(變量、方法、類、靜態初始化塊)。但是可以有final修飾的變量。
內部類綁定外圍類對象:創建內部類對象時,編譯器會爲內部類隱式聲明一個final修飾的外圍類引用,調用構造時,系統會傳參(外圍類對象)將該引用指向外圍類對象。
局部類:局部類是在方法、構造器、初始化塊中聲明的類,不能使用訪問權限修飾符來訪問,也不能使用static修飾。

上一篇
---The End---
...
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章