繁体   English   中英

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

[英]Accessing a protected variable from a subclass outside package

我浏览了很多网站,这些网站解释了 java 中的访问说明符,例如java 论文java 的访问说明符以及许多其他 stackoverflow 问题,例如这里

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

在对受保护成员进行试验时,我发现我无法从 package 之外的子类访问受保护成员。

检查下面的代码。 具有受保护成员的公共 class:

package com.One;

    public class ProVars {

    protected int i = 900;

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

}

不同 package 中的另一个公共 class 试图访问受保护的成员:

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

    }
}

任何解释表示赞赏。

你试图使用它们,就好像它们是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 ,看看会发生什么。

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

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

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

}

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

甚至多次阅读教程也没有提供线索,为什么您不能从另一个包的另一个对象访问Alpha类对象的受保护成员,其类AlphaSubAlpha的子类。

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

6.6.2 受保护访问的详细信息

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

您需要更改行ProVars p = new ProVars(); 进入AnotherClass p = new AnotherClass();

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

在您的main()使用子类:

public class AnotherClass extends ProVars {

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

}

}

当我们说它对子类可用时,我们的意思是它对子类代码可用。 但是在您的示例中,您是从外部调用 protected 方法。

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

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



}

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

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

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

**这里继承是指在子类中可以使用超类的相同受保护成员,使用父引用和点运算符访问如下将引发编译错误。

ProVars p = new ProVars();
System.out.println(p.i);// error: i has protected access in parent

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

System.out.println(i); // works fine, since subclass inherit the protected 
                          member of super class no matter whether they are in 
                          same or different package.

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

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

第二个总是被忽略

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

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

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

package a;

public class Fruit {
  protected int i = 5;
  protected void sayHello() {
    System.out.println("hello Fruit");
  }
}

现在像这样导入上面的内容:

package b;
import a.Fruit;

public class Banana extends Fruit {
  public static void main(String[] args) {

    Banana banana = new Banana();
    System.out.println(banana.i);   // 5
    banana.sayHello();              // hello Fruit

    Fruit fruit = new Fruit();
    System.out.println(fruit.i);    // compile error
    fruit.sayHello();               // compile error

    Fruit fb = new Banana();
    System.out.println(fb.i);       // compile error
    fb.sayHello();                  // compile error
  }
}

您必须使用 inheritance 并且在第二种 package 方法中您必须使用 system.Out.Println(this.Protected);

在主要方法中使用创建 object 像 Demopackage obj = new Demopackage(); 对象保护

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM