Почему перечисления не могут быть объявлены локально в методе? - PullRequest
53 голосов
/ 31 марта 2009

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

public class LocalEnums {

    public LocalEnums() {
    }

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

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

    }
}

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

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

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

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

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

Ответы [ 5 ]

37 голосов
/ 31 марта 2009

Перечисления являются статическими вложенными классами , поскольку они определяют статические переменные-члены (значения перечисления) , и это запрещено для внутренних классов : http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.1.3

Обновление: Я просматривал JLS ( спецификацию языка Java ) для получения более подробной информации об ограничениях статических вложенных классов и не нашел его (хотя это наверное там, спрятано под другой темой). С точки зрения чистой реализации, нет никаких причин, по которым это невозможно сделать. Поэтому я подозреваю, что это был вопрос философии языка: это не должно быть сделано, поэтому не будет поддерживаться. Но меня там не было, так что это чистое предположение.

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

15 голосов
/ 31 марта 2009

Я редко нахожу себя пишущим какие-либо типы внутри метода, если это не анонимный внутренний класс. Однако вы можете написать вложенные перечисления:

public class NestedEnum
{
    private enum MyEnum
    {
        X, Y, Z
    }

    public void foo()
    {
    }
}

Не думаю, что я действительно хочу прочитать метод, который объявил новый тип внутри него - есть ли у вас какая-либо конкретная причина для того, чтобы объявить его внутри метода, а не просто как вложенный тип? Я вижу аргумент «никакие другие методы не должны знать», но я думаю, что комментарий может разобраться с этим и все же оставить более читаемый код.

10 голосов
/ 26 мая 2010
  1. "Вложенные типы перечислений неявно static. " 8,9 Enums

  2. Разумно сделать вывод, что вложенные типы перечислений неявно содержат модификатор статического доступа.

  3. "Это ошибка времени компиляции, если Объявление локального класса содержит любой один из следующих доступа модификаторы: общедоступные, защищенные, частный или статический. " 14.3 14.3 Локальный Объявления класса
3 голосов
/ 01 апреля 2009

Это странно, потому что определение внутреннего класса java говорит, что константы времени компиляции могут быть объявлены как статические, а член Enum явно является константой времени компиляции, плюс enum - статический класс, предположительно ...

Документация :

8.1.3. Внутренние классы и вложенные экземпляры

(...) Внутренние классы не могут объявлять статические члены, если они не являются полями констант во время компиляции.

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
}
2 голосов
/ 31 марта 2009

http://mindprod.com/jgloss/enum.html дает хорошее описание java-перечислений - как упоминалось ранее, перечисления определены как статические, поэтому они не могут быть объявлены как локальные

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...