从包外的子类访问受保护的变量

我已经浏览了很多网站,这些网站解释了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对象的受保护成员,其类AlphaSubAlpha的子类。

实际上,Java语言规范解释了这一点,例如在JLS 8中:

6.6.2受保护访问的详细信息

受保护的成员或对象的构造函数可以从包外部访问,只能通过负责实现该对象的代码来声明它。