java類繼承總結一 父類類型與子類類型之間的轉化問題

java類繼承總結一 父類類型與子類類型之間的轉化問題 

本文將通過一個實例描述父類類型與子類類型之間的轉化問題,這個很特殊的問題常常會導致一些潛在的危險,讓你整整一個晚上都在調試程序以解決一個讓人抓狂的java.lang.ArrayStoreException異常。

1. 子類數組的引用可以裝換爲超類數組的引用

 2. 子類的引用child可以轉換爲父類的引用parent(這裏假設parent是父類對象,child是子類對象),但卻不可以通過 parent調用child的特有方法

 

class Employee{
  
protected String name;
  
protected long salary;
  
public Employee(String aName){
    
this.name = aName;
  }

  
  
public void setSalary(long aSalary){
    
this.salary = aSalary;
  }

  
  
public long getSalary(){
    
return this.salary;
  }

}


class Manager extends Employee{
  
protected long bonus;
  
public Manager(String aName){
    
super(aName);
  }

  
  
public void setBonus(long aBonus){
    
this.bonus = aBonus;
  }

  
  
public long getSalary(){
    
return super.getSalary()+this.bonus;
  }

}


public static void main(String[] args) {
    
//注意,這時managers 和employees 引用的是同一個數組
    Manager[] managers = new Manager[10];
    Employee[] employees 
= managers;
    
//(a)注意,下面三條語句是可以通過的,但運行時會拋出異常
    employees[0= new Employee("Abel"); //運行時此處拋出java.lang.ArrayStoreException異常
    managers[0].setSalary(1000);
    managers[
0].setBonus(500);
    
//(b)這樣的語句編譯和運行都沒有問題
    employees[0= new Manager("Abel");
    employees[
0].setSalary(1000);
    managers[
0].setSalary(1000);
    managers[
0].setBonus(500);
}

總結:
1. 在java中,對象變量是多態的,一個employee既可以引用Employee類型的實例,也可以引用子類Manager類型的實例,但一個manager不能引用一個Employee類型的實例,例如:
   (1) Employee e = new Manager("Abel") 是合法的
   (2)Manager   m = new Employee("Abel") 是不合法的
  原因很容易理解,manager與employee是is-a的關係,任何一個manager都是一個emplpyee,如(1)所示,一個Employee類型的引用e可以引用Manager類型的實例,這意味着可以通過e使用Manager中任何繼承自Employee的方法(注意,e不能使用Manager的特有方法,如e.setBonus(1000)是不合法的),Employee e = new Manager("Abel")的潛臺詞就是說,e從Employee的角度描述Manager,e就是一個Employee,不管e引用的是什麼,編譯器就把它當一個Employee來看。

2. 對於上面(a)的代碼,不能運行是可以理解的, employees[0]雖然在聲明時是Employee類型,但Employee[] employees = managers;規定了employees[i]指向的必須是Manager類型的實例,因此employees[0] = new Employee("Abel"); 這條語句必然會引發異常。
   (a)處的代碼employees[0] = new Employee("Abel");可以通過編譯似乎也情有可原,因爲employees聲明的類型是Employee[], 那麼employees[0]自然可以接受一個Employee類型的引用,但實際上

   Employee[] employees = managers;賦值的過程中又規定了employees接受的必須是Manager類型,從上面的例子可以看出,運行的時候會做這樣的檢查,但編譯的時候不會檢查的這麼深入,只會檢查變量的聲明類型,看來java編譯器還不夠智能啊 :)

3. 在實際編程的過程中,使用對象變量的多態性時一定要注意(尤其是使用數組的時候),否則編譯通過,但運行報錯,這個錯誤很可能讓你調試一個晚上才能找出問題所在!!

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