Тило добавил хороший ответ на ваш первый вопрос «Как это возможно?». Я хотел бы остановиться подробнее на втором заданном вопросе: почему такое поведение разрешено?
Для начала, давайте просто проясним, что это поведение не ограничивается внутренними классами, которые по определению являются нестатическими вложенными типами. Такое поведение разрешено для всех вложенных типов, включая вложенные перечисления и интерфейсы, которые должны быть статическими и не могут иметь включающий экземпляр. По сути, эта модель является упрощением вплоть до следующего утверждения: вложенный код имеет полный доступ к вложенному коду - и наоборот.
Так почему тогда? Я думаю, что пример лучше проиллюстрирует это.
Подумайте о своем теле и своем мозге. Если вы вводите героин в руку, ваш мозг становится все сильнее. Если область миндалины вашего мозга увидит то, что, по его мнению, представляет угрозу для вашей личной безопасности, скажем, например, оса, он заставит ваше тело развернуться и побежать к холмам, чтобы вы не «подумали» об этом дважды.
Таким образом, мозг является неотъемлемой частью тела - и, как ни странно, наоборот. Использование контроля доступа между такими тесно связанными объектами лишает их права на отношения. Если вам нужен контроль доступа, то вам нужно разделить классы по-настоящему на отдельные единицы. До тех пор они единое целое. Движущим примером для дальнейших исследований было бы посмотреть, как Iterator
обычно реализуется Java .
Неограниченный доступ от вложенного кода к вложенному коду делает его по большей части довольно бесполезным для добавления модификаторов доступа к полям и методам вложенного типа. Это добавляет беспорядок и может дать ложное чувство безопасности для новичков в языке программирования Java.