Неправильный тип поля для «этого» во внутреннем классе в JDK6? - PullRequest
0 голосов
/ 01 сентября 2011

Я столкнулся со странным результатом и не уверен, является ли это ошибкой в ​​Java или ожидаемым поведением.У меня есть внутренний класс, в котором я использовал отражение, чтобы получить объявленные поля (class.getDeclaredFields ()).Однако, когда я перебираю список полей и проверяю отдельные типы, поле «this» возвращает внешний класс, а не внутренний класс.

Это ожидаемое поведение?Мне это кажется довольно странным.

Пример:

import java.lang.reflect.Field;

public class OuterClass {

    public class InnerClass{
        public String innerClassString;
            public InnerClass innerClass;

    }


    public static void main(String[] args) {

        // print the fields of the inner class
        for( Field field : OuterClass.InnerClass.class.getDeclaredFields())
            System.out.println( field.getName() + "   :::   " + field.getType());
    }
}

Вывод:

innerClassString   :::   class java.lang.String
innerClass   :::   class OuterClass$InnerClass
this$0   :::   class OuterClass

Я ожидал, что этот $ 0 будет иметь тип OuterClass.InnerClass.

Это ошибка Java?Есть ли способ обойти это неожиданное поведение?

Спасибо,

Эрик

Ответы [ 2 ]

9 голосов
/ 01 сентября 2011

Каждый нестатический внутренний класс поддерживает невидимый ивар, который содержит ссылку на внешний класс, для которого он был создан.Вот что такое this$0.

Измените InnerClass на public static class и посмотрите на разницу.

Для ясности, Oracle рекомендует следующую терминологию:

http://download.oracle.com/javase/tutorial/java/javaOO/nested.html

Терминология: вложенные классы делятся на две категории: статические и нестатические. Вложенные классы, которые объявлены статическими , просто называются статическими вложенными классами . Нестатические вложенные классы называются внутренними классами .

...

Экземпляр InnerClass может существовать только в экземпляре OuterClass иимеет прямой доступ к методам и полям окружающего его экземпляра....

Чтобы создать экземпляр внутреннего класса, вы должны сначала создать экземпляр внешнего класса.Затем создайте внутренний объект во внешнем объекте с этим синтаксисом:

OuterClass.InnerClass innerObject = outerObject.new InnerClass();

===

Есть ли тогда доступ к переменной $ 0 изнутривнутренний класс, если хотите?

В методе внутреннего класса вы можете сказать:

OuterClass outer = OuterClass.this;

или

System.out.println(OuterClass.this.toString());

Это особый вариантиз this - OuterClass.this - обращается к this$0 ivar - он вернет экземпляр OuterClass.Обратите внимание, что это отличается от использования обычного this внутри метода InnerClass, который будет возвращать текущий экземпляр InnerClass.

===

Кроме того, какя могу определить, обрабатываю ли я поле "this $ 0" без сравнения строк?

Мне неясно, что вы пытаетесь сделать, поэтому я не могу порекомендовать, как добиться того, что выхочу.

0 голосов
/ 11 сентября 2017

этот $ 0 является ссылкой во внутреннем классе, который сообщает, какой экземпляр внешнего класса использовался для создания текущего экземпляра внутреннего класса.
Более подробно этот вопрос можно увидеть.

Что означает, если переменная имеет имя «this $ 0» в IntelliJ IDEA при отладке Java?

...