Анонимные переменные класса

Я экспериментировал с анонимными классами сегодня. Когда я делаю System.out.println(super.x);, он печатает 12, и когда я использую System.out.println(x);, он печатает 4. Я думал, что super.x будет печатать 4 и задавался вопросом, может ли кто-нибудь объяснить мне, почему это?

public class AnonClass {

    private int x = 1;

    public AnonClass(int x) {
        this.x = x;
    }

    public static void main(String[] args) {
        AnonClass test = new AnonClass(4);
        test.testMethod();
    }

    public void testMethod() {

        AnonClass anon = new AnonClass(12) {
            {
                System.out.println(super.x); //Prints 12
                System.out.println(x); //prints 4
            }
        };

    }
}

Ответ 1

Когда вы определяете такой анонимный класс внутри class AnonClass:

AnonClass anon =
    new AnonClass(12) {
      {
        System.out.println(super.x); //Prints 12
        System.out.println(x); //prints 4
      }
    };

компилятор создаст класс примерно так:

class AnonClass$1 extends AnonClass {
  final AnonClass enclosed;

  AnonClass$1(AnonClass enclosed, int x) {
    super(x);
    System.out.println(super.x);
    System.out.println(enclosed.x);
    this.enclosed = enclosed;
  }
}

а затем вызовите его так:

AnonClass anon = new AnonClass$1(this, 12);

Обратите внимание, что вызов суперконструктора (super(x);) происходит до содержимого инициализатора экземпляра (строки System.out.println).

Таким образом, поле AnonClass.x инициализируется суперконструктором 12, а затем его значение печатается как 12 через System.out.println(super.x);.

Затем System.out.println(x) фактически ссылается на x в прилагаемом экземпляре AnonClass, значение которого равно 4.

Причина, по которой он не печатает 12 снова, заключается в том, что x есть private; и как говорится в JLS Sec 8.2:

Члены класса, объявленные как private, не наследуются подклассами этого класса.

Таким образом, нет AnonClass$1.x для печати; единственным идентификатором в области под названием x является AnonClass.x.

Ответ 2

Здесь у вас есть два класса: обычный класс AnonClass и анонимный класс AnonClass$1, расширяющий AnonClass

Оба этих класса имеют поле x

У вас также есть два объекта: один из типов AnonClass, созданный внутри метода main с x = 4 и второй тип AnonClass$1, созданный внутри testMethod() с x = 12

Когда вы печатаете значение super.x, вы получаете доступ к полю x второго объекта; но значение x принадлежит первому объекту, потому что ваш класс не является static и содержит неявную ссылку на экземпляр внешнего класса

Ссылка: Вложенные классы в Java