10

Here is the slightly elaborated version of the same question.

We cannot access protected variable (of the superclass) in the subclass,where subclass is in different package.We can access only the inherited variable of the supeclass. But if we change the modifier to ' protected static' then we can access the variable of the superclass too. Why is it like that.?

Here is the code snippet of the same which i was trying to explain.

package firstOne;

public class First {
    **protected** int a=7;
}

package secondOne;

import firstOne.*;

public class Second extends First {
    protected int a=10; // Here i am overriding the protected instance variable

    public static void main (String [] args){
        Second SecondObj = new Second();
        SecondObj.testit();
    }
    public void testit(){
        System.out.println("value of A in Second class is " + a);
        First b = new First();
        System.out.println("value in the First class" + b.a ); // Here compiler throws an error.
    }
}

The above behavior is expected. But my question is, if we change the access modifier of the superclass instance variable 'a' to 'protected static' then we can access the variable(that of the superclass) too..! What i meant is,

package firstOne;

public class First {
    **protected static** int a=7;
}

package secondOne;

import firstOne.*;

public class Second extends First {
    protected int a=10;

    public static void main (String [] args){
        System.out.println("value in the super class" + First.a ); //Here the protected variable of the super class can be accessed..! My question is how and why..?
        Second secondObj = new Second();
        secondObj.testit();
    }

    public void testit(){
        System.out.println("value of a in Second class is " + a);
    }

}

The above code shows the output:

value in the super class 7

value of x in test1 class is 10

How is this possible...?

Denim Datta
  • 3,740
  • 3
  • 27
  • 53
Prasad
  • 368
  • 1
  • 6
  • 16
  • 2
    I'm more confused about why the first case _doesn't_ work. According to [the documentation on access control](http://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html) I would think `a` should be visible in both cases. – DaoWen Jun 24 '13 at 03:52
  • 1
    Isn't `protected` on instance members only applicable to `this`? i.e. you have to be using `this` if you want to access it from a subclass; it won't work on an arbitrary instance. – user541686 Jun 24 '13 at 04:06
  • @Thihara: I tested his code (minus the extra `**`s) and I also get a compiler error: `error: a has protected access in First`. – DaoWen Jun 24 '13 at 04:14
  • I'm on 1.6 though.... May be that's why? But how come though? – Thihara Jun 24 '13 at 04:47
  • @DaoWen: First case doesnt work because there i am trying to access the protected member of the super class from the subclass which is in different package. What you told, 'a' will be visible to both classes if both parent/child classes are in same package. In the first example, put the 'Second' class inside package 'firstOne'. Then it wont show any compilation error. – Prasad Jun 24 '13 at 05:32
  • @Mehrdad: Here i have not explicitly mentiones this keyword. But internally it will be resolved to this.a itself. This is what my understanding is. Please correct me if i am wrong :) – Prasad Jun 24 '13 at 05:34
  • @user2514784: Sorry I don't think you understood what I meant. I'm saying `b.a` is illegal because `b` is not `this`, and `protected` on a field only means "let subclasses access this member of `this`". However, `First.a` is allowed because if it weren't, you could just as well say `this.a` to access it, so it would be silly for the compiler to prohibit it since it's not protecting anything. – user541686 Jun 24 '13 at 05:40
  • @Mehrdad: Sorry i didnt get your question right the first time. Yes you are correct. – Prasad Jun 24 '13 at 06:03
  • @Mehrdad: But still this doesnt explain why there is a change in the behavior when i use the keyword static. – Prasad Jun 24 '13 at 06:17
  • 1
    @Prasad: Er, that means you didn't understand what I said, I just explained it to you! When you say `protected static` then that means `this.a` accesses the same variable as `b.a`, so it wouldn't make sense for the compiler to allow the first but prevent the others. When you just say `protected` then `this.a` isn't the same as `b.a` so the compiler allows you to access `this.a` but prevents you from accessing `b.a`. – user541686 Jun 24 '13 at 06:30
  • @Prasad - My point was that, according to the documentation, I would expect `Second` to have access to `First`'s protected members regardless of the package since they have a subclass relationship. I think Mehrdad might have it right about needing a `this` reference, but in that case the documentation should really be more clear. – DaoWen Jun 24 '13 at 06:34
  • Sorry about the misinformation, stupid me have put the classes in the same package :-/ – Thihara Jun 24 '13 at 06:43
  • @Mehrdad: You told when i say 'protected static' this.a and b.a accesses the same variable. But when you look at the output, thats not the case. They are accessing different variables. In the second code snippet, when I print the value using system.out, they are showing different values. According to you, if they were accessing the same variable when 'protected static' is used, they should have printed the same value 7, instead of showing 7 and 10. Can you explain this..? – Prasad Jun 24 '13 at 07:08
  • 1
    @Prasad: Uh, your code isn't the same thing as in my explanation. You have an extra `protected int a=10;`, which is shadowing the `protected static a` in `First`. That's just confusing you even more. Remove it so you see why the compiler behaves the way I told you. Then feel free to put it back after it makes sense. – user541686 Jun 24 '13 at 07:36

2 Answers2

5

From "Checking Access to Protected Members in the Java Virtual Machine":

Let m be a member declared in a class c that belongs to a package p. If m is public, it can be accessed by (code in) any class. If m is private, it can be accessed only by c. If m has default access, it can be accessed only by any class that belongs to p.

If m is protected, things are slightly more complicated. First, m can be accessed by any class belonging to p, as if it had default access. In addition, it can be accessed by any subclass s of c that belongs to a package different from p, with the following restriction: if m is not static, then the class o of the object whose member is being accessed must be s or a subclass of s, written os (if m is static, the restriction does not apply: m can be always accessed by s).

I found that reference in the JLS, section 6.6.2.1, which supports the part about "the object whose member is being accessed must be s or a subclass...". I don't see anything supporting the static clause, but based on your own example, it's obviously true.

Community
  • 1
  • 1
Ryan Stewart
  • 126,015
  • 21
  • 180
  • 199
  • So you mean to say that, when static keyword is used along with protected for variables, this is how the behavior changes and there is no logical reasoning given by the oracle doc and we just have to remember it...? – Prasad Jun 24 '13 at 06:39
  • You are right, there's nothing in the spec regarding this, in protected section or the static section.. Or well at least as far as I can tell. So I think this is a grey area in the spec... – Thihara Jun 24 '13 at 06:42
0

Override only applies to methods, not class variables. There is no such thing as to override a variable. You are shadowing the symbol accessing variable a of the superclass.

sibidiba
  • 6,270
  • 7
  • 40
  • 50