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)
编辑:
编译错误:
构造函数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)
所以规则很明确,但我不能说我理解他们背后的原因!
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)