Статические переменные в нестатических внутренних классах - PullRequest
4 голосов
/ 12 февраля 2011

Сначала я хотел спросить Почему Java запрещает статические поля во внутренних классах? , но вопрос уже есть.Причина, которую я привел для их необходимости (serialVersionUID), была устранена ответом Божо.Однако мне все еще любопытно:

Разве статические поля запрещены только в исходном коде или также в файле класса?

Кстати, убедительная причина, почему этозапрещено, еще предстоит изобрести.В Си есть статические переменные, разрешенные даже внутри функций.Срок их службы такой же, как и у любой другой статической переменной, только у них другая видимость.То же самое будет работать и в Java.

Ответы [ 3 ]

5 голосов
/ 12 февраля 2011

Внутренние классы могут определять статические поля:

Внутренние классы могут не объявлять статические члены, если они не являются постоянными полями времени компиляции (§15.28).

Следовательно, вы можете определить серийный идентификатор версии.

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

3 голосов
/ 12 февраля 2011

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

Это было бы сбивающим с толку, хотя:

class X
    class Y
        static int z;

X x1 = new X();
X.Y y1 = x1.new Y();    

X x2 = new X();
X.Y y2 = x2.new Y();    
X.Y y3 = x2.new Y();    

Интуитивно, y2 и y3 должны иметь одинаковые z, но должны ли они быть одинаковыми z, видимыми y1?


Концептуально внутренний класс действителен только во внешнем экземпляре. Можно даже предположить, что JVM выгружает его, когда внешний экземпляр GC'ed; аргумент, приведенный в [1] против выгрузки класса, не применяется, потому что у внутренних классов нет статической переменной или статического инициализатора.

Однако реальность такова, что существует один класс, общий для всех внутренних экземпляров, независимо от внешних экземпляров. Это, безусловно, правда: y1.getClass()==y2.getClass()==y3.getClass().

Можно утверждать, что языковая спецификация диктует, что это правда: [2]

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

Класс y1 и класс y2 имеют один и тот же загрузчик классов, двоичное имя X.Y четко определено и не зависит от внешнего экземпляра. Таким образом, у y1 и y2 должен быть один и тот же класс времени выполнения.

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


[1] http://java.sun.com/docs/books/jls/third_edition/html/execution.html#12.7

[2] http://java.sun.com/docs/books/jls/third_edition/html/typesValues.html#4.3.4

1 голос
/ 28 октября 2012

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

Основное правило

  1. статический внутренний класс не допускает статические методы статический внутренний класс
  2. статический внутренний класс позволяет все от статического до нестатического
...