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

时间:2013-12-05 16:11:40

标签: java

我已经浏览了很多网站,其中解释了java中的访问说明符,例如java papersjava's access specifiers以及许多其他堆栈溢出问题,例如here

所有这些人解释说,受保护的成员可以被任何子类(也可以是包外的子类)访问,并且可以由包级别类访问。

在尝试受保护的成员时,我发现我无法从包外的子类访问受保护的成员。

检查以下代码。受保护成员的公共类:

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(p.i);//the field ProVars.i is not visible(Compilation Error)
                p.foo();//the method foo() from the type ProVars is not visible

    }
}

感谢任何解释。

11 个答案:

答案 0 :(得分:9)

您尝试使用它们,就好像它们是public一样。它们不是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并查看会发生什么。

答案 1 :(得分:8)

即使在派生类中,您也只能从至少属于您自己类型的限定符中访问受保护字段。

AnotherClass内,您可以访问new AnotherClass().i,但不能访问new ProVars().i

答案 2 :(得分:3)

如果你的主要方法不是静态的,那就好了。静态方法不关心继承,因此你的“扩展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();
}

}

答案 3 :(得分:2)

您需要更改线路     ProVars p = new ProVars(); 成     AnotherClass p = new AnotherClass();

否则,您仍在创建ProVars类型的对象,并且编译器将无法实现AnotherClass和ProVars之间的继承(这会导致编译错误)。

答案 4 :(得分:1)

main()

中使用子类
public class AnotherClass extends ProVars {

    public static void main(String[] args) {
    AnotherClass p = new AnotherClass();
    System.out.println(p.i);
            p.foo();

}

}

答案 5 :(得分:1)

对Java受受保护访问的混淆是由错误的教程引起的:https://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html

即使阅读了几次本教程也没有任何线索,为什么您不能从另一个包的另一个对象访问 Alpha 类的受保护成员。类 AlphaSub Alpha 的子类。

实际上,Java语言规范对此进行了说明,例如在JLS 8中:

6.6.2有关受保护访问的详细信息

可以从外部访问对象的受保护成员或构造函数 仅由负责该代码的代码声明的包 该对象的实现

答案 6 :(得分:0)

当我们说它可以从子类获得时,我们的意思是它可用于子类代码。但是在你的例子中,你从外面调用受保护的方法。

因此,虽然您的示例不起作用,但这应该

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();
}



}

答案 7 :(得分:0)

访问变量的代码在静态方法中 - 静态方法不直接是继承受保护字段的对象的一部分。

尝试将代码移动到AnotherClass类中的方法,然后从静态方法中调用该方法。

答案 8 :(得分:0)

在一个包中的类中声明受保护的成员由子类继承,该子类可以位于该类的相同包中,也可以位于不同的包中。

**这里继承的意思是超类的同一受保护成员在子类中可用,使用父引用和点运算符来访问如下所示会抛出编译错误。

ProVars p = new ProVars(); System.out.println(p.i); //错误:我在父

中具有受保护的访问权限

只需在你的子类中使用它:

的System.out.println(ⅰ); //工作正常,因为子类继承了protected                           超级成员,无论他们是否在                           相同或不同的包装。

答案 9 :(得分:0)

两个条件必须满足才能访问超类中的受保护字段

1)受保护,并且只能在类的子类中才能在包点之外访问

第二个总是被忽略的

2)它们是由访问它们的代码实现的对象的字段。

请参考此JavaDocs https://docs.oracle.com/javase/specs/jls/se11/html/jls-6.html#jls-6.6.2

答案 10 :(得分:0)

这是 受保护的 访问修饰符的工作方式:

package one;

public class Fruit {

    protected void sayHello() {
        System.out.println("hello");
    }
}

package two;
import one.Fruit;

public class Banana extends Fruit{

   new Banana().sayHello;   // hello
   new Fruit().sayHello;    // compile error

}