繼承

  • 覆蓋方法

超類中有些方法對于子類并不適用,為此子類需要覆蓋超類的方法。

子類和超類方法簽名(方法名+參數列表)相同,則為覆蓋方法。

覆蓋方法的返回類型(可協(xié)變返回類型)

返回類型不是方法簽名的一部分,覆蓋方法時要保證返回類型的兼容性,允許子類覆蓋方法返回類型是超類返回類型的子類型。

內聯(lián)

一個方法沒有被覆蓋并且很短,編譯器會對其進行優(yōu)化,避免動態(tài)綁定帶來的系統(tǒng)開銷。

  • 重載方法

方法名稱相同,參數列表不相同的方法為重載方法,一個類中就可以存在這樣的關系,而覆蓋是子類方法和超類方法之間的關系。


  • 私有域的訪問問題

盡管每個子類對象都擁有超類的私有域,但是在子類的方法中不能直接訪問這個私有域,必須通過訪問器訪問。

例如:

Employee.java

public class Employee{
    private double salary;
    ...
    
    public LocalDate getHireDay(){
      return hireDay;
   }
}

Manager.java

public class Manager extends Employee{
   public double getSalary(){
      double baseSalary = super.getSalary();
      return baseSalary + bonus;
   }
   
   /* error:子類方法不能訪問超類的私有域
   public double getSalary(){
      double baseSalary = salary;
      return baseSalary + bonus;
   }
   */
   
}

  • super與this

this:返回對象的引用;

super:返回的不是對象引用,不能將super賦值給一個對象變量,只是一個指示編譯器調用超類方法的特殊關鍵字。


  • 方法調用

  1. 假設存在x.f(param),x為C類的一個對象。則會先篩選C類中所有名為f的方法和C類的超類的public的f方法(C不能直接訪問超類的私有域和私有方法);

  2. 編譯器查看參數類型,若找到匹配的,找不到可以使用類型轉換,則直接選擇這個方法(重載過程);

  3. 若出現(xiàn)private、static、final方法,則直接是靜態(tài)綁定,因為這些都是本類才能調用的方法,不依賴于對象。而調用方法依賴于隱式參數的實際類型,則是動態(tài)綁定;

  4. 運用了動態(tài)綁定時,首先在實際類型的類里找方法,若找不到再去實際類型的超類里面找。

方法表

為了減小查找方法的開銷,虛擬機使用了方法表;

假設D是C的子類,則調用d.f(param)方法時,首先去D的方法表中找;

若查找不到,則到C的隱式參數方法表中查找(依賴于隱式參數的方法,即非private、sstatic、final)。


  • 超類與子類方法可見性

子類覆蓋超類方法時,子類方法可見性不能低于超類方法可見性,如超類使用了public,則子類也要使用public。因為如果不這么做,c引用了子類D的一個對象d,調用c.fun(param)(可見性為public),而D類對fun的可見性為private,則必然會出錯。


  • 阻止繼承——使用final

希望阻止人們利用某個類定義子類,不允許被拓展的類被稱為final類。

final類中所有的方法也默認被聲明為final(即使沒有顯式寫出來),但域并沒有被默認聲明為final。

子類不能覆蓋final方法,因此final方法也是靜態(tài)綁定的。

將類或方法聲明為final的主要目的

防止子類覆寫方法,確保他們在子類中語義不變。


  • 強制類型轉換

將一個子類引用賦給超類變量不需要強制轉換;
將一個超類引用賦給子類變量需要類型轉換。

例如如下超類賦給子類(Manager extends Empolyee):

Employee[] employees = new Employee[3];
Manager managerOld = new Manager();
//子類引用賦值給超類變量不需要強制類型轉換
employees[0] = managerOld;     
employees[1] = new Employee();

/**
*盡管employee[0]引用的實際類型是Manager
*但編譯器并不知道
*表面還是超類引用
*賦值給子類變量需要強制類型轉換
*/
Manager managerNew = (Manager)employees[0]; 

/**
*養(yǎng)成良好習慣,提前判斷引用的實際類型,防止向下類型轉換的“謊報”錯誤
*/
if(employee[1].instanceof Manager){
    //由于employees[1]實際類型是Employee,因此不會執(zhí)行
    Manager boss = employees[1];        
}

  • 特點

向下類型轉換時需要使用強制類型轉換;

只能在繼承層次內進行強制類型轉換;

將超類轉換為子類前,需要使用instanceof檢查實際類型;

如果只是需要子類的覆蓋方法,可以不轉換,因為動態(tài)綁定可以準確調用到子類的覆蓋方法;

只有需要使用子類特定方法或域時才需要強制類型轉換;


  • 受保護訪問

任何被聲明為private的域和方法都不能被其他類訪問,包括子類;

使用受訪問保護的protected讓子類可以訪問超類某個域,但是例如Manager可以訪問Manager對象某個protected域,但是不能訪問Employee對象的protected域。

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容