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