views:

498

answers:

5

I observed that Outer classes can access inner classes private instance variables. How is this possible? A sample code demonstrating the same is explained below::

class ABC{
    class XYZ{
        private int x=10;
    }

    public static void main(String... args){
        ABC.XYZ xx = new ABC().new XYZ();
        System.out.println("Hello :: "+xx.x); ///Why is this allowed??
    }
}

Can anyone explain why this behavior is allowed?

A: 

Because your main() method is in the ABC class, which can access its own inner class.

aberrant80
+3  A: 

The inner class is just a way to cleanly separate some functionality that really belongs to the original outer class. They are intended to be used when you have 2 requirements:

  1. Some piece of functionality in your outer class would be most clear if it was implemented in a separate class.
  2. Even though it's in a separate class, the functionality is very closely tied to way that the outer class works.

Given these requirements, inner classes have full access to their outer class. Since they're basically a member of the outer class, it makes sense that they have access to methods and attributes of the outer class -- including privates.

Kaleb Brasee
+1  A: 

The inner class is (for purposes of access control) considered to be part of the containing class. This means full access to all privates.

The way this is implemented is using synthetic package-protected methods: The inner class will be compiled to a separate class in the same package (ABC$XYZ). The JVM does not support this level of isolation directly, so that at the bytecode-level ABC$XYZ will have package-protected methods that the outer class uses to get to the private methods/fields.

Thilo
A: 

Access restrictions are done on a per class basis. There is no way for a method declared in a class to not be able to access all of the instance/class members. It this stands to reason that inner classes also have unfettered access to the members of the outer class, and the outer class has unfettered access to the members of the inner class.

By putting a class inside another class you are making it tightly tied to the implementation, and anything that is part of the implementation should have access to the other parts.

TofuBeer
+3  A: 

The logic behind inner classes is that if you create an inner class in an outer class, that's because they will need to share a few things, and thus it makes sense for them to be able to have more flexibility than "regular" classes have.

If, in your case, it makes no sense for the classes to be able to see each other's inner workings - which basically means that the inner class could simply have been made a regular class, you can declare the inner class as static class XYZ. Using static will mean they will not share state (and, for example new ABC().new XYZ() won't work, and you will need to use new ABC.XYZ().
But, if that's the case, you should think about whether XYZ should really be an inner class and that maybe it deserves its own file. Sometimes it makes sense to create a static inner class (for example, if you need a small class that implements an interface your outer class is using, and that won't be helpful anywhere else). But at about half of the time it should have been made an outer class.

abyx