从包外的子类访问受保护的变量
我已经浏览了很多网站,这些网站解释了java中的访问说明符 ,例如java论文 , java的访问说明符 ,以及许多其他类似的stackoverflow问题。
所有这些人解释说,受保护的成员可以被任何子类(也可以是包外的子类)访问,并且可以由包级别类访问。
在试验受保护的成员时,我发现我无法从包外的子类访问受保护的成员。
检查下面的代码。 受保护成员的公共类:
package com.One; public class ProVars { protected int i = 900; protected void foo() { System.out.println("foo"); } }
尝试访问受保护成员的不同包中的另一个公共类:
package com.Two; import com.One.ProVars; public class AnotherClass extends ProVars { public static void main(String[] args) { ProVars p = new ProVars(); System.out.println(pi);//the field ProVars.i is not visible(Compilation Error) p.foo();//the method foo() from the type ProVars is not visible } }
任何解释都表示赞赏。
你试图像使用它们一样使用它们。 他们不public
,他们受到protected
。
例
ProVars p = new ProVars(); p.foo(); // This will throw an error because foo() is not public.
对于子类使用protected
方法或变量的正确用法是:
public class MyClass extends ProVars { public MyClass() { System.out.println(i); // I can access it like this. foo(); // And this. } }
为什么这样做?
因为你inherited
了这个类。 这意味着你已经拥有了它的所有方法和变量。 现在,因为您的方法和变量protected
,所以它也意味着可以从subclass
访问它。 尝试将它们声明为private
,看看会发生什么。
即使在派生类中,您也只能从至少属于您自己类型的限定符访问受保护字段。
在AnotherClass
,您可以访问new AnotherClass().i
,但不能访问new AnotherClass().i
。
如果你的主要方法不是静态的,那就好了。 静态方法不关心inheritance,因此你的“扩展ProVars”不起作用。 另一方面,这应该工作:
public class AnotherClass extends ProVars { public void accessProtected() { System.out.println(this.i); this.foo(); } public static void main(String[] args) { AnotherClass p = new AnotherClass(); p.accessProtected(); } }
你需要更改ProVars p = new ProVars();
进入AnotherClass p = new AnotherClass();
否则,您仍在创建ProVars类型的对象,并且编译器将无法实现AnotherClass和ProVars之间的inheritance(这会导致编译错误)。
在main()
使用子类:
public class AnotherClass extends ProVars { public static void main(String[] args) { AnotherClass p = new AnotherClass(); System.out.println(pi); p.foo(); } }
当我们说它可以从子类中获得时,我们的意思是它可用于子类代码。 但在您的示例中,您从外部调用受保护的方法。
因此,虽然您的示例不起作用,但这应该是
package com.Two; import com.One.ProVars; public class AnotherClass extends ProVars { public static void main(String[] args) { ProVars p = new ProVars(); p.test(); } public test() { System.out.println(this.i);) this.foo(); } }
访问变量的代码在静态方法中 – 静态方法不直接是inheritance受保护字段的对象的一部分。
尝试将代码移动到AnotherClass类中的方法,然后从静态方法调用该方法。
在一个包中的类中声明受保护的成员由子类inheritance,子类可以位于类的相同包中,也可以位于不同的包中。
**这里inheritance意味着同类的超类的受保护成员在子类中可用,使用父引用和点运算符来访问下面将抛出编译错误。
ProVars p = new ProVars(); System.out.println(pi); //错误:我在父级中具有受保护的访问权限
只需在你的子类中使用它:
的System.out.println(ⅰ); //工作正常,因为子类inheritance了超类的受保护成员,无论它们是在相同还是不同的包中。
与Java 保护访问的混淆是由错误的教程引起的: https : //docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html
甚至几次阅读教程并没有提供线索,为什么你不能从另一个包的另一个对象访问类Alpha对象的受保护成员,其类AlphaSub是Alpha的子类。
实际上,Java语言规范解释了这一点,例如在JLS 8中:
6.6.2受保护访问的详细信息
受保护的成员或对象的构造函数可以从包外部访问,只能通过负责实现该对象的代码来声明它。