Почему внутренние классы не могут объявлять статические члены?

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

Мне интересно, почему внутренние классы не могут объявить статические члены, например, какое-то поле private static, которое экземпляр этого внутреннего класса мог бы разделить с другими экземплярами того же внутреннего класса? это просто реализация вещей в Java, которые нужно воспринимать как должное, или что-то еще?


person Dmitry Berdnikov    schedule 18.12.2011    source источник
comment
Я не знаю Java, и меня удивило, что внутренний класс связан с экземпляром внешнего класса.   -  person Armen Tsirunyan    schedule 19.12.2011
comment
@Armen: нестатический внутренний класс действительно похож на обычный внутренний класс с неявным указателем на экземпляр внешнего класса.   -  person Oliver Charlesworth    schedule 19.12.2011
comment
@ArmenTsirunyan несколько часов назад это тоже было неожиданностью для меня =) теперь я прошу здесь некоторых квестов заполнить пробелы в понимании концепций Java...   -  person Dmitry Berdnikov    schedule 19.12.2011


Ответы (5)


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

Кроме того, эта цитата может быть не совсем правильной: я считаю, что вы можете объявить статический serialVersionUID во внутреннем классе.

person jtahlborn    schedule 18.12.2011
comment
Да, это ограничение компилятора, а не что-то присущее JVM. Внутренние классы — это главный ключ, и на самом деле нет разницы между внутренними и внешними на уровне JVM. - person Hot Licks; 19.12.2011
comment
В частности, вы можете объявить статические поля, которые являются константами времени компиляции, которыми должен быть serialVersionUID. - person Michael Borgwardt; 19.12.2011
comment
Разве помещение вашей переменной в класс, которому она логически принадлежит, не является веской причиной для ее поддержки? - person Eric Lindauer; 29.05.2013
comment
@EricLindauer - не знаю, спросите у разработчиков спецификации языка Java. - person jtahlborn; 29.05.2013
comment
Разве инкапсуляция не является веской причиной для ее разрешения? Я предпочитаю держать свои поля как можно ближе к тому месту, где я их использую, не загрязняя внешний класс. - person Hummeling Engineering BV; 08.06.2015
comment
@HummelingEngineering - как я уже сказал в своем предыдущем комментарии, я не защищаю это решение и, конечно же, не несу за него ответственности. я просто посыльный. Ваш вопрос следует адресовать разработчикам языка Java. - person jtahlborn; 08.06.2015
comment
@jtahlborn - мой комментарий не был адресован вам, он просто размышлял о дизайне Java. - person Hummeling Engineering BV; 08.06.2015

Поскольку Спецификация языка Java говорит Итак:

Внутренний класс — это вложенный класс, который явно или неявно не объявлен статическим. Внутренние классы не могут объявлять статические инициализаторы (§8.7) или интерфейсы-члены. Внутренние классы не могут объявлять статические члены, если они не являются постоянными полями времени компиляции (§15.28).

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

person Michael Borgwardt    schedule 18.12.2011
comment
Действует ли это ограничение для внутренних классов static? - person ; 19.12.2011
comment
@pst: по определению не существует статического внутреннего класса. Смотрите первое предложение, которое я процитировал. - person Michael Borgwardt; 19.12.2011
comment
Э-э, статический вложенный класс. - person ; 19.12.2011
comment
@pst: если вы перейдете по ссылке на спецификацию, вы обнаружите, что в ней прямо говорится, что вложенные классы, которые не являются внутренними классами, могут свободно объявлять статические члены в соответствии с обычными правилами языка программирования Java. - person Michael Borgwardt; 19.12.2011
comment
проголосуйте за ясность по этому вопросу. Несмотря на ключевое слово static, они на самом деле не являются статическими. - person Daniel B. Chapman; 22.12.2011

Почему внутренние классы не могут объявлять статические члены?

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

image ›› две области внутри внешнего класса

person Lucas de Lima    schedule 13.09.2020

Внутренний class не может объявлять поля static, если только они не являются константами времени компиляции. Следовательно, если вы объявите поле static как final, оно будет работать.

class Foo {
    class Test {
       final static int i = 10;
    }
}

будет компилироваться и работать отлично

Поля static могут быть объявлены только в типах static или верхнего уровня. Следовательно, (чистая) переменная static может быть объявлена ​​только в static class.

person sonal    schedule 24.06.2014

Это привело бы к конфликту интересов, чтобы иметь статическую переменную-член внутри внутреннего класса. Вообще говоря, внутренний класс должен иметь экземпляр объекта внешнего или внешнего класса, прежде чем он может быть создан. Статическая переменная-член предполагает, что вам даже не нужен экземпляр объекта для этого конкретного класса, внутреннего класса в данном случае, но этот класс, от которого зависит внутренний класс, может сосуществовать только с экземпляром внешнего класса. Вы видите, где в споре возникает конфликт интересов? Однако вы можете создать статическую переменную-член внутри внутреннего класса, объявив внутренний класс статическим, что означает, что внутреннему классу больше не нужно сосуществовать с объектом внешнего класса.

public class A {

   public static class B {

       private static JPanel myJPanel;

   }

}
person EVAC-Q8R    schedule 18.12.2011
comment
Почему B, объявляющий статический член, каким-то образом означает, что он не зависит от включающего экземпляра A? Они кажутся ортогональными. - person Sean Owen; 19.12.2011
comment
@EVAC-Q8R Думаю, я понимаю, что ты имеешь в виду. для доступа к статическому члену внутреннего класса это будет что-то вроде OuterClassInstanceName.InnerClassTypeName.innerClassStaticMemberName, что определенно будет неудобной смесью. С другой стороны, по-прежнему можно получить доступ к статическим членам через экземпляр в Java (что обычно не требуется). Так почему бы тогда не использовать вот такую ​​конструкцию: OuterClassInstanceName.new InnerClass().innerClassStaticMemberName - person Dmitry Berdnikov; 19.12.2011
comment
@ Шон - я объявил внутренний класс B статическим, а не общедоступным классом B, что означает, что ему больше не нужен охватывающий объект для его создания ... не из-за статического экземпляра JPanel myJPanel. - person EVAC-Q8R; 19.12.2011