Protected variables can be accessed within Child Class or Child Object

17,761

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.

Share:
17,761
Santron Manibharathi
Author by

Santron Manibharathi

Working as a programmer in a Private Concern.

Updated on June 04, 2022

Comments

  • Santron Manibharathi
    Santron Manibharathi about 2 years

    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 Objects 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?

  • Seelenvirtuose
    Seelenvirtuose over 10 years
    Ui. 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
    Adrian Shum over 10 years
    I believe both EJP and @Seelenvirtuose are wrong. So happened I have answered a similar question recently: stackoverflow.com/a/21929828/395202
  • Seelenvirtuose
    Seelenvirtuose over 10 years
    No, 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
    user207421 over 10 years
    It'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 access p.protectedVariable.
  • Radiodef
    Radiodef over 10 years
    Maybe you forgot to put them in different packages.
  • user207421
    user207421 over 10 years
    @Radiodef There is nothing in the question about different packages.
  • Radiodef
    Radiodef over 10 years
    I 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
    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 access emp.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
    Seelenvirtuose over 10 years
    According 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
    user207421 over 10 years
    @Seelenvirtuose That would be why I edited it into my answer.
  • Rpant
    Rpant over 7 years
    The answer is misleading. In second part , manager.hireDay does not work because you are accessing protected member of instance of same type. Once manager inherits hireDay , hireDay is now a protected field of Manager class. Hence , even a complete different class , Entrepreneur will be able to access hireday using an instance of Manager ( manager.hireDay ) as long as Enterpreneur belongs to the same package as Manager.
  • Adrian Shum
    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 of protected). 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
    Rpant over 7 years
    I 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 and Manager to belong to different package. However Enterpreneur belongs to the same package as Manager
  • Adrian Shum
    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
    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
    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
    Adrian Shum over 7 years
    As 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
    Adrian Shum over 7 years
    You 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
    Rpant over 7 years
    Wow , 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
    Adrian Shum over 7 years
    You 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
    Adrian Shum over 7 years
    And, 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 to static. However, in accessibility control in Java, it makes not difference for static or instance method.
  • Adrian Shum
    Adrian Shum over 7 years
    I 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
    Rpant about 7 years
    I 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.