Доступ к полю внешнего анонимного класса из внутреннего анонимного класса - PullRequest
5 голосов
/ 11 февраля 2009

Чтобы получить доступ к полю x внешнего класса A из внутреннего класса B, я понимаю, что вы можете использовать «A.this.x». Но что, если внешний класс также является анонимным? Например,

public class Main1 {
    public static void main(String[] args) {
        Comparable c1 = new Comparable(){
            int x = 3;
            public int compareTo(Object o) {
                Comparable c2 = new Comparable(){
                    int x = 4;
                    public int compareTo(Object o) {
                        return x;  // <-- THIS LINE
                    }
                };
                return c2.compareTo(o);
            }
        };
        System.out.println(c1.compareTo(null));
    }
}

Когда этот код выполняется, печатается значение 4, потому что это значение поля x c2. Тем не менее, я хотел бы изменить строку, помеченную «ЭТА ЛИНИЯ», чтобы она возвращала внешний класс x (то есть поле x в c1 со значением 3). Если бы внешний класс (то есть класс c1) был именованным классом A, то я мог бы заменить

return x;

с

return A.this.x;

Но поскольку внешний класс также является анонимным, у меня нет имени для использования.

Вопрос: Есть ли способ изменить строку, помеченную «ЭТА ЛИНИЯ», чтобы она ссылалась на поле x c1, а не на c2, без изменения анонимных классов в именованные классы?

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

Ответы [ 5 ]

4 голосов
/ 11 февраля 2009

Я бы не стал скрывать другую переменную, выбрав имя, отличное от x.

2 голосов
/ 11 февраля 2009

Простой ответ - не скрывать переменные:

public static void main(String[] args) {
    Comparable c1 = new Comparable() {
        int x = 3;
        public int compareTo(Object o) {
            Comparable c2 = new Comparable() {
                //changed this name
                int y = 4;
                public int compareTo(Object o) {
                    return x;
                }
            };
            return c2.compareTo(o);
        }
    };
    System.out.println(c1.compareTo(null));
}

Выход:

3

Учитывая, что вы работаете с сгенерированным кодом, эта опция для вас?

1 голос
/ 11 февраля 2009

Классы анонимные - безымянные. Нет доступа к их полям, используя ссылку на имя. Там нет имени.

1 голос
/ 11 февраля 2009

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

0 голосов
/ 11 февраля 2009

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

Это похоже на классический случай, когда что-то вроде Lisp's gensym облегчит задачу. Другими словами, пусть генератор кода использует разные идентификаторы для этих переменных - например, х1 и х2.

...