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

这个问题在这里已经有了答案:

  • 在Java中,封装私有,公共,受保护和私有26个答案之间的区别

  • 受保护的修饰符仅用于包和包外的子类中。 当你使用Example ex=new Example();创建一个对象时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
        }
    }
    

    符合JLS 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(){}; // This will work as the access is by an anonymous class instance creation expression 
        }
    }
    

    通常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);
        }
    }
    

    但是这样做

    public class Example extends Exception {
    
        Example() {
            super("Hello", null, false, false);
        }
    }
    

    这也是如此

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

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


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

    public Check() {
        super();
    }
    
    链接地址: http://www.djcxy.com/p/24053.html

    上一篇: Why cant i use protected constructors outside the package?

    下一篇: Java Instance Variable Accessibility