protected這個修飾符,各大參考書都會這樣說:訪問權限為類內,包內和子類,因此在父類中定義的方法和成員變量如果為protected修飾的,是可以在不同包中的子類進行訪問的,示例代碼如下:
1 package cn.tedu.object.a; 2 3 public class A { 4 5 protected void m(){ 6 System.out.println("A m~~~"); 7 } 8 9 }
1 package cn.tedu.object.b; 2 3 import cn.tedu.object.a.A; 4 5 public class B extends A { 6 void callM() { 7 m(); 8 super.m(); 9 B b = new B(); 10 b.m(); 11 } 12 }
如上代碼所示,class B繼承了class A,但是兩個類位於a、b兩個不同的包中,此時class B可以直接訪問class A中的protected修飾的方法。一共有三種方法訪問:
第一種為第7行,直接調用;
第二種為第8行,加super關鍵字;其實前兩種是等效的。
第三種為第9、10行,實例化一個對象進行調用。
那么問題來了,如果說在b包中新建一個class C,並且有如下代碼,會報錯嗎?
1 package cn.tedu.object.b; 2 3 import cn.tedu.object.a.A; 4 5 public class C extends A { 6 7 void callM() { 8 m(); 9 super.m(); 10 B b = new B(); 11 b.m(); //The method m() from type A is not visible 12 } 13 14 }
會報錯!那為什么會報錯呢?
因為b.m()這種調用屬於子類對象調用,並不是子類調用。
這個是非常需要引起注意的。因此,當創建子類對象調用父類的protected成員變量時,必須要注意:子類對象和子類是對應的!
通過這個例子其實也可以看出來,當一個包外子類繼承保護成員時,該成員在這個子類內實際上變為私有。
事實上,除了以上三種調用父類protected成員變量的方法外,其余都是會報錯的!
包括用超類實例去訪問。代碼如下:
1 package cn.tedu.object.b; 2 3 import cn.tedu.object.a.A; 4 5 public class B extends A { 6 7 void callM() { 8 A a=new A(); 9 a.m(); //The method m() from type A is not visible 10 } 11 12 }
同樣的,會報錯!因此,可以得到結論:
包外子類有權訪問超類成員,它指子類繼承該成員,然而,這並不意味着包外子類能夠使用超類實例的引用訪問該成員。
