Использование имени внутреннего класса и имени объекта в Java
В следующем фрагменте кода, по-видимому, кажется, что он должен выпустить некоторую ошибку компиляции, но это не так:
class Outer {
public static class Inner {
static String obj = "Inner";
}
static Optional Inner = new Optional();
//The (inner) class name and the object name are same.
}
class Optional {
String obj = "Optional";
}
public class Main {
public static void main(String[] args) {
System.out.println(Outer.Inner.obj);
//Refers to the string inside the optional class
}
}
Класс Outer
имеет внутри себя статический класс с именем Inner
. Кроме того, он объявляет объект (статический) класса Optional
(static Optional Inner = new Optional();
)
Этот объект и имена классов (внутри класса Outer
) являются такими же, как Inner
. В программе отображается Optional
. Ожидается, что в выражении Outer.Inner.obj
в пределах main()
будет отображаться Inner
, но это не так. Однако фактический вывод Optional
относится к классу Optional
.
Одним из способов отображения Inner
является изменение имени объекта на что-то еще.
static Optional Inner1 = new Optional();
Из выводимого на экран вывода, кажется, что имя объекта (или переменная) выбрано над именем типа (класс Inner
), поскольку они имеют одинаковое имя. Какой именно случай применяется здесь?
Ответы
Ответ 1
Параграф 6.4.2 Спецификации языка Java содержит некоторую информацию о правилах, которые применяются в этом случае.
Простое имя может возникать в контекстах, где его потенциально можно интерпретировать как имя переменной, типа или пакета. В этих ситуациях в правилах раздела 6.5 указывается, что переменная будет выбрана в предпочтении к типу и что тип будет выбран в предпочтении к пакету. Таким образом, иногда бывает невозможно ссылаться на объявление видимого типа или пакета через его простое имя. Мы говорим, что такая декларация скрыта.
Это относится к пункту 6.5 Определение значения имени, в котором подробно описаны правила.
В вашем примере Outer.Inner
может ссылаться на тип вложенного класса с именем Inner
или на статическую переменную-член Inner
. Правила говорят, что переменная будет выбрана по типу.
Ответ 2
На самом деле это имя класса Outer $Inner.
Внутренние классы - это, по сути, взлом, введенный в Java 1.1. JVM на самом деле не имеет понятия внутреннего класса, поэтому компилятор должен его использовать. Компилятор генерирует класс B
"вне" класса A
, но в том же пакете, а затем добавляет к нему синтетические аксессоры/конструкторы, чтобы позволить A
получить к нему доступ.
Оформить следующее сообщение:
головоломка видимости внутреннего класса Java
Ответ 3
Подумайте, что у внутреннего класса действительно есть свой .java файл.
Это даст вам понять, почему он выбирает переменную над классом Inner.