Запрос о вложении классов в Java - PullRequest
3 голосов
/ 22 сентября 2019
public class Outer{
    public class Inner{
    }
}

public class Main {
    public static void main(String[] args) {
        Outer objOut = new Outer();
        //Outer.Inner object1= objOut.new Inner();  // runes without a problem
        //objOut.Inner object2= objOut.new Inner(); //gives error
    }
}

Это может показаться немного любительским, но в чем разница между Outer.Inner против objOut.Inner.

Ответы [ 3 ]

3 голосов
/ 22 сентября 2019

Вы не можете использовать имя переменной в качестве типа другой переменной, что вы пытаетесь сделать с objOut.Inner.Тип переменной - Inner (или, необязательно, Outer.Inner).

Поскольку Inner является внутренним классом , он связан с экземпляр его внешнего класса (его включающий экземпляр ).Когда вы создаете его экземпляр, вы можете при желании указать, с каким экземпляром объекта он связан, что вы и делаете с objOut.new Inner.

. Этот пример может помочь сделать его более понятным:

public class Example {
    private String str;

    public class Inner {
        void show() {
            // Show the string for the Example this Inner is part of
            System.out.println(Example.this.str);
        }
    }

    public Example(String s) {
        this.str = s;
    }

    public static void main(String[] args) {
        Example e1 = new Example("e1");
        Example e2 = new Example("e2");
        Inner i1 = e1.new Inner();
        i1.show(); // "e1"
        Inner i2 = e2.new Inner();
        i2.show(); // "e2"
    } 
}

Live Copy

Обратите внимание, как экземпляр i1 Inner получает e1 в качестве включающего его экземпляра Example и, таким образом, видит e1str, но i2 получает e2 в качестве включающего его экземпляра, поэтому он видит e2 str.

Я предлагаю этот учебник по Java для получения дополнительной информации.


¹ Иногда это не является обязательным, например, в моем классе Example, указанном выше, так как там, где используется new Inner, нет экземпляра по умолчанию, который он мог бы использовать.Это было бы необязательно в экземпляре метода Example, но не в этом static методе.

2 голосов
/ 22 сентября 2019

Этот:

Outer.Inner = objOut.new Inner();

не будет компилироваться, но если вы измените его на:

Outer.Inner object = objOut.new Inner();

, это будет означать создание экземпляра внутреннего класса, который имеет ссылку на класс Outer- objOut будет экземпляром класса Outer.

Также это:

objOut.Inner = objOut.new Inner();

не будет компилироваться, поскольку objOut, который является экземпляром класса Outer, не имеетpoperty Inner.

И не класс Outer знает экземпляр класса Inner - это экземпляр класса Inner, который знает экземпляр класса Outer, с помощью которого он был создан.

РЕДАКТИРОВАТЬ

Строка:

objOut.Inner object2= objOut.new Inner();

не будет компилироваться, поскольку идентификатор типа Inner принадлежит Outer классу , а не экземпляруэтого класса.

2 голосов
/ 22 сентября 2019

Оба не компилируются.

Чтобы сделать первый компилятор, необходимо объявить переменную и дать имя этой переменной.

Outer.Inner obj = objOut.new Inner();

Последний не будет 't скомпилировать, даже если вы сделали этот шаг, так как objOut.Inner не является ни типом (потому что первичное выражение objOut не является типом), ни допустимым именем (потому что . не допускается в идентификаторе (jls-3.8) ).

Упрощенное правило (jls-14.4) для вашего случая будет

LocalVariableType VariableDeclaratorId [= VariableInitializer];
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...