Непонимание вложенных типов - PullRequest
0 голосов
/ 17 декабря 2011

Я готовлюсь к SCJP и запутался, читая о вложенных типах.Есть простой вопрос, и я не могу понять результат.

public class Outer {
    private int innerCounter;

    class Inner {
        Inner() {
            innerCounter++;
        }

        public String toString() {
            return String.valueOf(innerCounter);
        }
    }

    private void multiply() {
        Inner inner = new Inner();
        this.new Inner();
        System.out.print(inner);
        inner = new Outer().new Inner();
        System.out.println(inner);
    }

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

Он печатает

21

Зная, что счетчик не статичен, как рассматриваются первые два объектакак один объект?

Ответы [ 6 ]

3 голосов
/ 17 декабря 2011

Нестатический внутренний класс имеет доступ ко всем членам своего внешнего класса. Похоже, это действительно было определено как:

class Outer {

    private int innerCount;

    class Inner() {
        private final Outer owner;

        public Inner(Outer owner) {
            this.owner = owner;
            this.owner.innerCount++;
        }
    }

    private void multiply() {
        Inner inner = new Inner(this);
        ...
    }
}

Итак, позвольте мне аннотировать ваш метод:

private void multiply() {
    // this.innerCount = 0

    Inner inner = new Inner();
    // this.innerCount = 1

    this.new Inner();
    // this.innerCount = 2

    System.out.print(inner);  // Prints "2"

    // Creates a new Outer (with a separate innerCount)
    // then uses that to create a new Inner, which updates
    // the new innerCount
    inner = new Outer().new Inner();
    // inner.innerCount = 1

    System.out.println(inner);  // Prints "1"
}
1 голос
/ 17 декабря 2011

Для создания нестатического внутреннего класса требуется ссылка на «внешний» класс. В случае метода multiply у вас уже есть активный экземпляр Outer, и поэтому оба значения new Inner() и this.new Inner() относятся к одному и тому же объекту Outer, но сами являются уникальными объектами. По сути, все вложенные нестатические экземпляры класса внутренне всегда связаны с экземпляром класса Outer.

1 голос
/ 17 декабря 2011

Я предполагаю, что вы говорите о Внутренних объектах.Ну, они не рассматриваются как один объект, но они связаны с тем же внешним объектом (это)

0 голосов
/ 17 декабря 2011

Я не понимаю, где ваша путаница, но я постараюсь объяснить, почему она печатает 21. Пожалуйста, смотрите встроенные комментарии

Примечание: объекты названы для пояснения.


public class Outer {
private int innerCounter;</p>

<p>class Inner {
    Inner() {
        innerCounter++;
    }</p>

<pre><code>public String toString() {
    return String.valueOf(innerCounter);
}

}

private void multiply () {Inner inner = new Inner (); // Step2: Создать первый внутренний объект // Давайте назовем его innerA // Обратите внимание, что innerA созданusing outerA // Увеличивает переменную innerCount для outerA this.new Inner ();// step3 создаем второй внутренний объект // Давайте назовем его innerB // Обратите внимание, что innerB создан с использованием externalA // Увеличивает переменную innerCount для outerA

System.out.print(inner); //step 3 print innerCount from outerA
//With the two increments done, prints 2
inner = new Outer().new Inner(); //step4 create second outer object
//Lets call it outerB.
//Lets call this third inner object as InnerC
//InnerC creation increments OuterB's innerCount variable (so value 1)
//Assigned now to the old reference
System.out.println(inner); // prints the value of innerC

}

public static void main (String [] args) {new Outer (). Multiply ();// Step1: Создать первый внешний объект // Давайте назовем его OuterA

}}

0 голосов
/ 17 декабря 2011
Inner inner = new Inner();
Inner inner = this.new Inner();

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

private int number;

public int getNumber(){
    return this.number;
}

public int getNumber(){
    return number;
}

Здесь также в обоих методах используется один и тот же экземпляр, поэтому this не влияет на вывод.

0 голосов
/ 17 декабря 2011

Я не получил то, что вы называли «двумя первыми объектами», но innerCounter это поле Внешнего класса.

В вашем коде вы создаете два экземпляра Outer - здесь new Outer().multiply(); и здесь inner = new Outer().new Inner();.

Первый экземпляр Внешнего * innerCounter увеличивается, вызывая конструктор Inner два раза (Inner inner = new Inner(); и this.new Inner();), второй - только один раз (inner = new Outer().new Inner();).

Таким образом, вы получаете 2 и 1 в качестве вывода.

...