回覆列表
  • 1 # 小紅的甜心

     1)父類建構函式

      java中當呼叫某個類的構造方法的時候,系統總會呼叫父類的非靜態初始化塊進行初始化,這個呼叫是隱式的,而且父類的靜態初始化程式碼

      塊總是會被執行,接著呼叫父類的一個或者多個構造器執行初始化,這個呼叫也可以透過super進行顯式呼叫。

      例如:

      父類程式碼如下:

      public class Creature {//父類

      {//非靜態程式碼塊

      System.out.println("creature的非靜態程式碼塊正在執行");

      }

      public Creature(){

      System.out.println("creature的建構函式正在執行");

      }

      }

      子類程式碼如下:

      public class Animal extends Creature {

      {

      System.out.println("animal的初始化程式碼塊正在執行");

      }

      public Animal(){

      System.out.println("animal的構造方法正在執行");

      }

      public static void main(String[] args){

      Animal a = new Animal() ;

      }

      }

      則執行程式後的結果為:

      creature的非靜態程式碼塊正在執行

      creature的建構函式正在執行

      animal的初始化程式碼塊正在執行

      animal的構造方法正在執行

      從結果中可以看出:呼叫某個類的構造方法的時候總是會先執行父類的非靜態程式碼塊,然後執行父類的構造方法,最後才是執行當前類的。

      非靜態程式碼塊和構造方法。執行過程中有先後順序。

      若果想要顯式呼叫父類的構造方法則可以使用super(),來呼叫,但是super關鍵字和this關鍵字都必須放在構造放的第一行,而且只能使用第一個。

      注:super用於顯式呼叫父類的構造器,this可以顯式呼叫本類中的過載的構造器。

      2)訪問子類物件的例項變數

      子類的方法可以訪問父類中的例項變數,這是因為子類繼承父類就會獲得父類中的成員變數和方法,但是父類方法不能訪問子類的例項變數,因為父類根本無法知道它將被哪個類繼承,它的子類將會增加怎麼樣的成員變數。但是,在極端的情況下,父類也可以訪問子類中的變數。

      例如:

      父類程式碼如下:

      public class Base {//父類

      private int i = 2 ;

      public Base(){

      this.display() ;

      }

      public void display(){

      System.out.println(i);

      }

      }

      子類中程式碼如下:

      public class Derived extends Base {

      private int i = 22 ;

      public Derived(){

      i = 222 ;

      }

      public void display(){

      System.out.println(i);

      }

      }

      測試用例如下:

      public class Test {

      public static void main(String[] args) {

      new Derived() ;

      }

      }

      程式的執行結果為:

      0

      呼叫new Derived() ;建立Derived

      例項的時候,系統會為Derived物件分配記憶體空間,Derived會有兩個i例項變數,會分配兩個空間來儲存i的值。分配完空間以後i的值為0

      ,如果有引用型別則引用型別的值為null。接下來程式在執行Derived的構造器之前會執行Base的構造器,表面上看Base的構造器中只有

      一行程式碼,但是在父類中定義i的時候執行的初始值2,因此經過編譯之後,該構造方法中應該包含如下兩行程式碼:

      i =2 ;

      this.display() ;

      程式先將Base中的i賦值為2,然後執行display方法。此處有一個關鍵字this,this到底代表誰呢?表面上看this代表的是Base的當前例項,但是實際上程式碼是放在Derived的構造器中的,所以this最終代表的是Derived的當前例項(編譯型別是Base而實際引用一個Derived物件),所以如果在父類的構造方法中直接輸出System.out.println(this.i) ;則輸出的結果為2。但是呼叫this.display()方法,此時呼叫的是子類中重寫的display方法,輸出的變數i也是子類中的i,但是此時子類中的變數i還沒有賦值,所以輸出結果為0。

      為了詳細的看清楚this變數到底代表什麼例項,我們將Base的構造方法修改如下:

      public Base(){

      System.out.println(this.i);

      System.out.println(this.getClass());

      this.display() ;

      }

      再次執行程式,結果為:

      2

      class edu.qichao.chapter2.Derived

      0

      可以看到this代表的是Derived的例項,但是編譯的時候型別為Base,所以輸出this.i的值為2。

      3)呼叫被子類重寫的方法

      預設情況下,子類可以呼叫父類的方法,但是父類不能呼叫子類的方法,因為父類不知道它將被哪個子類繼承,也不知道子類將增加怎麼

      樣的方法。

      例如:

      父類Animal的程式碼如下:

      public class Animal {

      private String desc ;

      public Animal(){

      this.desc = getDesc() ;

      }

      public String getDesc(){

      return "Animal" ;

      }

      public String toString(){

      return desc ;

      }

      }

      子類Wolf的程式碼如下:

      public class Wolf extends Animal {

      private String name ;

      private double weight ;

      public Wolf(String name , double weight){

      this.name = name ;

      this.weight = weight ;

      }

      public String getDesc(){

      return "Wolf[name=" + name + ",weight=" + weight + "]" ;

      }

      public static void main(String[] args){

      System.out.println(new Wolf("灰太狼" , 3));

      }

      }

      程式的執行結果為:

      Wolf[name=null,weight=0.0]

      在main方法中透過new Wolf("灰太狼" , 3);來建立一個Wolf的例項,子類會隱式呼叫父類的構造方法,在父類構造方法中初始化desc變數this.desc = getDesc() ;此處需要注意this變數,雖然這個this放在Animal的構造放中,但是是在Wolf的構造方法中呼叫父類的構造方法,所以this編譯時型別為Animal,執行時型別為Wolf,此處呼叫的getDesc方法是子類Wolf的方法,但是子類中的name和weight變數都沒有初始化,預設為null和0.0.所以程式的最終結果為:Wolf[name=null,weight=0.0]

      4)繼承成員變數和成員方法的區別

      java中隊成員變數的繼承和成員方法的繼承是不同的。

      例如:

      父類程式碼如下:

      public class Base {

      int count = 2 ;

      public void display(){

      System.out.println(this.count);

      }

      }

      子類程式碼如下:

      public class Derived extends Base {

      int count = 20 ;

      @Override

      public void display(){

      System.out.println(this.count);

      }

      }

      測試用例如下:

      public class Test {

      public static void main(String[] args) {

      Base b = new Base() ;

      System.out.println(b.count);

      b.display() ;

      System.out.println("-----------------");

      Derived d = new Derived() ;

      System.out.println(d.count);

      d.display() ;

      System.out.println("-----------------");

      Base bd = new Derived() ;

      System.out.println(bd.count);

      bd.display() ;

      System.out.println("-----------------");

      Base d2b = d ;

      System.out.println(d2b.count);

      }

      }

      程式執行結果為:

      2

      2

      -----------------

      20

      20

      -----------------

      2

      20

      -----------------

      2

  • 中秋節和大豐收的關聯?
  • 微博權重為什麼有人那麼高?