Подтвердить что ты не робот

Почему статические поля (не окончательные) ограничены во внутреннем классе в 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
}

В то время как я получил от Почему у нас есть статические конечные члены, но у меня есть статический метод во внутреннем классе?, что он может наследовать статический член из класса владельца, Но почему это не должно быть? Какой основной ООП больно?

4b9b3361

Ответ 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".