Hello Stackoverflow community :-]
I am a new member and first I would like to thank you for the very helpful advice and correction that you provide. As I am french, please forgive me if my english is not perfect.
Here is my question : I'm currently learning Java programming language, and I wanted to test some inheritance stuff. If I understood right, a field declared as protected
can be accessed by classes which are in the same package as the class where protected field is declared, and by all of its subclasses, whether they are in the same package or not.
So, I did these 4 classes to test this. I have a package named "package1" containing classes A and C. I also have a second package named "package 2" containing classes A2 and C, where A2 extends A. The two C classes have exactly the same code, just the package where they are located changes.They do not extend A.
In A class, I declared some members with different access properties, especially the constructor which is declared with protected
visibility. Here is the code of the four classes.
package1, class A :
package package1;
public class A {
public int a;
protected int b;
private int c;
int d;
protected static int h = 30;
protected void aff(){
System.out.println(h);
}
protected A(){
a = 1;
b = 2;
c = 3;
d = 4;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
}
}
package 1, class C :
package package1;
public class C {
public C(){
super();
}
public void app(){
A obj = new A(); //////// OK
}
public static void main(String[] args) {
// TODO Auto-generated method stub
A obj = new A(); //////// OK
obj.aff(); //////// OK
System.out.println(obj.a);
}
}
package2, class A2 (extends A) :
package package2;
import package1.A;
public class A2 extends A{
public int x;
A2(){
super();
}
public void app(){
A obj = new A(); //////// ERROR
}
public static void main(String[] args) {
// TODO Auto-generated method stub
A obj = new A(); //////// ERROR
A2 obj2 = new A2();
obj2.aff(); //////// OK
}
}
package2, class C :
package package2;
import package1.A;
public class C {
public C(){
super();
}
public void app(){
A obj = new A(); //////// ERROR
}
public static void main(String[] args) {
// TODO Auto-generated method stub
A obj = new A(); //////// ERROR
obj.aff(); //////// ERROR
System.out.println(obj.a);
}
}
For C class in package2, the code A obj = new A();
throws an error but it's not the case for C class in package1. That's correct because constructor is declared as protected
and C in package2 is not a subclass of A, while C is in package1. To that point, I understand.
Where I have a problem is with the code A obj = new A();
in class A2 : wherever it is written, it throws an error The constructor A() is not visible
... As class A constructor is declared as protected
, why couldn't I instantiate an object of type A in A2 class ?
When I declare A constructor as public
, it works fine. Besides, if I put A2 class in package1 by letting code as it is, it works too. It seems that instantiating A object in a subclass of A is only possible if the subclass is located in the same package if A constructor is declared as protected
.
However, as you can see, if I first instantiate a A2 object and then call the class A protected
aff() method, there it works and the protected rule is respected.
Does someone have the explanation for this error ? When instantiating an object of superclass in its subclass, does this subclass always be located in the same package as its superclass, if superclass constructor is declared as protected
? And why is it the case if so ?
Or does this has to deal with the fact that a constructor is not inherited by subclasses ? But I can't figure out to see why if it's the case...
Thanks a lot in advance for taking time to read and answer :-]
See Java Language Specification:
Your class
A2
is not responsible for the implementation ofA
in thenew A()
call.Meaning, it is not responsible for the implementation of an instance of
A
, but it is responsible for the implementation of an instance ofA2
.This is fun so let me try to summarize it. see JLS#6.6.1
protected
can qualify a constructor or a member of a class."member" includes field/method (static/instance), nested class/interface (static/inner)
First, to access a protected constructor/member, the enclosing class (e.g.
A
) must be accessible. Assume that's the case, then ----Inside the package --
A protected constructor or member is accessible anywhere within the same package.
--Outside the package --
A protected constructor is only accessible within subclass constructors, either as a
super()
call, or as an anonymous class instantiation.A protected static field/method, nested class/interface is accessible anywhere within subclass bodies.
A protected instance field/method is more complex --
obj.m
is accessed in class B (outside A's package)obj
's type is CThe access
obj.m
is granted only if B is subclass of A, and C is subclass of B or C is B.super.m
is always allowed; however, it's unclear how JLS frames the issue. It seems that the access should be treated the same asthis.m
, therefore access is allowed.