4

Consider the following snippet.

package breakoop;

public class BreakOOP {

    public static class A{
        private int a;
    }

    public static class B extends A{
        public int f(){
            return super.a;
        }
    }

    public static void main(String[] args) {
        B b = new B();
        System.out.println(b.f());
    }
}

The example only compiles if A and B are encapsulated within the BreakOOP class.

This seems to go against some of the fundamental concepts of OOP. Can someone explain why this compiles? What is the reasoning behind it?

Igor Ševo
  • 5,459
  • 3
  • 35
  • 80
  • 1
    You're referring to `super.a` I guess. That compiles because the spec says so which is that any private member is visible inside the scope of the top level class, i.e. within `BreakOOP` in your case (I'll have to look up the relevant section of the JLS). – Thomas Sep 27 '16 at 11:57
  • Inner classes get the visibility rules from their parent classes. Why this is? - Up to debate, this just the way it goes in java. Thus, accessing super.a from B is like two private variables in the BreakOOP class. If you want more extensive protection, you'll have to move them into different compilation units. – mtj Sep 27 '16 at 11:58
  • Possible duplicate of [Access to superclass private fields using the super keyword in a subclass](http://stackoverflow.com/questions/31478718/access-to-superclass-private-fields-using-the-super-keyword-in-a-subclass) – Bob Brinks Sep 27 '16 at 12:05
  • 1
    I don't know the reasoning behind why this is allowed, but the argument that it increases encapsulation, in my oppinion, seems similar to the argument on why the friend keyword in C++ can increase encapsulation. – jmrah Sep 27 '16 at 12:28
  • Why do you think it shouldn't compile? – fgb Sep 27 '16 at 12:54

2 Answers2

3

Check this: https://docs.oracle.com/javase/tutorial/java/javaOO/nested.html. It says it increases encapsulation by allowing the static class to access private members of the top level class (sometimes you may need to do that). And a is private member of class A, which is in the scope of BreakOOP, which in turn makes it accessible inside class B.

uoyilmaz
  • 3,035
  • 14
  • 25
1

The Java Language Specification states:

A private class member or constructor is accessible only within the body of the top level class (§7.6) that encloses the declaration of the member or constructor.

Since classes A and B are defined within the body of BreakOOP that rule applies and B can see private members of A.

As for the OOP concepts: since A and B are static inner classes they don't have the special life-cycle relation with BreakOOP that true inner classes have (i.e. you don't need an instance of BreakOOP to create a new instance of A or B but they still have a somewhat special relation in that they have access to private members. If they should not have that kind of relationship then they shouldn't be inner classes but true top level classes.

Thomas
  • 87,414
  • 12
  • 119
  • 157