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

时间:2015-04-09 05:07:11

标签: java protected access-modifiers

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

package code;
public class Example{
    protected Example(){}
    ...
}

Check.java

package test;
public class Check extends Example {
  void m1() {
     Example ex=new Example(); //compilation error
  }
}
  1. 即使我延长了课程,为什么我会收到错误? 请解释
  2. 修改

    编译错误:

      

    构造函数Example()不可见

3 个答案:

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