尝试在位于其他包中的子类中使用受保护的构造函数时,Eclipse 显示错误

Eclipse shows an error when trying to use protected constructor in a subclass located in other package

你好 Whosebug 社区 :-]

我是新会员,首先感谢您提供的非常有用的建议和更正。由于我是法国人,如果我的英语不完美,请原谅我。

这是我的问题:我目前正在学习 Java 编程语言,我想测试一些继承的东西。如果我理解正确,声明为 protected 的字段可以被 classes 访问,这些 classes 与声明受保护字段的 class 位于同一包中,并且它的所有子classes,是否在同一个包中。

所以,我做了这 4 个 classes 来测试这个。我有一个名为 "package1" 的包,其中包含 classes A 和 C。我还有一个名为 "package 2" 的包,其中包含 classes A2 和 C,其中 A2 扩展了 A。两个 C class 的代码完全一样,只是它们所在的包 changes.They 没有扩展 A.

在 A class 中,我声明了一些具有不同访问属性的成员,尤其是声明为 protected 可见性的构造函数。这是四个 classes 的代码。

package1,class一个:

package package1;

public class A {

    public int a;
    protected int b;
    private int c;
    int d;

    protected static int h = 30;

    protected void aff(){
        System.out.println(h);
    }

    protected A(){
        a = 1;
        b = 2;
        c = 3;
        d = 4;
    }

    public static void main(String[] args) {
        // TODO Auto-generated method stub

    }

}

包 1,class C:

package package1;

public class C {

    public C(){
        super();
    }

    public void app(){
        A obj = new A(); //////// OK
    }

    public static void main(String[] args) {
        // TODO Auto-generated method stub


        A obj = new A(); //////// OK
        obj.aff(); //////// OK

        System.out.println(obj.a);

    }

}

package2,class A2(扩展 A):

package package2;
import package1.A;

public class A2 extends A{

    public int x;

    A2(){
        super();
    }


    public void app(){
        A obj = new A(); //////// ERROR
    }

    public static void main(String[] args) {
        // TODO Auto-generated method stub


        A obj = new A(); //////// ERROR

        A2 obj2 = new A2();
        obj2.aff(); //////// OK



    }

}

package2,class C:

package package2;
import package1.A;

public class C {


    public C(){
        super();
    }

    public void app(){

        A obj = new A(); //////// ERROR
    }

    public static void main(String[] args) {
        // TODO Auto-generated method stub


        A obj = new A(); //////// ERROR
        obj.aff(); //////// ERROR

        System.out.println(obj.a);

    }

}

对于 package2 中的 C class,代码 A obj = new A(); 会抛出错误,但对于 package1 中的 C class 则不会。这是正确的,因为构造函数被声明为 protected 并且 package2 中的 C 不是 A 的子 class,而 C 在 package1 中。至此,我明白了。

我遇到问题的地方是 class A2 中的代码 A obj = new A();:无论写在哪里,它都会抛出错误 The constructor A() is not visible... As class构造函数声明为protected,为什么我不能在A2 class中实例化A类型的对象?

当我将 A 构造函数声明为 public 时,它工作正常。此外,如果我按原样将 A2 class 放在 package1 中,它也可以工作。似乎只有当 subclass 位于同一个包中并且 A 构造函数被声明为 protected 时,才能在 A 的 subclass 中实例化 A 对象。

但是,如您所见,如果我首先实例化一个 A2 对象,然后调用 class A protected aff() 方法,它就可以工作并且遵守受保护的规则。

有人对此错误有解释吗?在其subclass中实例化一个superclass的对象时,这个subclass是否总是和它的super[=61=位于同一个包中],如果superclass 构造函数声明为 protected ?如果是这样,为什么会这样?

或者这是否必须处理构造函数未被 subclasses 继承的事实?但我不知道为什么会这样...

非常感谢您花时间阅读和回答:-]

参见Java Language Specification

A protected member or constructor of an object may be accessed from outside the package in which it is declared only by code that is responsible for the implementation of that object.

您的classA2负责实施A new A()呼唤。

意思是,它不负责A的一个实例的实现,但是负责A2的一个实例的实现.

这很有趣,所以让我试着总结一下。见 JLS#6.6.1

protected 可以限定 class.

的构造函数或成员

"member" 包括 field/method (static/instance),嵌套 class/interface (static/inner)

class A {
    protected int f
    protected void m(){}
    protected class X{}
    protected interface Y{}

首先,要访问受保护的 constructor/member,封闭的 class(例如 A)必须是可访问的。假设是这样,那么 --

--包裹内--

受保护的构造函数或成员可在同一包内的任何位置访问。

--包裹外--

受保护的构造函数只能在子class 构造函数中访问,可以作为super() 调用,也可以作为匿名class 实例化。

受保护的静态 field/method,嵌套的 class/interface 可在子 class 体内的任何地方访问。


受保护实例field/method更复杂--

  • protected "m" 定义在 class A
  • obj.m 在 class B 中访问(在 A 的包外)
  • obj 的类型是 C

仅当 B 是 A 的子class,并且 C 是 B 的子class 或 C 是​​ B 时,才授予访问权限 obj.m

super.m 总是允许的;但是,尚不清楚 JLS 如何解决这个问题。看来访问应该和this.m一样对待,所以允许访问。