Reputation: 642
Is the protected
variable of a parentObject
be accessed from any child Object
? or can be accessed only by only the particular childObject
? I have a scenario which clearly expresses my doubt.
I have two classes ParentClass
and ChildClass
. ParentClass
is parent of ChildClass
. I have a protected
variable in ParentClass
named protVar
. It is of type Object
. Then, I create two Object
s like the following.
ParentClass p1 = new ParentClass();
ChildClass c1 = new ChildClass();
c1.callMethod(p1); // Here I want to access protected variable of p1 which is a separate object and Not initialized within c1 as super()
Now will I be able to access the protVar
of p1
from c1
?
Upvotes: 5
Views: 24595
Reputation: 40056
Disclaimer: the answer is copied from my answer of another question. However no answer from that question is accepted. I believe it also suit this question therefore I am copying the content with some minor editing to here.
protected
is a bit interesting in Java. Although we always says "protected" give access to subclass of different package, it is not the whole picture.
For example, if you have Child
extending Parent
, and there is a protected member in Parent
. What you can do in Child
is to access that protected member of Child
, but not even that protected member of Parent
. Sounds a bit strange right although they sounds the same thing?
Quoted from Core Java 9th Edition:
However, the Manager class methods can peek inside the hireDay field of Manager objects only, not of other Employee objects. This restriction is made so that you can’t abuse the protected mechanism by forming subclasses just to gain access to the protected fields
(class Manager extends Employee, and there is a hireDay protected member in Employee, and Manager and Employee are located in DIFFERENT package)
For example,
public class Manager extends Employee {
// accessing protected member of itself
public void foo1() {
System.out.println("" + this.hireDay); // OK
}
// access protected member of instance of same type
public void foo2(Manager manager) {
System.out.println("" + manager.hireDay); // OK
}
// access protected member of instance of super-class
public void foo3(Employee employee) {
System.out.println("" + employee.hireDay); // NOT ALLOWED!
}
}
Which means, protected member allow child class from another package to access through reference of that child class (either this
, or another reference that is-a child class)
And, be specific to OP's answer: if callMethod
is declared in ChildClass
, then NO, you cannot do it and it will not even compile. However if callMethod
is declared in ParentClass
then everything is fine, because it is simply ParentClass
accessing protected member of a ParentClass
instance.
Update:
Given criticisms in comment, I think it worth to go to JLS to see what it say:
(Quoted from http://docs.oracle.com/javase/specs/jls/se8/html/jls-6.html#jls-6.6.2.1 about Access to a protected Member, second bullet)
If the access is by a field access expression E.Id, or a method invocation expression E.Id(...), or a method reference expression E :: Id, where E is a Primary expression (§15.8), then the access is permitted if and only if the type of E is S or a subclass of S
This is essentially what I was trying to deliver in the answer:
Within Manager
class, manager.hireDay
works because manager
is a primary expression, and the access is permitted because type of manager
is Manager
or subclass of Manager
.
So, based on JLS, why manager.hireDay
works DOES have relationship with type of manager
(being the same type).
Upvotes: 9
Reputation: 1054
Even though the question is old , I am trying my best to explain , since this is a fairly common question for java newbies.
Consider Employee class in package p1.
package p1;
public class Employee{
protected String hireDay = "hireday";
}
Manager extends Employee and is in a different package.
package p2;
public class Manager extends p1.Employee {
//now even Manager class has hireDay protected variable that was defined in Employee class.
//Since Manager class has protected variable hireDay , for any manager m1 , we can access hireDay as m1.hireDay ONLY within package p2.
}
Enterprenur class extends Manager and is in package p3.
package p3;
public class Enterpreneur extends p2.Manager{
//now Enterpreneur class has inherited hireDay protected variable that Employee class had. (see comments in Employee class.)
//Since Enterpreneur class has protected variable hireDay , for any Enterpreneur e , we can access hireDay as e.hireDay ONLY within package p3.
//the following will work because using Enterpreneur reference e , we can access e.hireday within package p3 , this has nothing to do with
//the fact that right now our code is present in Enterpreneur class , like the other answer said. Note the method is static.
public static void printhireDay(Enterpreneur e){
System.out.println("hireday is :" + e.hireDay);
}
//this will work because using this reference we can only access protected variable in the same class(Enterpreneur) or in a subclass.
public void printhireDay(){
System.out.println("hireday is :" + this.hireDay);
}
// This shouldn't work because using manager reference , we can only access protected field within package p2.
/* public printhireDay(Manager m){
System.out.println("hireday is :" + m.hireDay)
}*/
}
Now within the root package , we have this class to test.
public class HelloWorld{
public static void main(String []args){
p3.Enterpreneur e = new p3.Enterpreneur();
//both of these work.
e.printhireDay();
//printing by passing the reference e.
p3.Enterpreneur.printhireDay(e);
}
}
Upvotes: -1
Reputation: 311023
Yes, a derived class can access a protected variable in a base class via both 'super' and another reference to the base class.
EDIT It should be noted that I am here assuming the same package as you didn't state anything about different packages. The rules are different otherwise.
Upvotes: 2
Reputation: 1445
If your child class and Parent class in same package than you can access this object directly [If you wish], Otherwise you have two option.
1 - Create a public getter method in Parent class and access your protected field using that method
2 - Inside child class fetch the Parent protected field using reflection like given below
public void callMethod(ParentClass o) {
try {
Field f = o.getClass().getDeclaredField("protVar");
f.setAccessible(true);
Object value = f.get(o);
} catch (SecurityException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
Upvotes: 0