class OuterClass {
class InnerClass {
static int i = 100; // compile error
static void f() { } // compile error
}
}
Хотя невозможно получить доступ к статическому полю с помощью OuterClass.InnerClass.i
, если я хочу записать что-то, что должно быть статическим, например, количество созданных объектов InnerClass, было бы полезно сделать это поле статическим. Так почему же Java запрещает статические поля / методы во внутренних классах?
РЕДАКТИРОВАТЬ: Я знаю, как сделать компилятор довольным статическим вложенным классом (или статическим внутренним классом), но я хочу знать, почему Java запрещает статические поля / методы внутри внутренних классов (или обычного внутреннего класса) как из языковой конструкции, так и из аспекты реализации, если кто-то знает об этом больше.
java
inner-classes
static-members
Jichao
источник
источник
Ответы:
Идея внутренних классов заключается в том, чтобы работать в контексте включающего экземпляра. Почему-то разрешение статических переменных и методов противоречит этой мотивации?
источник
Потому что эти внутренние классы являются внутренними классами "экземпляра". То есть они похожи на атрибут экземпляра включающего объекта.
Поскольку они являются «экземпляровыми» классами, нет никакого смысла разрешать
static
функции, поскольку ониstatic
изначально предназначены для работы без экземпляра.Это как если бы вы одновременно пытались создать статический / экземплярный атрибут.
Возьмем следующий пример:
class Employee { public String name; }
Если вы создаете два экземпляра сотрудника:
Employee a = new Employee(); a.name = "Oscar"; Employee b = new Employee(); b.name = "jcyang";
Понятно, почему у каждого своя стоимость собственности
name
?То же самое происходит с внутренним классом; каждый экземпляр внутреннего класса не зависит от другого экземпляра внутреннего класса.
Поэтому, если вы попытаетесь создать
counter
атрибут класса, нет возможности разделить это значение между двумя разными экземплярами.class Employee { public String name; class InnerData { static count; // ??? count of which ? a or b? } }
Когда вы создаете экземпляр
a
иb
в приведенном выше примере, какое значение будет правильным для статической переменнойcount
? Определить его невозможно, поскольку существованиеInnerData
класса полностью зависит от каждого из окружающих объектов.Вот почему, когда класс объявлен как
static
, ему больше не нужен живой экземпляр, чтобы жить самим собой. Теперь, когда нет зависимости, вы можете свободно объявлять статический атрибут.Я думаю, это звучит повторяюще, но если вы подумаете о различиях между атрибутами экземпляра и класса, это будет иметь смысл.
источник
final
статических полей разрешено во внутреннем классе в java. Как вы объясните этот сценарий?InnerClass
не может иметьstatic
членов, потому что принадлежит экземпляру (изOuterClass
). Если вы объявитеInnerClass
какstatic
отсоединить его от экземпляра, ваш код будет скомпилирован.class OuterClass { static class InnerClass { static int i = 100; // no compile error static void f() { } // no compile error } }
Кстати: вы по-прежнему сможете создавать экземпляры
InnerClass
.static
в этом контексте позволяет этому произойти без включающего экземпляраOuterClass
.источник
InnerClass
вовсе не принадлежитOuterClass
, экземпляры из него сделать. Сами по себе два класса не имеют такой связи. Вопрос, почему у вас не может быть статических методов вInnerClass
неподвижном состоянии, остается.Фактически, вы можете объявить статические поля, если они являются константами и написаны во время компиляции.
class OuterClass { void foo() { class Inner{ static final int a = 5; // fine static final String s = "hello"; // fine static final Object o = new Object(); // compile error, because cannot be written during compilation } } }
источник
Поскольку внутренние классы зависят от экземпляра включающего класса / Outer, поэтому внешний класс необходимо инициализировать перед инициализацией внутреннего класса.
Это JLS говорит об инициализации класса. Нам нужно, чтобы класс T был инициализирован, если
Поэтому, если внутренний класс имеет доступ к статическому полю, это вызовет инициализацию внутреннего класса, но это не гарантирует, что включающий класс инициализирован.
Это нарушило бы некоторые основные правила . вы можете перейти к последнему разделу (чтобы
two cases
), чтобы избежать нубовОдна вещь , когда некоторые это он будет вести себя так же , как обычный класс во всех отношениях , и это связано с внешним классом.
static nested
class
nested class
static
Но концепция
Inner class
/ будет связана с классом внешнего / включающего. Обратите внимание, что связано с экземпляром, а не с классом. Теперь связь с экземпляром явно означает, что ( из концепции переменной экземпляра ) она будет существовать внутри экземпляра и будет отличаться от экземпляра.non-static
nested class
instance
Теперь, когда мы делаем что-то статическое, мы ожидаем, что оно будет инициализировано при загрузке класса и должно быть разделено между всеми экземплярами. Но из-за нестатичности даже сами внутренние классы ( вы можете определенно забыть об экземпляре внутреннего класса на данный момент ) не используются совместно со всеми экземплярами внешнего / включающего класса ( по крайней мере, концептуально ), тогда как мы можем ожидать, что некоторая переменная внутреннего класса будет совместно использоваться всеми экземплярами внутреннего класса.
Итак, если Java позволяет нам использовать статическую переменную внутри не статического вложенного класса. будет два случая .
context of instance
(переменной экземпляра). Тогда это НЕТ.источник
Вот мотивация, которую я считаю наиболее подходящей для этого "ограничения": вы можете реализовать поведение статического поля внутреннего класса как поле экземпляра внешнего объекта; Так что вам не нужны статические поля / методы . Я имею в виду, что все экземпляры внутреннего класса некоторого объекта совместно используют поле (или метод).
Итак, предположим, вы хотите подсчитать все экземпляры внутреннего класса, вы бы сделали:
public class Outer{ int nofInner; //this will count the inner class //instances of this (Outer)object //(you know, they "belong" to an object) static int totalNofInner; //this will count all //inner class instances of all Outer objects class Inner { public Inner(){ nofInner++; totalNofInner++; } } }
источник
final
тогда?Проще говоря, нестатические внутренние классы представляют собой переменные экземпляра для внешнего класса, и они создаются только тогда, когда создается внешний класс и объект внешнего класса создается во время выполнения, а статические переменные создаются во время загрузки класса. Итак, нестатический внутренний класс - это вещь времени выполнения, поэтому static не является частью нестатического внутреннего класса.
ПРИМЕЧАНИЕ: всегда относитесь к внутренним классам как к переменной для внешнего класса, они могут быть статическими или нестатическими, как и любые другие переменные.
источник
static final
константы.Потому что это вызвало бы двусмысленность в значении слова «статика».
Взято из "Core Java SE 9 для нетерпеливых" Кей С. Хорстманн. Стр. 90 Глава 2.6.3
источник
Думаю, это для последовательности. Хотя, похоже, для этого нет никаких технических ограничений, вы не сможете получить доступ к статическим членам внутреннего класса извне, т. Е.
OuterClass.InnerClass.i
Потому, что средний шаг не статичен.источник
static final
константы.