Java進基礎階-4-對象內存、存活、回收+構造函數

目錄

1、Java內存分配

2、方法棧

3、一個對象的內存

4、構造函數

4.1、繼承與構造函數

4.2、如果我們沒調用super()函數會怎樣?

4.3、this()函數

5、對象的存活

6、釋放對象的3種方式


1、Java內存分配

棧: 局部變量中的基本數據類型直接存入棧中

        局部變量中對對象的引用(指針)存在棧中

堆: 成員變量全部存在堆中(包括:基本數據類型、對象引用和對象引用的實例)

      【成員變量屬於類,類最終都是要被new 出來的,所以成員變量全部存儲在堆中】

public class Test_Subject {

    //成員變量
    private String  hello;  //存儲於堆中
    
    //成員變量
    private Person  per=new Person();   //per是對Person對象的引用,存儲於堆中,new出來的Person對象也存儲於堆中
    
    class  Person{
        //實例變量
        String name;  //name存儲在Person對象所屬的堆空間中
    }
    
    public void showAge(int a){   //參數a也是局部變量 存儲於棧中

        //局部變量
        int age=23;               //age存儲在棧中
        //p也是局部變量
        Person p=new Person();    //p存儲在棧, new Person()這個對象存儲在堆中
    }
}

2、方法棧

存放方法的棧中保存了方法的狀態,包括執行到了那一行代碼,還有所有的局部變量。

下面是各個方法互相調用時,它們存放於棧中的狀態。(正在執行的方法都會被放在棧頂。)

3、一個對象的內存

一個對象的內存=所有實例變量使用的內存+對象本身的開銷(一般是16字節)

對象本身的開銷=一個指向對象類的引用+垃圾回收信息+同步信息

另外一般內存的使用都會被填充爲8字節(64位計算機中的機器字)的倍數。不夠8的倍數,填充爲8的倍數。

      Integer對象內存(24字節)= 對象開銷(16字節)+int(4字節)+填充字節(4字節)

      Date對象內存(32字節)=對象開銷(16字節)+3*int(12字節)+填充字節(4字節)

     Counter對象內存(32字節)=對象開銷(16)+String(8)+int(4)+填充字節(4)、

     Node內存(40)=對象開銷(16)+額外開銷(8)+Item的引用(8)+Node的引用(8) 

因爲Node是一個非靜態的內部類,所以它持有對外部類的引用,額外開銷就是來之於對外部類的引用。

對對象的引用,其實就是一個機器地址,一個機器地址所需內存一般是8字節(64位架構的計算機,32爲架構的是4字節)

4、構造函數

  1. 構造函數會在new的時候被調用,它快於賦值給引用它的變量的賦值過程。
  2. 構造函數不會有返回類型。
  3. 構造函數不會被繼承。
  4. 構造函數只有在你沒有寫任何構造函數的時候,纔會給你創建一個沒有參數的構造函數。
  5. 如果你寫了有參數的構造函數,如果你還想要有一個沒有參數的構造函數,就必須自己寫出來,編譯器不會給你創建。

4.1、繼承與構造函數

  • 一個子類佔用的內存大小除了自身的對象開銷+所有實例變量的大小以外,還要加上父類的內存。
  • 當你在new一個子類的時候,第一件事會調用父類的構造函數,而且一定會調用(因爲完整的對象也需要完整的父類,你想要調用父類的所有方法和狀態,就必須構造父類)。
  • 在構造函數中,通過super()函數來調用父類的構造函數。
  • 抽象的類也有構造函數,雖然你不能new一個抽象類,但是當你在new它的子類的時候會調用抽象類的構造函數。

4.2、如果我們沒調用super()函數會怎樣?

編譯器會幫我們加上super()的調用。添加的方式會有兩種:

1、如果你沒有寫構造函數,它會默認會給你添加一個無參的構造函數,並添加上super()函數。

2、如果你有構造函數,那麼它會對每個重載版本的構造函數上添加上super()函數。

注意:編譯器添加的一定是沒有參數的構造函數和super()函數,假如父類有多個版本的構造函數,那麼只有無參的版本會被調用。

對於super()的調用必須是構造函數的第一條語句。

public class Test_Constructor {

    static class Animal{
        public String name;
        public final int age=1;
        public Animal() {
            System.out.println("你好");
        }
    }

    static class  Dog extends Animal{
        public Dog() {
            System.out.println("汪汪");
        }
        public Dog(String name) {
            System.out.println("汪汪");
        }
    }

    public static void main(String[] args) {
        Dog a=new Dog();
        Dog b=new Dog("小花");
    }
}

//輸出結果
你好
汪汪
你好
汪汪

4.3、this()函數

  • this()函數是從某個構造函數調用同一個類的另外一個構造函數,只需要改變this()的參數就可以調用;
  • this()函數只能在構造函數中,且只能是第一條語句;
  • super()與this()不能兼得,只能出現一個。

5、對象的存活

public class Test_Object {

    static class Person {
        String name; // 實例變量的壽命與Person對象相同,如果該對象存活,該變量也會存活
    }

    public void showAge(int a) {
        int age = 23; // 局部變量只會存活在該方法調用的時候,當該方法執行完畢,那麼該變量消失
        showName();
    }
    /**
     * 1、當showAge方法在調用ShowName方法的時候,showAge方法以及它的變量age都是存活的,只是不處於棧頂;
     * 2、這個時候的age變量是無法被使用的,只有在棧頂的showName函數中的name變量可以被使用;
     * 3、當這兩個函數都執行完成之後,showAge函數和它的變量纔會消失。
     */
    public void showName() {
        String name = "zhangSan";
        System.out.println("name");
    }

    public static void main(String[] args) {
        /**
         *  Perosn對象的生命週期取決於它的引用變量p,只要p一直引用着Person對象,那麼該對象就會一直存活。
         */
        Person p=new Person(); 
    }
}

6、釋放對象的3種方式

public class Test_Clear_Object {

    class Person {
        String name;
    }

    /**
     * 方式一:將對象的引用變量放在方法中,這樣在方法執行完成之後,p1引用變量就會消失,
     *        這樣對Person對象的引用就沒有了,該對象就可以被GC回收了。
     */
    public void clear1(){
        Person p1=new Person();
    }

    /**
     * 方式二:引用被賦值到其他對象上,這樣new的第一個Person對象就沒有了引用,可以被回收。
     */
    public void clear2(){
        Person p2=new Person();
        p2=new Person();
    }
    /**
     * 方式三:直接將引用置空,這樣Person對象就沒被引用了。
     */
    public void clear3(){
        Person p3=new Person();
        p3=null;
    }
}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

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