为什么我不能在包外面使用受保护的构造函数来处理这段代码:
package code;
public class Example{
protected Example(){}
...
}
Check.java
package test;
public class Check extends Example {
void m1() {
Example ex=new Example(); //compilation error
}
}
修改
编译错误:
构造函数Example()不可见
答案 0 :(得分: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,然后访问不是 允许的。类实例可以访问受保护的构造函数 创建表达式(不声明匿名类)或a 方法引用表达式仅来自其中的包 已定义。
例如,这不会编译
public class Example extends Exception {
void method() {
Exception e = new Exception("Hello", null, false, false);
}
}
但是这样做
public class Example extends Exception {
Example() {
super("Hello", null, false, false);
}
}
这样做
public class Example {
void method() {
Exception e = new Exception("Hello", null, false, false) {};
}
}
所以规则很明确,但我不能说我理解他们背后的原因!
答案 1 :(得分:4)
protected modifier仅在包中和包外的子类中使用。使用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
}
}
示例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
}
}
答案 2 :(得分:3)
实际上你已经使用了Example的protected构造函数,因为Check有一个隐式构造函数和隐式的Example构造函数调用:
public Check() {
super();
}