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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/29530199/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 15:26:17  来源:igfitidea点击:

Why can't I use protected constructors outside the package?

javaprotectedaccess-modifiers

提问by Abhilash28

Why can't I use protected constructors outside the package for this piece of code:

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

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

Check.java

检查.java

package test;
public class Check extends Example {
  void m1() {
     Example ex=new Example(); //compilation error
  }
}
  1. Why do i get the error even though i have extended the class? Please explain
  1. 为什么即使我扩展了课程,我也会收到错误消息?请解释

EDIT:

编辑:

Compilation error:

编译错误:

The constructor Example() is not visible

构造函数 Example() 不可见

采纳答案by kittu

protected modifier is used only with in the package and in sub-classes outside the package. When you create a object using Example ex=new Example();it will call parent class constructor by default.

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

As parent class constructor being protected you are getting a compile time error. You need to call the protected constructor according to JSL 6.6.2.2 as shown below in example 2.

作为受保护的父类构造函数,您会收到编译时错误。您需要根据 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
    }
}

Example 2 conforming to JLS 6.6.2.2:

示例 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 
    }
}

回答by Paul Boddington

Usually protectedmeans only accessible to subclasses or classes in the same package. However here are the rules for constructors from the JLS:

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

6.6.2.2. Qualified Access to a protected Constructor

Let C be the class in which a protected constructor is declared and let S be the innermost class in whose declaration the use of the protected constructor occurs. Then:

If the access is by a superclass constructor invocation super(...), or a qualified superclass constructor invocation E.super(...), where E is a Primary expression, then the access is permitted.

If the access is by an anonymous class instance creation expression new C(...){...}, or a qualified anonymous class instance creation expression E.new C(...){...}, where E is a Primary expression, then the access is permitted.

If the access is by a simple class instance creation expression new C(...), or a qualified class instance creation expression E.new C(...), where E is a Primary expression, or a method reference expression C :: new, where C is a ClassType, then the access is not permitted. A protected constructor can be accessed by a class instance creation expression (that does not declare an anonymous class) or a method reference expression only from within the package in which it is defined.

6.6.2.2. 对受保护构造函数的合格访问

设 C 是声明了受保护构造函数的类,让 S 是最里面的类,在其声明中使用了受保护的构造函数。然后:

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

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

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

As an example, this does not compile

例如,这不会编译

public class Example extends Exception {

    void method() {
        Exception e = new Exception("Hello", null, false, false);
    }
}

but this does

但这确实

public class Example extends Exception {

    Example() {
        super("Hello", null, false, false);
    }
}

and so does this

这也是

public class Example {

    void method() {
        Exception e = new Exception("Hello", null, false, false) {};
    }
}

So the rules are clear, but I can't say I understand the reasons behind them!

所以规则很清楚,但我不能说我理解它们背后的原因!

回答by Evgeniy Dorofeev

In fact you are already using protected constructor of Example because Check has an implicit constructor and implicit Example constructor call:

事实上,您已经在使用 Example 的受保护构造函数,因为 Check 有一个隐式构造函数和隐式 Example 构造函数调用:

public Check() {
    super();
}