为什么我不能在包外使用受保护的构造函数?

Abh*_*h28 27 java protected access-modifiers

为什么我不能在包外面使用受保护的构造函数来获取这段代码:

package code;
public class Example{
    protected Example(){}
    ...
}
Run Code Online (Sandbox Code Playgroud)

Check.java

package test;
public class Check extends Example {
  void m1() {
     Example ex=new Example(); //compilation error
  }
}
Run Code Online (Sandbox Code Playgroud)
  1. 为什么即使我扩展了课程,我也会得到错误?请解释

编辑:

编译错误:

构造函数Example()不可见

Pau*_*ton 12

通常protected意味着只能访问同一个包中的子类或类.但是,以下是JLS中构造函数的规则:

6.6.2.2.对受保护构造函数的限定访问权限

设C是声明受保护构造函数的类,并让S成为其声明中使用受保护构造函数的最内层类.然后:

如果访问是通过超类构造函数调用super(...)或限定的超类构造函数调用E.super(...),其中E是主表达式,则允许访问.

如果访问是通过匿名类实例创建表达式new C(...){...},或者是限定的匿名类实例创建表达式E.new C(...){...},其中E是一个主表达式,然后允许访问.

如果访问是通过简单的类实例创建表达式new C(...),或者是限定类实例创建表达式E.new C(...),其中E是主表达式,或者是方法引用表达式C: :new,其中C是ClassType,然后不允许访问.受保护的构造函数可以由类实例创建表达式(不声明匿名类)或方法引用表达式访问,只能从定义它的包中访问.

例如,这不编译

public class Example extends Exception {

    void method() {
        Exception e = new Exception("Hello", null, false, false);
    }
}
Run Code Online (Sandbox Code Playgroud)

但确实如此

public class Example extends Exception {

    Example() {
        super("Hello", null, false, false);
    }
}
Run Code Online (Sandbox Code Playgroud)

这样做

public class Example {

    void method() {
        Exception e = new Exception("Hello", null, false, false) {};
    }
}
Run Code Online (Sandbox Code Playgroud)

所以规则很明确,但我不能说我理解他们背后的原因!


kit*_*ttu 7

protected 修饰符仅在包内和包外的子类中使用。当您使用Example ex=new Example();它创建对象时,默认情况下将调用父类构造函数。

作为受保护的父类构造函数,您会收到编译时错误。您需要根据 JSL 6.6.2.2 调用受保护的构造函数,如下例 2 所示。

package Super;

public class SuperConstructorCall {

    protected SuperConstructorCall() {
    }

}

package Child;

import Super.SuperConstructorCall;

public class ChildCall extends SuperConstructorCall
{

    public static void main(String[] args) {

        SuperConstructorCall s = new SuperConstructorCall(); // Compile time error saying SuperConstructorCall() has protected access in SuperConstructorCall
    }
}
Run Code Online (Sandbox Code Playgroud)

示例 2 符合JLS 6.6.2.2

package Super;

    public class SuperConstructorCall {

    protected SuperConstructorCall() {
    }

}

package Child;

import Super.SuperConstructorCall;

public class ChildCall extends SuperConstructorCall
{

    public static void main(String[] args) {

        SuperConstructorCall s = new SuperConstructorCall(){}; // This will work as the access is by an anonymous class instance creation expression 
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 答案仍然不令人信服,我知道它会调用受保护的父类 consturtor ie> Example() 但正如我们所知,如果我们扩展该类,我们可以在包外使用受保护的修饰符,那么为什么这在这里不起作用在构造函数的情况下? (3认同)