今天根據要求對集中訪問控制符做了測試,在子類跨包繼承的權限問題,發現有些矛盾。
代碼說明:父類Father 在packageA中 子類Child01也在packageA中 子類Child02在packageB中
下面上代碼;
1 package packB; 2 import packA.Father; 3 // 本類是Father類不同包的子類 4 public class Child02 extends Father 5 { 6 public static void main(String[] args) { 7 Father father = new Father(); 8 System.out.println(father.public_a); // public修飾的成員,在不同包中子類能訪問 9 // System.out.println(father.protected_b); // protected修飾的成員,在不同包子類中不能訪問 10 // System.out.println(father.default_c); // default修飾(默認)的成員,在不同包子類中不能訪問 11 // System.out.println(father.private_d); // private修飾的成員,在不同包子類中不能訪問 12 13 father.pulic_aa(); // public修飾的方法,在不同包子類中能訪問 14 // father.protected_bb(); // protected修飾的方法,在不同包子類中不能訪問 15 // father.default_cc(); // default修飾(默認)的方法,在同包子類中不能訪問 16 // father.private_dd(); // private修飾的方法,在同包子類中不能訪問 17 18 // 下面是個人對跨包繼承的深入理解,與別人的理解和說法有些矛盾 由於方法的權限和屬性一樣 就不寫了 19 20 // 訪問方式一: 21 Child02 child = new Child02(); 22 child.public_a = 10; 23 child.protected_b = 20; 24 // child.default_c = 30; //報錯 父類該屬性對子類不可見 25 // child.private_d = 30; //報錯 父類該屬性對子類不可見 26 27 } 28 // 訪問方式二: 29 void test(){ 30 public_a = 10; 31 protected_b = 20; 32 // default_c = 30; // 報錯 父類該屬性對子類不可見 33 // private_d = 30; // 報錯 父類該屬性對子類不可見 34 } 35 // 訪問方式三: 36 void test1(){ 37 super.public_a = 10; 38 super.protected_b = 20; 39 // super.default_c = 30; // 報錯 父類該屬性對子類不可見 40 // super.private_d = 30; // 報錯 父類該屬性對子類不可見 41 } 42 43 44 45 46 }
從第7行到第16行,是對在跨包子類中的Father對象進行操作,訪問結果說明只能訪問到 public修飾的屬性和方法。
就是從這里產生了矛盾,因為和之前所了解的內容有出入 故對其進行深入了解。
下面從第20行到第40行是另外的三種訪問方式 和之前了解的權限相匹配;
方式一:是訪問子類對象中從父類繼承的屬性,發現父類中protected修飾的屬性可以被訪問,此時訪問的是子類對象的屬性;
方式二:是訪問子類中從父類繼承的屬性,發現父類中protected修飾的屬性可以被訪問,此時訪問的屬性是子類的屬性;
方式三:通過super來調用父類的屬性,這里會讓人覺得這個肯定是父類調用自身的屬性了;
於是我對代碼進行改造,讓結果變得更明顯:
Father 類
1 package packA; 2 //本類是參考類,用來和child、uncle了來測試 3 public class Father { 4 // 成員變量 5 public int public_a = 1; 6 protected int protected_b = 2; 7 int default_c = 3; 8 private int private_d = 4; 9 // 方法 10 public void pulic_aa(){ 11 12 } 13 protected void protected_bb(){ 14 15 } 16 void default_cc(){ 17 18 } 19 private void private_dd(){ 20 21 } 22 23 public static void main(String[] args) { 24 25 } 26 27 }
Child02類
1 package packB; 2 import packA.Father; 3 // 本類是Father類不同包的子類 4 public class Child02 extends Father 5 { 6 public static void main(String[] args) { 7 Father father = new Father(); 8 System.out.println(father.public_a); // public修飾的成員,在不同包中子類能訪問 9 // System.out.println(father.protected_b); // protected修飾的成員,在不同包子類中不能訪問 10 // System.out.println(father.default_c); // default修飾(默認)的成員,在不同包子類中不能訪問 11 // System.out.println(father.private_d); // private修飾的成員,在不同包子類中不能訪問 12 13 father.pulic_aa(); // public修飾的方法,在不同包子類中能訪問 14 // father.protected_bb(); // protected修飾的方法,在不同包子類中不能訪問 15 // father.default_cc(); // default修飾(默認)的方法,在同包子類中不能訪問 16 // father.private_dd(); // private修飾的方法,在同包子類中不能訪問 17 18 // 下面是個人對跨包繼承的深入理解,與別人的理解和說法有些矛盾 由於方法的權限和屬性一樣 就不寫了 19 20 // 訪問方式一: 21 Child02 child = new Child02(); 22 child.public_a = 10; 23 child.protected_b = 20; 24 // child.default_c = 30; //報錯 父類該屬性對子類不可見 25 // child.private_d = 30; //報錯 父類該屬性對子類不可見 26 child.test(); 27 child.test1(); 28 } 29 // 訪問方式二: 30 void test(){ 31 public_a = 10; 32 protected_b = 20; 33 System.out.println(public_a+"*"+protected_b); 34 System.out.println(super.public_a+"*"+super.protected_b); 35 Father father01 = new Father(); 36 System.out.println(father01.public_a); 37 // default_c = 30; // 報錯 父類該屬性對子類不可見 38 // private_d = 30; // 報錯 父類該屬性對子類不可見 39 } 40 // 訪問方式三: 41 void test1(){ 42 super.public_a = 10; 43 super.protected_b = 20; 44 // super.default_c = 30; // 報錯 父類該屬性對子類不可見 45 // super.private_d = 30; // 報錯 父類該屬性對子類不可見 46 } 47 48 49 50 51 }
輸出結果:
從結果可以明顯的看出通過super方式得到是Child02類的public_a的屬性,並不是Father類的public_a的屬性;
強勢插入一段自己對super的理解,super是子類對父類的一個引用,指向子類從父類繼承下來的屬性,若指向父類中子類沒有繼承的屬性則會報錯,另外如果子類對繼承的屬性進行重寫,則super指向父類的該屬性。
我們可以看看和Father同包的Child01類里面指向沒有繼承的屬性是不是可以:
1 package packA; 2 // 本類是Father類同包的子類 3 public class Child01 extends Father 4 { 5 public static void main(String[] args) { 6 Father father = new Father(); 7 System.out.println(father.public_a); //測試證明 public修飾的成員,在同包子類中能訪問 8 System.out.println(father.protected_b); //測試證明 protected修飾的成員,在同包子類中能訪問 9 System.out.println(father.default_c); //測試證明 default修飾(默認)的成員,在同包子類中能訪問 10 // System.out.println(father.private_d); 測試證明 private修飾的成員,在同包子類中不能訪問 11 12 father.pulic_aa(); //測試證明 public修飾的方法,在同包子類中能訪問 13 father.protected_bb(); //測試證明 protected修飾的方法,在同包子類中能訪問 14 father.default_cc(); //測試證明 default修飾(默認)的方法,在同包子類中能訪問 15 // father.private_dd(); 測試證明 private修飾的方法,在同包子類中不能訪問 16 } 17 void test(){ 18 super.public_a = 10; 19 super.protected_b = 20; 20 super.default_c = 30; 21 // super.private_d = 30; // 報錯 父類該屬性對子類不可見 22 } 23 }
這樣就充分說明了,屬性的繼承和super使用條件,也就是方式三中訪問的屬性其實是Child02類的屬性,也就是說在跨包的子類里面訪問父類的屬性的還是只有public;
同時子類繼承權限因為跨包影響,從pulic,protected和default 變成 pulic和protected;