0

I am trying to understand the behavior of protected member in a class. I have a class TopClass which contains protected integer pr.

Class:

package com.test;

import com.test.anotherpackage.SubClass1;
import com.test.anotherpackage.SubClass2;
import com.test.anotherpackage.SubClass3;

public class TopClass {
    protected int pr;

    void action(TopClass t, SubClass1 s1, SubClass2 s2, SubClass3 s3) {
        t.pr = 3;
        s1.pr = 0;
        s2.pr = 1;
        s3.pr = 1;
    }
}

There is another package com.test.anotherpackage which has 3 classes SubClass1,SubClass2 and SubClass3. Inheritance hierarchy is as follows:

  1. SubClass1 extends TopClass
  2. SubClass2 extends SubClass1
  3. SubClass3 extends SubClass2

SubClass1

package com.test.anotherpackage;

import com.test.TopClass;

public class SubClass1 extends TopClass {

    void action(TopClass t, SubClass1 s1, SubClass2 s2, SubClass3 s3) {
        t.pr = 0; // Error because not in same package.
        s1.pr = 0; //(1)
        s2.pr = 1; // Does not throw an Exception. Why? (2)
        s3.pr = 1; // (3)
    }
}

SubClass2

package com.test.anotherpackage;

import com.test.TopClass;

public class SubClass2 extends SubClass1 {
    void action(TopClass t, SubClass1 s1, SubClass2 s2, SubClass3 s3) {
        t.pr = 0; // Error because not in same package.
        s1.pr = 0; // Throws Exception, why?  (4)
        s2.pr = 1; //  (5)
        s3.pr = 1; // Does not throw an Exception. Why?(6)
    }
}

SubClass3

package com.test.anotherpackage;

import com.test.TopClass;

public class SubClass3 extends SubClass2 {
    void action(TopClass t, SubClass1 s1, SubClass2 s2, SubClass3 s3) {
        t.pr = 0; 
        s1.pr = 0; // Not Visible (7)
        s2.pr = 1; // Not Visible (8)
        s3.pr = 1; // (9)
    }
}

In above code, (1), (2), (3), (5), (6) and (9) work perfectly without any visibility issues. But (4), (7), (8) have visibility issues.

According to JLS§6.6.2.1,

Let C be the class in which a protected member is declared. Access is permitted only within the body of a subclass S of C.

In addition, if Id denotes an instance field or instance method, then:

If the access is by a qualified name Q.Id, where Q is an ExpressionName, then the access is permitted if and only if the type of the expression Q is S or a subclass of S.

If the access is by a field access expression E.Id, where E is a Primary expression, or by a method invocation expression E.Id(. . .), where E is a Primary expression, then the access is permitted if and only if the type of E is S or a subclass of S.

Thing I am trying to understand here is why if the type of the expression Q is S or a subclass of S comes into picture. Is there any specific scenario in which this implementation can be beneficial? Any related example will be highly appreciated. I tried looking it on SO, but couldn't find an explanation which could solve my doubt.

Ryan B
  • 3,364
  • 21
  • 35
D3V
  • 1,543
  • 11
  • 21

1 Answers1

0

The expression you're discussing is also the one responsible for your questions in the code:

if the type of the expression Q is S or a subclass of S

(2) because the type of the expression s2 is a subclass of SubClass1
(4) because the type of the expression s1 is not a subclass of SubClass2
(5) because the type of the expression s3 is a subclass of SubClass2

However, I don't know of

any specific scenario in which this implementation can be beneficial

either.

Michael Lang
  • 3,902
  • 1
  • 23
  • 37
  • Reasons you explained are already covered by JLS§6.6.2.1. I wanted to know why the implementation has that clause. I do not understand the reason behind permitting accessibility via subclass reference in superclass. – D3V Jul 08 '13 at 05:09