Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Protected constructor and accessibility

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();     } } 
like image 511
Chandra Kanth Avatar asked Mar 01 '11 05:03

Chandra Kanth


People also ask

What happens if a constructor is declared protected?

Protecting a constructor prevents the users from creating the instance of the class, outside the package. During overriding, when a variable or method is protected, it can be overridden to other subclass using either a public or protected modifier only. Outer class and interface cannot be protected.

Is protected accessible in outside package?

Protected members cannot be accessed from the non-child class of outside package. Package members cannot be accessed from non-child class of outside package. Public modifier is the most accessible modifier among all modifiers.

Can we use protected in constructor?

Access specifiers/modifiers allowed with constructorsModifiers public, protected and, private are allowed with constructors.

Can we use private access modifiers in constructor declaration?

Like methods, constructors can have any of the access modifiers: public, protected, private, or none (often called package or friendly). Unlike methods, constructors can take only access modifiers. Therefore, constructors cannot be abstract , final , native , static , or synchronized .


2 Answers

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.

like image 150
mazaneicha Avatar answered Sep 25 '22 03:09

mazaneicha


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).

like image 26
Gursel Koca Avatar answered Sep 26 '22 03:09

Gursel Koca