Способ вызова внутреннего класса внешним классом - PullRequest
0 голосов
/ 13 ноября 2018

Я знаю, что для создания экземпляра внутреннего класса члена у вас есть два разных конструктора:

Во-первых:

Outer out = new Outer();
Outer.Inner in = out.new Inner();

Второе:

Outer.Inner in = new Outer().new Inner();

Теперь я не знаю, почему этот код компилируется:

public class Outer {

    private String greeting="Hi";

    protected class Inner {
        public int repeat=3;

        public void go() {
            for (int i =0; i<repeat; i++) {
                System.out.println(greeting);
            }
        }
    }

    public void callInner() {
        Inner in = new Inner(); //in my opinion the correct constructor is Outer.Inner in = new Inner()
        in.go();
    }

    public static void main(String[] args) {
        Outer out = new Outer();
        out.callInner();

    }
}

Почему он компилируется?

Большое спасибо!

Ответы [ 4 ]

0 голосов
/ 13 ноября 2018

Когда вы вызываете метод callInner, вы фактически находитесь в области действия Outer класса.И причина, по которой компилятор принимает вызов new Inner(), точно такая же, почему вам не нужно явно указывать, из какого класса происходит ваша воображаемая статическая переменная (когда это часть того же класса, который вы вызываете).См. Пример ниже:

public class Outer {
  private static int x = 1;

  private void innerCall() {
    x++;
  }
}

В вышеприведенном случае вы делаете то же самое, что и в вашем примере, за исключением того, что вы используете класс, а не переменную (что здесь не очень важно).Ваш синтаксис был бы необходим, если бы вы хотели получить доступ к классу / переменной извне класса (области видимости).Тогда это будет выглядеть следующим образом:

public class Outer {
  public static int x = 1;
}

Outer.x++;

Выше вы должны явно указать, из какой области вы хотите получить доступ к вашей переменной x.Это как если бы вы хотели получить доступ к файлу из данного каталога.Если вы находитесь в этом каталоге, вы просто получаете доступ к файлу по его имени.Однако, когда вы находитесь за его пределами, вы должны также написать имя каталога, чтобы увидеть файл, который вы хотите получить.

0 голосов
/ 13 ноября 2018

Первый основной метод будет называться

public static void main(String[] args){
        Outer out = new Outer();
        out.callInner();
}

отсюда вы создаете объект класса Outer и вызываете метод callInner, как показано ниже

public void callInner() {
        Inner in = new Inner(); //in my opinion the correct constructor is Outer.Inner in = new Inner()
        in.go();
    }

, и теперь вы создали объектВнутренний и вызываемый метод go.

 protected class Inner {
        public int repeat=3;

        public void go() {
            for (int i =0; i<repeat; i++) {
                System.out.println(greeting);
            }
        }
    }

, так что это простой вызов, все находятся в одной области видимости.поэтому необходимо для внешнего. Внутренняя концепция для вызова.

Важно понимать, что Внешнее и Внутреннее связаны.Более конкретно, вам необходим экземпляр Outer для создания экземпляра Inner.

0 голосов
/ 13 ноября 2018

Как показывает ваше объяснение, вам нужен экземпляр Outer для создания экземпляра Inner.Поскольку метод callInner является методом экземпляра Outer (он не объявлен static), уже существует экземпляр Outer присутствует: this

Код также может быть записан какчто:

public void callInner() {
    Outer out = this;
    Inner in = out.new Inner();
    in.go();
}

Теперь код выглядит аналогично вашему первому примеру.

Но давайте сохраним код, как показано:

public void callInner() {
    Inner in = new Inner();
    in.go();
}

Теперь, если мы посмотрим подЭто в основном то же самое:

 public void callInner();
   Code:
      0: new           #21                 // class playground/Outer$Inner
      3: dup
      4: aload_0
      5: invokespecial #23                 // Method playground/Outer$Inner."<init>":(Lplayground/Outer;)V
      8: astore_1
      9: aload_1
     10: invokevirtual #26                 // Method playground/Outer$Inner.go:()V
     13: return

В строке 4 мы получаем aload_0, который загружает в экземплярах методов this.


Сравните: Уроки Java - пример внутреннего класса

0 голосов
/ 13 ноября 2018

Поскольку вы создаете экземпляр Inner в области действия Outer (внутри метода экземпляра), вам не нужно явно создавать экземпляр ссылки на классы Outer, как в вашем примере:

Outer.Inner in = new Outer().new Inner();

Можно создать экземпляр, просто ссылаясь на Inner:

 Inner in = new Inner();

Это относится ко всем методам экземпляра в классе, если они не являются статичными.

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