Thilo a ajouté une bonne réponse à votre première question "Comment est-ce possible?". Je souhaite développer un peu la deuxième question posée: pourquoi ce comportement est-il autorisé?
Pour commencer, soyons parfaitement clairs sur le fait que ce comportement n'est pas limité aux classes internes, qui par définition sont des types imbriqués non statiques. Ce comportement est autorisé pour tous les types imbriqués, y compris les énumérations imbriquées et les interfaces qui doivent être statiques et ne peuvent pas avoir d'instance englobante. Fondamentalement, le modèle est une simplification jusqu'à la déclaration suivante: le code imbriqué a un accès complet au code englobant - et vice versa.
Alors, pourquoi alors? Je pense qu'un exemple illustre mieux ce point.
Pensez à votre corps et à votre cerveau. Si vous injectez de l'héroïne dans votre bras, votre cerveau devient haut. Si la région de l'amygdale de votre cerveau voit ce qu'il croit être une menace pour votre sécurité personnelle, disons une guêpe par exemple, il fera tourner votre corps dans l'autre sens et courra vers les collines sans que vous «y pensiez» deux fois.
Ainsi, le cerveau est une partie intrinsèque du corps - et curieusement, l'inverse aussi. L'utilisation du contrôle d'accès entre ces entités étroitement liées renonce à leur revendication de relation. Si vous avez besoin d'un contrôle d'accès, vous devez séparer davantage les classes en unités vraiment distinctes. Jusque-là, ils sont la même unité. Un exemple de conduite pour d'autres études serait d'examiner comment un Java Iterator
est généralement implémenté.
L'accès illimité du code englobant au code imbriqué rend, pour la plupart, plutôt inutile d'ajouter des modificateurs d'accès aux champs et aux méthodes d'un type imbriqué. Cela ajoute de l'encombrement et pourrait donner un faux sentiment de sécurité aux nouveaux arrivants du langage de programmation Java.