Protected variables can be accessed within Child Class or Child Object
Solution 1
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).
Solution 2
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.
Santron Manibharathi
Working as a programmer in a Private Concern.
Updated on June 04, 2022Comments
-
Santron Manibharathi about 2 years
Is the
protected
variable of aparentObject
be accessed from any childObject
? or can be accessed only by only the particularchildObject
? I have a scenario which clearly expresses my doubt.I have two classes
ParentClass
andChildClass
.ParentClass
is parent ofChildClass
. I have aprotected
variable inParentClass
namedprotVar
. It is of typeObject
. Then, I create twoObject
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
ofp1
fromc1
? -
Seelenvirtuose over 10 yearsUi. Sorry to say, but this is simply not true! A protected member (field or method) can only be accessed via the super mechanism. If you get a reference in another way, you can only access this member when being in the same package (as protected also includes package visibility)!
-
Adrian Shum over 10 yearsI believe both EJP and @Seelenvirtuose are wrong. So happened I have answered a similar question recently: stackoverflow.com/a/21929828/395202
-
Seelenvirtuose over 10 yearsNo, I am not wrong. You cannot access protected fields from an object that you just have a reference from (e.g. through a simple variable). But keep in mind, that this is true only, if your accessing code resides in another package. If it is the same package, you can access the protected fields, as protected includes package visibility.
-
user207421 over 10 yearsIt's extremely strange that you should all think this isn't correct. I tested it before I posted. A method
ChildClass.method(ParentClass p)
can accessp.protectedVariable.
-
Radiodef over 10 yearsMaybe you forgot to put them in different packages.
-
user207421 over 10 years@Radiodef There is nothing in the question about different packages.
-
Radiodef over 10 yearsI guess the OP could have provided that detail but I find that to be a kind of specious technicality since your answer didn't make the distinction either. If they are in the same package then whether or not one is derived from the other doesn't matter.
-
Adrian Shum over 10 years@EJP that's strange, because, in my answer, I have tried and found that in
Manager.foo3(Employee emp)
, it cannot accessemp.protectedVar
(of course, given Manager and Employee are in different package). If it is in the same package, it is quite meaningless because the "package" accessibility will always allow you to access those protected member if you reside in same package. -
Seelenvirtuose over 10 yearsAccording to your edit, I removed my downvote. But whether or not the OP mentioned it, the detail of being in the same package or not is so important when talking about access modifiers, that any good answer should explain it.
-
user207421 over 10 years@Seelenvirtuose That would be why I edited it into my answer.
-
Rpant over 7 yearsThe answer is misleading. In second part ,
manager.hireDay
does not work because you are accessing protected member of instance of same type. Oncemanager
inheritshireDay
,hireDay
is now a protected field ofManager
class. Hence , even a complete different class ,Entrepreneur
will be able to access hireday using an instance ofManager
(manager.hireDay
) as long asEnterpreneur
belongs to the same package asManager
. -
Adrian Shum over 7 years@Rpant I believe you haven't understand the rationale behind. When we are talking about
protected
in the example above, of course we have to make sure that the classes are from different package, so you do not gain accessibility through package/default (which is also part ofprotected
). If things are put under same package,protected
or package/default makes no difference. And, in above example,manager.hireDay
DOES work. Please read it again to make sure you really understand :) -
Rpant over 7 yearsI am not saying it DOESN'T work. I am saying the explanation you are giving as to why it works ( its instance of same type) is wrong. In the explanation I gave , I am still considering ,
Employee
andManager
to belong to different package. HoweverEnterpreneur
belongs to the same package asManager
-
Adrian Shum over 7 years"In second part , manager.hireDay does not work because " that's what you wrote. And, I do understand people can use different way to understand this behavior but what I wrote (which based on a book) is the actual effect you will observe (i.e. you can only access thru ref of same class, given parent class in different package).
-
Adrian Shum over 7 years@Rpant and, if you are interested, you may check JLS: docs.oracle.com/javase/specs/jls/se8/html/… , the 2nd bullet point: 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. which is what described in the answer
-
Rpant over 7 years""In second part , manager.hireDay does not work because "" , I meant ""In second part , manager.hireDay works not because (of the explanation)""
-
Adrian Shum over 7 yearsAs I said before, you may use a different semantic to understand. However please read the JLS as quoted. What I was explaining is exactly what the JLS saying. "Access (of protected field hireday) is permitted if and only if the type of E (manager in the example) is S or subclass of S (Manager in this example)"
-
Adrian Shum over 7 yearsYou still miss the point. If you only understand this by "the field can be accessed because it is in same package", you cannot explain why in Manager class, it is valid to do
anEntrepreuerRef.hireDay
-
Rpant over 7 yearsWow , I was wrong .. Did not expect this to work , but it does work. I was expecting
anEntrepreuerRef.hireDay
to be accessible only within package p3. I however still did not get your point across about why it works. -
Adrian Shum over 7 yearsYou may read the JLS I quoted and my answer again. It works because it is a protected field (declared in superclass of another package), and it is accessing thru reference with type same as (or subclass of) itself.
-
Adrian Shum over 7 yearsAnd, I think you also have one confusion of accessibility common to Java newbies: In your example, you explicitly mentioned some method being
static
, for which I believe you expect there is something special for accessibility related tostatic
. However, in accessibility control in Java, it makes not difference for static or instance method. -
Adrian Shum over 7 yearsI wonder if the JLS proved to you the correctness of my answer (and incorrectness in yours)? It will be great if you can clarify and withdraw your downvote in my original answer (if it is from you), so that it makes new comer easier to follow. THanks
-
Rpant about 7 yearsI up-voted your answer again. In your answer , if you can add code in Employee class to access manager.hireDay, that will clearly demo access of protected member variable of sub-type. Your code already demos same type and super type.