Clarification about accessibility of private members

Eddie Aftandilian eaftan at google.com
Thu Oct 13 20:24:23 UTC 2016


Thanks for the clear explanation!

On Mon, Oct 3, 2016 at 2:50 AM, Maurizio Cimadamore <
maurizio.cimadamore at oracle.com> wrote:

>
>
> On 30/09/16 22:31, Eddie Aftandilian wrote:
>
> JLS 6.6.1 says, "Otherwise, the member or constructor is declared private,
> and access is permitted if and only if it occurs within the body of the top
> level class (§7.6) that encloses the declaration of the member or
> constructor."  Under that definition, I believe the following code should
> be legal:
>
> class Holder {
>   class Super {
>     private String s1;
>   }
>   class Sub extends Super {
>     private String doIt() {
>       return s1;
>     }
>   }
> }
>
> Holder is the top level class that encloses the declaration of s1, and the
> "return s1" statement occurs inside Holder's body.  However, javac 1.8.0
> issues an error on this code:
>
> Holder.java:7: error: s1 has private access in Holder.Super
>       return s1;
>              ^
> 1 error
>
> What am I missing?
>
> I think there's another aspect at stake here: interplay between
> inheritance and scoping. But let's start from the beginning: the rules for
> checking that 's1' is a valid field identifier are defined in 6.5.6.1:
>
> "If an expression name consists of a single Identifier, then there must be
> exactly one declaration denoting either a local variable, parameter, or
> field *visible* (§6.4.1) at the point at which the Identifier occurs.
> Otherwise, a compile-time error occurs."
>
> What does 'visible' mean? Let's expand 6.4.1:
>
> "A declaration d is said to be visible at point p in a program if the
> scope of d includes p, and d is not shadowed by any other declaration at p."
>
> Ok, so the question we need to ask is: does the scope of 's1' includes the
> instance method doIt() ?
>
> The scope of a field is defined as follows in JLS 6.3:
>
> "The scope of a declaration of a member m declared in or inherited by a
> class type C (§8.1.6
> <https://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.1.6>)
> is the entire body of C, including any nested type declarations."
>
> So, from the perspective of 'Sub' the only way for it to have a field 's1'
> in scope is:
>
> * if it declares the field 's1'
> * if it inherits a field 's1'
>
> In your example, the first bullet clearly does not apply: 'Sub' doesn't
> declare any fields. So the question is, does 'Sub' inherits 's1' from
> 'Super' ? The answer is again no, this time because of JLS 8.2. (Class
> Members):
>
> "Members of a class that are declared private are not inherited by
> subclasses of that class."
>
> That is, 's1' is not inherited because it is declared private in 'Sup'.
> Popping back, this means that 's1' is not visible inside 'doIt()' and
> therefore the error message you get is expected.
>
> Maurizio
>
> Thanks,
> Eddie
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.openjdk.java.net/pipermail/compiler-dev/attachments/20161013/e04a399b/attachment.html>


More information about the compiler-dev mailing list