Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java private constructors visibility

I try to understand why there is a difference between accessibility of class members when speaking about constructors.

Consider the following example:

class A {   static class B {       private B(String s) {}     private void foo() {}   }   static class C extends B {     public C(String s) {       super(s); // call B(String), which is private, and obviously accessible     }     void bar() {       foo(); // compilation error (symbol unknown), as B.foo() is private     }   } } 

Private members of A, as being private, should not be accessible from B. For fields and methods, it is the case, but it seems that constructors are not following the same rule.

From the JLS-8 (6.6.1. Determining Accessibility), we can read:

[...]

A member (class, interface, field, or method) of a reference type, or a constructor of a class type, is accessible only if the type is accessible and the member or constructor is declared to permit access:

  • [...]

  • Otherwise, the member or constructor is declared private, and access is permitted if and only if it occurs within the body of the top level class (§7.6) that encloses the declaration of the member or constructor.

Can anyone explain me why the constructor is accessible from C, even while being declared private?

like image 627
Wohops Avatar asked Nov 19 '15 09:11

Wohops


People also ask

What happens when constructor is private in Java?

A private constructor does not allow a class to be subclassed. A private constructor does not allow to create an object outside the class. If all the constant methods are there in our class we can use a private constructor. If all the methods are static then we can use a private constructor.

When would you see a private constructor?

Private constructors are used to prevent creating instances of a class when there are no instance fields or methods, such as the Math class, or when a method is called to obtain an instance of a class.

Are Java constructors always public?

No, Constructors can be public , private , protected or default (no access modifier at all). Making something private doesn't mean nobody can access it. It just means that nobody outside the class can access it.

How do you make a constructor visible in Java?

The default constructor is a public no arguments constructor. To be more specific it has the same access level as the class, so public in a public class, private in a private class, etc. In your second example you are creating a package access level constructor.


2 Answers

The method foo() is private, so you don't inherit it and can't call it directly from the C class.

However, you can see private methods and constructor from B since everything is declared in the same containing class, and access them with super, which is why super() works. In the same way, you can access foo with super.foo().

Note that you can redefine a new foo method in C, but this method will not override B.foo().

like image 80
WilQu Avatar answered Sep 23 '22 17:09

WilQu


So the trick here might be the following :

you cannot access foo because it is declared private so you don't inherit it in C.

However, as was noted in comments you can access super.foo(); because super refers to a type that is declared in the same top level class (see JLS 6.6.1 for this).

Then the trick is that calling super(s) can be viewed as calling super.<init>(s) which ends up being the same case as super.foo()

like image 34
benzonico Avatar answered Sep 23 '22 17:09

benzonico