Содержит ли анонимный класс, реализующий частный абстрактный класс stati c, ссылку на его включающий класс, когда он создан в нестатическом контексте c? - PullRequest
0 голосов
/ 09 июля 2020

Я читал в Эффективном Java, 3-м издании, что анонимные классы, созданные в нестатистических c контекстах, содержат невидимые ссылки на их включающий класс. Верно ли то же самое для анонимного класса, реализующего внутренний класс c статики, но созданного с помощью нестационарной c функции?

Например:

class Concept {
    public Response func() {
        return new Inner {
            @Override
            protected Object bar() {
                return new Object;
            }
        }.invoke();
    }

    private abstract static Inner {
        protected Response invoke() {
            return Response.status(SC_OK).entity(bar).build();
        }

        protected abstract Object Response bar();
    }
}

Имеет ли анонимный класс, созданный в методе fun c (), содержит ссылку на включающий его класс Concept?

1 Ответ

2 голосов
/ 09 июля 2020

Согласно JLS §15.9.5 :

Анонимный класс всегда является внутренним классом (§8.1.3); это никогда не будет c (§8.1.1, §8.5.1).

Обратите внимание, что в JLS нет исключений для случая, когда анонимный класс расширяет static class.

Следовательно, он должен иметь ссылку на экземпляр включающего его класса.

Я упростил ваш пример, превратив его в законный автономный класс Java, скомпилировал его и посмотрел байт-коды для анонимного класса, используя javap -c. Код конструктора делает ссылку на включающий класс и сохраняет в скрытом поле (this$0).

class Concept {
    public Inner func() {
        return new Inner() {
            @Override
            protected Object bar() {
                return new Object();
            }
        };
    }

    private abstract static class Inner {
        protected abstract Object bar();
    }
}
javap -c 'Concept$1.class'
Compiled from "Concept.java"
class Concept$1 extends Concept$Inner {
  final Concept this$0;

  Concept$1(Concept);
    Code:
       0: aload_0
       1: aload_1
       2: putfield      #1                  // Field this$0:LConcept;
       5: aload_0
       6: invokespecial #2                  // Method Concept$Inner."<init>":()V
       9: return

  protected java.lang.Object bar();
    Code:
       0: new           #3                  // class java/lang/Object
       3: dup
       4: invokespecial #4                  // Method java/lang/Object."<init>":()V
       7: areturn
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...