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

Почему нельзя объявлять перечисления локально в методе?

Сегодня я обнаружил, что кодирую что-то вроде этого...

public class LocalEnums {

    public LocalEnums() {
    }

    public void foo() {
        enum LocalEnum {
            A,B,C
        };

        // ....
        // class LocalClass { }

    }
}

и я был удивлен, когда компилятор сообщил об ошибке на локальном enum:

Член enum LocalEnum не может быть локальный

Почему не может быть объявлено enums локально, например classes?

Я нашел это очень полезным в определенных ситуациях. В том случае, когда я работал, остальная часть кода не нуждалась в значении enum.

Есть ли какой-либо конфликт конструкций/конструкций, который объясняет, почему это невозможно, или это может быть будущей особенностью Java?

4b9b3361

Ответ 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-перечислений - как упоминалось ранее, перечисления определены как статические, поэтому они не могут быть объявлены как локальные жители