注:protected 既包括protected 域,又包括protected 方法,以下統稱爲protected!
看到protected,我們想到的可能是:protected 既提供包訪問權限,同時對繼承自該類的所有子類(或子類的下級子類)提供訪問權限 !這句話是沒有錯的,不管子類與父類是否位於同一包中,子類的對象都可以訪問protected成員,因爲這些成員已經帶到子類中來了!
本文之所以要對protected單獨作出討論,是因爲protected並不是上面所提到的那麼簡單,還有許多情況是我們沒碰到過的,這其中包含着陷阱,一不小心,就會觸發異常!
我們可以把對protected成員的訪問分成兩種情況,一種是創建子類對象,並且用該子類對象來訪問protected成員,這個在本文第一段已提到 !
這裏,我們來討論另一種特殊的情況:當子類與父類位於不同包中,在子類中創建父類對象,並用此父類對象來訪問protected成員時,就會拋出一個異常!正如以下程序中看到的:
package A; //父類所在的包
public class Father {
protected int i = 5; //父類中的protected 域
protected void test() { //父類中的protected方法
System.out.println(this.i);
}
}
==================================================================================
package B; //子類與父類位於不同的包中
import A.Father; //導入父類
public class Son extends Father {
public static void main(String[] args) {
Father f = new Father(); //創建父類對象
System.out.println(f.i); //此處會拋出錯誤
f.test(); //此處也會拋出同樣的錯誤
}
}
我們看到上面的程序會拋出兩個錯誤,原因就在於:當子類與父類位於不同包中時,父類中的protected成員,對於父類本身是不可訪問的,只有子類對象纔可以訪問!上面的程序我們可以把會出錯的那兩句改成:
Son t = new Son();
System.out.println(t.i);
t.test();
這樣就不會出錯!
=======================================================================
在上面的例子上,再做一點修改,把Father 中的test()改爲protected static void test()
然後在Son類中創建Father f = new Father();
此時,f 仍然不能訪問f.i,但是f卻可以訪問test(),即用f.test()時,不會出錯,原因是:
因爲test() 是static Method , static method 調用 不需要通過對象的實例,跟寫成 Son.test() 是一樣的效果 !
===========================總結======================================
當父類與子類位於同一包中時,不管是子類對象還是父類對象都可以訪問protected,但是它們的意義是不一樣的;對於子類對象,之所以可以訪問是因爲:子類從父類繼承了protected成員,理所當然可以訪問;父類對象(在子類中創建的)之所以可以訪問是因爲protected提供了包訪問極限!
當父類與子類位於不同包中時,protected成員就只能通過子類對象來訪問(因爲protected對於子類是可見的),而父類對象不再可以訪問!不過,可以訪問static 成員(因爲protected的包訪問極限已失去作用)