Protected constructor and accessibility

一曲冷凌霜 提交于 2019-12-17 07:22:27

问题


Why can't we instantiate a class with a protected constructor if its child is in a different package? If protected variables and methods can be accessed, why doesn't the same rule also apply for a protected constructor?

pack1:

package pack1;

public class A {
    private int a;
    protected int b;
    public int c;

    protected A() {    
        a = 10;
        b = 20;
        c = 30;
    }
}

pack2:

package pack2;

import pack1.A;

class B extends A {
    public void test() {
        A obj = new A(); // gives compilation error; why?
        //System.out.println("print private not possible :" + a);
        System.out.println("print protected possible :" + b);
        System.out.println("print public possible :" + c);
    }
}

class C {
    public static void main(String args[]) {
        A a = new A(); // gives compilation error; why?
        B b = new B();
        b.test();
    }
}

回答1:


According to the Java Spec (https://docs.oracle.com/javase/specs/jls/se8/html/jls-6.html#jls-6.6.2.2)

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.

In your case, access to the protected constructor of A from B would be legal from a constructor of B through an invocation of super(). However, access using new is not legal.




回答2:


JLS 6.6.7 answers your question. A subclass only access a protected members of its parent class, if it involves implementation of its parent. Therefore , you can not instantiate a parent object in a child class, if parent constructor is protected and it is in different package...

6.6.7 Example: protected Fields, Methods, and Constructors Consider this example, where the points package declares:

package points;
public class Point {
    protected int x, y;
    void warp(threePoint.Point3d a) {
        if (a.z > 0)        // compile-time error: cannot access a.z
            a.delta(this);
    }
}

and the threePoint package declares:

package threePoint;
import points.Point;
public class Point3d extends Point {
    protected int z;
    public void delta(Point p) {
        p.x += this.x;      // compile-time error: cannot access p.x
        p.y += this.y;      // compile-time error: cannot access p.y
    }
    public void delta3d(Point3d q) {
        q.x += this.x;
        q.y += this.y;
        q.z += this.z;
    }
}

which defines a class Point3d. A compile-time error occurs in the method delta here: it cannot access the protected members x and y of its parameter p, because while Point3d (the class in which the references to fields x and y occur) is a subclass of Point (the class in which x and y are declared), it is not involved in the implementation of a Point (the type of the parameter p). The method delta3d can access the protected members of its parameter q, because the class Point3d is a subclass of Point and is involved in the implementation of a Point3d. The method delta could try to cast (§5.5, §15.16) its parameter to be a Point3d, but this cast would fail, causing an exception, if the class of p at run time were not Point3d.

A compile-time error also occurs in the method warp: it cannot access the protected member z of its parameter a, because while the class Point (the class in which the reference to field z occurs) is involved in the implementation of a Point3d (the type of the parameter a), it is not a subclass of Point3d (the class in which z is declared).




回答3:


I agree with previous posters, don't know why you would want to do this (instantiate parent in that way in extending class) but you could even do something like this:

public void test() {
    A obj = new A(){}; // no compilation error; why? you use anonymous class 'override'
    ...



回答4:


Why do you need A obj=new A(); in class, whereas object of class b is itself an object of class A

And in class c it is giving error because, you are accessing the protected property of class A which is constructor.

To get object of class A in this case you must use this function in class A

static A getInstance()
{
   A obj = new A(); // create obj of type A.
   return obj; // returns that object by this method. No need to use 'New' kind of instantiation.
}


来源:https://stackoverflow.com/questions/5150748/protected-constructor-and-accessibility

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!