Внутренний класс Java со статическим методом - PullRequest
0 голосов
/ 25 июня 2019

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

public class OuterClass{
public static void main(String[] args)throws Exception{
    System.out.println(OuterClass.InnerClass.yearOfBorn);//works ok
    System.out.println(OuterClass.InnerClass.returnYearOfBorn());//not works
    System.out.println(OuterClass.InnerClass.returnYearOfBornAsPublic());//not works
}    
private final class InnerClass{
    private static final int yearOfBorn=13;
    private static int returnYearOfBorn(){
        return yearOfBorn;
    }        
    public static int returnYearOfBornAsPublic(){
        return yearOfBorn;
    }            
}

}

Оба статических методавыдает ошибку, утверждающую, что

модификатор 'static' разрешен только в объявлениях константных переменных

Я знаю, что в документах указано, что

Это описано в спецификации языка JavaРаздел §8.1.3

8.1.3 Внутренние классы и включающие в них экземпляры

An inner class is a nested class that is not explicitly or implicitly declared static. Inner classes may not declare static initializers (§8.7) or member interfaces. Inner classes may not declare static members, unless they are compile-time constant fields (§15.28).

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

Спасибо.

1 Ответ

2 голосов
/ 25 июня 2019

Нестатические внутренние классы имеют что-то особенное.

статические внутренние классы не имеют этого.классы верхнего уровня не имеют его.у любого внутреннего интерфейса или перечисления его нет.

Эта особая вещь - невидимое поле.

Это невидимое поле имеет тип Outer, и оно final.Он инициализируется первым в своем конструкторе, и, да, каждый конструктор нестатического внутреннего класса имеет магический невидимый параметр типа Outer, который служит в качестве этого поля.

Итак, когдавы пишете:

public class Outer {
    public class Inner {
    }
}

Компилятор скомпилирует этот код, как если бы вы на самом деле написали:

public class Outer {
    public static class Inner {
        private final Outer I_AM_MAGIC;

        public Inner(Outer outer) {
            this.I_AM_MAGIC = outer;
        }
    }
}

Вы можете увидеть эту скрытую магию, используя инструмент декомпиляции javap;введите -verbose и -private, и вы увидите это.Причина, по которой существует эта магия, заключается в том, что вы можете вызывать методы экземпляра вашего внешнего изнутри вашего внутреннего, но ... в каком экземпляре вы вызываете эти внешние методы?В этом скрытом экземпляре!

Обратите внимание, что этот экзотический, на первый взгляд странный код: someOuter.new Inner() на самом деле является допустимым кодом Java.При вызове new Inner() из нестатического контекста в Outer экземпляр this передается как невидимый параметр этому конструктору, но если вас там нет, код просто не компилируется вообще ...если вы не используете синтаксис outer.new Inner().

Причина, по которой компилятор не позволит вам добавить статические методы в Inner, заключается в том, что, как считается, это может привести к некоторой путанице.По сути, ответ на ваш вопрос звучит так: «Нет веских причин ... просто ... спецификация говорит, что компилятор java не должен этого разрешать, поэтому javac этого не позволяет».

Обратите внимание, что в действительностиНа самом деле эти нестатические внутренние классы - запутанная вещь.Я настоятельно рекомендую вам научить себя ВСЕГДА делать свои внутренние классы static, если вы действительно не знаете, что делаете.И даже тогда подумайте дважды.Тогда подумайте еще раз.Тогда, возможно, рассмотрите возможность создания нестатического внутреннего класса.

...