Java внутренние/внешние вопросы о классе о внешнем доступе частных переменных класса

У меня есть следующий класс Java:

class Outer
{
    private Integer a;
    private Long b;

    class Inner
    {
        public void foo()
        { 
            System.out.println("a and b are " + a + " " + b);
        }
    }
}

когда я работаю javap Внешний и Outer$Inner, я получаю следующее:

C:\test>javap Outer
Compiled from "Outer.java"
class Outer extends java.lang.Object{
    Outer();
    static java.lang.Integer access$000(Outer);
    static java.lang.Long access$100(Outer);
}

C:\test>javap Outer$Inner
Compiled from "Outer.java"
class Outer$Inner extends java.lang.Object{    
    final Outer this$0;
    Outer$Inner(Outer);
    public void foo();
}

У меня есть два вопроса:

1) почему компилятор Java генерирует статические методы, которые берут 'Внешний' параметрический усилитель, во внешнем классе, для доступа к его частным переменным? почему не методы экземпляра, которые внутренний класс может легко назвать через его участника за 0 this$?

2) почему 0 this$ во внутреннем классе сделаны финалом? что произойдет, если это не будет окончательным?

Спасибо и всего наилучшего.

16
задан Danubian Sailor 6 December 2011 в 10:12
поделиться

2 ответа

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

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

Правка: что касается методов access$000, то ключом к ключу является то, что они являются доступом к пакетам и принимают в качестве аргумента External. Таким образом, когда код в Inner вызывает, скажем, Inner.this.a, он на самом деле вызывает Inner.access$000(this$0). Таким образом, эти методы дают доступ к private членам внешнего класса к внутреннему классу.

14
ответ дан 30 November 2019 в 22:43
поделиться

1) Они должны быть статическими , чтобы не переопределяться в каком-нибудь подклассе. Надеюсь, вы понимаете.

Shrini, из вашего комментария кажется, что есть необходимость объяснить вещи, чтобы избежать некоторых неправильных представлений. Прежде всего, знайте, что нельзя переопределить методы static. Переопределение эксклюзивно в объектах, и оно есть для того, чтобы облегчить полиморфизм. Тогда как статические методы относятся к классу. Нашел пару хороших ресурсов для поддержки моего аргумента и чтобы вы поняли, что статические методы не могут быть переопределены.

Теперь для вашего второго реторта, вы правы, говоря, что они имеют доступ на уровне пакета и не могут быть переопределены в подклассах вне пакета. Но я не знаю, почему вы пренебрегаете случаем, когда подклассы/ы существуют в одном и том же пакете. Это обоснованный случай, IMO. На самом деле, было бы абсурдно называть метод как access$000() или что-то в этом роде, в реальной работе. Но не стоит недооценивать шанс случайного переопределения. Может быть случай, когда подкласс Outer, скажем SubOuter, тоже имеет внутренний класс. Я не пытался javap сам, просто догадываясь.

<дополнение>

2) Даже если вы думаете, что он не будет модифицирован, технически есть возможность, как уже указывал cletus, использование final может обеспечить легкую оптимизацию компилятором.

2
ответ дан 30 November 2019 в 22:43
поделиться
Другие вопросы по тегам:

Похожие вопросы: