java有四種訪問權限,它們各自的范圍如下圖所示
當下列訪問修飾符修飾字段和方法時:
private
任意位置的子類不可以訪問從父類繼承的private字段和方法。這里所說的訪問包括通過super關鍵字訪問。
任意位置的對象不能通過“.”訪問對象的字段和方法。
public
任意位置的子類可以訪問從父類繼承的public字段和屬性。
任意位置的對象可以通過“.”訪問字段和屬性。
default
當子類與父類在同一包下時,子類可以訪問從父類繼承的default權限的字段和方法。
當創建該對象的類與該對象所屬的類在同一包下時,可以通過“.”訪問對象的字段和方法。
對於父類中的private、default權限的一些方法和字段,子類在一定程度上不能訪問它們,通過super訪問也不行。但子類對象初始化時,不僅子類中聲明的成員變量分配了內存,父類的成員變量也都分配了內存,只是父類的成員不能被子類訪問罷了。但是我們可以通過子類從父類繼承的某些方法來操作這部分不能訪問的變量。
protected
上面的三種訪問權限都很好理解,protected的描述卻不是那么清晰。
1)、當子類訪問從父類繼承的成員或方法時,不管是否在同一包都可以,在這個情況下同public權限。
測試: p2包下的C2繼承p1包下的C1,C2在類中可以直接訪問繼承來的方法
package p1; public class C1 { protected void fun() {} }
package p2; import p1.C1; public class C2 extends C1{ public void test() { fun(); } }
編譯正確:
2)當訪對象要用“.”訪問對象的protected字段(方法)時,分兩種情況討論
i 如果訪問的這個方法(字段)是該對象的類自己定義的,且類型是protected。要求對象所在類與對象所屬類在同一包下。
package p1; public class C1 { protected void fun() {} }
package p2; import p1.C1; public class C2{ public void test() { new C1().fun(); } }
編譯報錯:(因為對象所在類p2.C2與對象所屬類p1.C1不在同一包下)
將C2放在包p1下后:
package p1; public class C2{ public void test() { new C1().fun(); } }
編譯正確:
ii 如果對象訪問的這個方法是該對象的類繼承而來的。要求對象所在類與該方法(字段)被最初被定義的類在同一包下。其實 i 是 ii 的特殊情況。
測試: C2繼承C1的protected方法fun(),C3調用C2繼承的fun()方法,C3與C2在同一包下,編譯報錯。
package p1; public class C1 { protected void fun() {} }
package p2; import p1.C1; public class C2 extends C1{
}
package p2; public class C3{ public void test() { C2 c2 = new C2(); c2.fun(); } }
編譯結果:
測試:將上面的示例改變一下,C3放到C1的包下,編譯通過。
package p1; import p2.C2; public class C3{ public void test() { C2 c2 = new C2(); c2.fun(); } }
編譯結果:
protected總結:當在子類內部訪問從父類繼承而來的protected字段(方法)時,沒有包限制。當對象通過“.”訪問字段(方法)時,被protected修飾的方法(字段)的可見范圍是,該字段(方法)被定義的類所在的包。
本文個人編寫,水平有限,如有錯誤,懇請指出,歡迎討論分享。