We have to distinguish between the source code and the JVM level.
At the source code level, the inner class Inner
can access e.g. private fields of the enclosing class Enclosing
.
At the JVM level, there is no concept of an inner class: an inner class is just an independent class with a special name (typically containing a $ sign, e.g. Enclosing$Inner
), located in the same package as the Enclosing
class. Just like any other class, this Enclosing$Inner
class can't access Enclosing
's private fields. To allow access to the private fields (as source code level demands), the compiler plays a trick: it secretly adds getters and setters to the fields, unter synthetic names (not the classical getField()
and setField()
names), and has the inner class use these access methods instead of a direct field access. And as both classes are in the same package, the access methods need to allow at least package visibility, and that's how they are created by the compiler.
So, these methods make it possible for any other class declared in the same package, to access private fields of the Enclosing
class, breaking the normal encapsulation of private fields.
It's up to you to decide if that risk matters, as from within Java there are other possibilities to break the access rules. So, personally I've always happily created inner classes where appropriate from an architectural point of view.