We have to distinguish between the source code and the JVM level.
- At the source code level, the inner class - Innercan 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- Enclosingclass. Just like any other class, this- Enclosing$Innerclass 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.