今天根据要求对集中访问控制符做了测试,在子类跨包继承的权限问题,发现有些矛盾。
代码说明:父类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;