Почему нельзя объявлять перечисления локально в методе?
Сегодня я обнаружил, что кодирую что-то вроде этого...
public class LocalEnums {
public LocalEnums() {
}
public void foo() {
enum LocalEnum {
A,B,C
};
// ....
// class LocalClass { }
}
}
и я был удивлен, когда компилятор сообщил об ошибке на локальном enum
:
Член enum LocalEnum не может быть локальный
Почему не может быть объявлено enums локально, например classes?
Я нашел это очень полезным в определенных ситуациях. В том случае, когда я работал, остальная часть кода не нуждалась в значении enum
.
Есть ли какой-либо конфликт конструкций/конструкций, который объясняет, почему это невозможно, или это может быть будущей особенностью Java?
Ответы
Ответ 1
Перечисления представляют собой статические вложенные классы, потому что они определяют статические переменные-члены (значения перечисления), и это запрещено для внутренних классов: http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.1.3
Обновление: Я просмотрел JLS
(спецификацию языка Java) для более подробной информации об ограничениях статических вложенных классов и не нашел (хотя, вероятно, там, другая тема). С чистой точки зрения, нет причин, по которым это невозможно сделать. Поэтому я подозреваю, что это проблема языковой философии: ее не следует делать, поэтому она не будет поддерживаться. Но меня там не было, так что чистая спекуляция.
В качестве комментария:, если ваши методы достаточно велики, чтобы требовать их собственных перечислений, то это сильный признак того, что вам нужно рефакторинг.
Ответ 2
Я редко нахожу, что пишу какие-либо типы внутри метода, если это не анонимный внутренний класс. Однако вы можете писать вложенные перечисления:
public class NestedEnum
{
private enum MyEnum
{
X, Y, Z
}
public void foo()
{
}
}
Я не думаю, что мне действительно хотелось бы прочитать метод, объявляющий новый тип внутри него - есть ли у вас какая-либо конкретная причина для желания объявить его внутри метода, а не как вложенный тип? Я могу видеть аргумент "нет других методов, которые нужно знать", но я думаю, что комментарий может сортировать и оставлять более читаемый код.
Ответ 3
-
"Вложенные типы перечислений неявно
static. " 8.9 Enums
-
Разумно заключить, что вложенные типы перечислений неявно содержат модификатор статического доступа.
- "Это ошибка времени компиляции, если объявление локального класса содержит любые один из следующих способов доступа модификаторы: общедоступные, защищенные, частный или статический. " 14.3 14.3 Local Объявления класса
Ответ 4
Это странно, потому что определение внутреннего класса Java говорит, что константы времени компиляции могут быть объявлены статическими, а член Enum явно является константой времени компиляции, плюс enum является статическим классом, предположительно...
Документация:
8.1.3 Внутренние классы и экземпляры Enclosing
(...) Внутренние классы не могут объявлять статические члены, если они не являются постоянными полями времени компиляции.
class Outer{
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
}
Ответ 5
http://mindprod.com/jgloss/enum.html дает хорошее описание java-перечислений - как упоминалось ранее, перечисления определены как статические, поэтому они не могут быть объявлены как локальные жители