Почему статические поля (не окончательные) ограничены во внутреннем классе в java
Возможный дубликат:
Почему Java запрещает статические поля во внутренних классах?
Я прошел спецификацию и понял, что статический член во внутреннем классе не может быть статическим, который не является окончательной постоянной времени компиляции.
class HasStatic {
static int j = 100;
}
class myInnerClassTest {
class Inner extends HasStatic {
static final int x = 3; // OK: compile-time constant
static int y = 4; // Compile-time error: an inner class
}
static class NestedButNotInner{
static int z = 5; // OK: not an inner class
}
interface NeverInner {} // Interfaces are never inner
}
В то время как я получил от Почему у нас есть статические конечные члены, но у меня есть статический метод во внутреннем классе?, что он может наследовать статический член из класса владельца, Но почему это не должно быть? Какой основной ООП больно?
Ответы
Ответ 1
Ваш класс myInnerClassTest
не объявлен как статический. Итак, что это означало бы для него статическое поле?
Будет ли это
- то же самое для всех экземпляров независимо от экземпляра-экземпляра?
- то же самое для всех экземпляров этого внутреннего класса, имеющих один и тот же закрытый экземпляр?
На первый взгляд большинство программистов, вероятно, подумают, что это первый случай, в то время как логика инкапсуляции (нестатического) внутреннего класса должна, вероятно, привести к второму выбору. В любом случае (или оба с разными модификаторами) потребуется новое определение static
, которое, вероятно, не рассматривается как необходимое. И в любом случае программисты были бы смущены точным значением.
Из спецификации:
Внутренний класс - это вложенный класс, который явно или неявно объявленный статический.
Внутренние классы включают локальные (§14.3), анонимные (§15.9.5) и нестатические классы членов (§8.5).
Внутренние классы не могут объявлять статические инициализаторы (§8.7) или член интерфейсы или ошибка времени компиляции.
Внутренние классы не могут объявлять статические члены, если они не являются постоянными переменные (§4.12.4), или возникает ошибка времени компиляции.
Ответ 2
Согласно JLS: -
8.1.3. Внутренние классы и экземпляры Enclosing
Внутренний класс - это вложенный класс, который явно или неявно объявленный статический. Внутренние классы не могут объявлять статические инициализаторы (§8.7) или интерфейсов членов. Внутренние классы не могут объявлять статические членов, если они не являются постоянными полями времени компиляции (§15.28).
Любая локальная переменная, параметр формального метода или обработчик исключений параметр, используемый, но не объявленный во внутреннем классе, должен быть объявлен окончательный. Любая локальная переменная, используемая, но не объявленная во внутреннем классе должно быть определенно назначено (§16) перед телом внутреннего класса.
Помимо этих двух вещей, которые я нашел важными.. Есть еще много, что вы можете получить оттуда.. Существует огромное объяснение inner classes
, anonymous inner classes
и nested classes
..
ОБНОВЛЕННОЕ ПОЯСНЕНИЕ: -
Просто подумайте об этом. Статический блок выполняется во время инициализации класса, и вы не можете инициализировать нестатический внутренний класс, не имея экземпляра охватывающего класса, что причина.
Внутренние классы связаны с instance
охватывающего класса. Они похожи на другие атрибуты экземпляра окружающего класса. Теперь нет смысла встраивать поле static
в non-static
контекст.. Однако, если вы объявите их как Компиляция констант времени, они будут разрешены.
ПРИМЕЧАНИЕ: - static final Object = null
не константы времени компиляции. Итак, вы не можете иметь их внутри своего внутреннего класса
С другой стороны, если ваш внутренний класс был static
, это фактически вложенный класс, то вы можете объявить свое поле static, поскольку они все равно будут связаны с классом, поэтому вы можете получить к ним доступ даже до того, класс в экземпляре..
Надеюсь, это имеет смысл.
ОБНОВЛЕНИЕ 2: -
public class A {
class B {
static int x = 0;
}
}
В приведенном выше коде static variable x
будет распространяться для каждого экземпляра класса B..
Кроме того, каждый экземпляр class A
будет иметь свою собственную копию class B
(так как JVM будет загружать класс B каждый раз создается instance of A
),..
Таким образом, static variable x
не может быть разделен между каждым экземпляром class A
, если только он не является константой времени компиляции.. (Чтобы сделать его более прямой вперед: - Вы можете сделать - B.x
, если вы видите B как внешний класс. Но класс B сам по себе различен для каждого экземпляра класса A. Таким образом, B.x
будет отличаться для каждого экземпляра класса A. Итак, статическая переменная x
фактически не разделяется между разными экземплярами класса A. Не имеет смысла для статической переменной.)
Надеюсь, теперь это имеет смысл.
Ответ 3
Все ограничения описаны в
JLS # 8.1.3. Внутренние классы и Enclosing Instances
Поскольку статические объявления связаны с классом, если вы объявляете его внутри внутреннего класса, он будет ассоциироваться с экземпляром, а не с классом.
![innerclass]()
Нестационарные внутренние классы являются членами Object. И для членов инициализация происходит только при создании экземпляра объекта. Если статические переменные были разрешены, инициализация была бы выполнена до создания экземпляра.
Вот почему существуют отдельные внутренние классы non-static
и static
.
Вам всегда нужен экземпляр внешнего класса для доступа к внутреннему классу Outer.Inner
только исключение - это static inner class
, для которого нет ограничений, которые применимы к нестационарным внутренним классам.
static class Inner {
static final int x = 3; // OK: compile-time constant
static int y = 4;// OK
static class NestedButNotInner {// OK
}
interface NeverInner {// OK
};
}
Однако константы разрешены и документируются в JLS
Ответ 4
Поскольку внутренний класс, тесно связанный с классом верхнего уровня, должен иметь экземпляр внешнего класса для создания внутреннего через
Outer o = new Outer();
Inner i = o.new Inner();
Следовательно, это связано с экземпляром, а не с классом.
Ответ 5
Как вы знаете, внутренний класс может наследовать статический член из своего класса владельца.
class HasStatic {
static int j = 100;
}
class myInnerClassTest {
class Inner extends HasStatic {
}
public static void main(String[] args){
System.out.println(Inner.j);
}
}
И он печатает "100".