为什么不能在方法中本地声明枚举?

时间:2009-03-31 13:02:28

标签: java enums

今天,我发现自己编写了这样的代码......

public class LocalEnums {

    public LocalEnums() {
    }

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

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

    }
}

当编译器在本地enum上报告错误时,我感到很惊讶:

  

成员枚举LocalEnum不能   本地

为什么枚举不能像那样被声明为本地?

我发现这在某些情况下非常有用。在我工作的情况下,其余代码不需要了解enum

是否有任何结构/设计冲突解释了为什么这不可能或者这可能是Java的未来功能?

6 个答案:

答案 0 :(得分:37)

枚举是静态嵌套类,因为它们定义静态成员变量(枚举值),而不允许内部类:{ {3}}

更新:我正在查看JLS java语言规范),了解有关静态嵌套类限制的更多详细信息,但未找到它(虽然可能存在,隐藏在不同的主题下)。从纯粹的实现角度来看,没有理由不这样做。所以我怀疑这是一个语言哲学问题:不应该这样做,因此不会得到支持。但我不在那里,所以这是纯粹的推测。

作为评论:如果您的方法足够大以至于需要自己的枚举,则表明您需要重构。

答案 1 :(得分:15)

我很少发现自己在方法中编写任何类型,除非它是一个匿名的内部类。但是,您可以编写嵌套枚举:

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

    public void foo()
    {
    }
}

我不认为我真的想要读取一个在其中声明了新类型的方法 - 你是否有任何具体的理由希望在方法中声明它而不仅仅是嵌套类型?我可以看到“没有其他方法需要知道”的论点,但我认为评论可以解决这个问题并且仍然会留下更易读的代码。

答案 2 :(得分:10)

  1. “嵌套枚举类型是隐式的 静态。“8.9 Enums

  2. 推断这一点是合理的     嵌套的枚举类型隐式包含     静态访问修饰符。

  3. “如果a是编译时错误     本地类声明包含任何     以下访问之一     修饰语:public,protected,     私人的,或静态的。“14.3 14.3 Local Class Declarations

答案 3 :(得分:3)

这很奇怪,因为java内部类定义说编译时常量可以声明为静态,而Enum的成员显然是编译时常量,加上枚举是一个静态类,所以... ...

Documentation

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
}

答案 4 :(得分:3)

其他答案将很快过时。

更新:Java 16中的本地枚举

Java 15中的现在预览功能是支持本地枚举的一项新功能。据推测,如果一切顺利,此功能将出现在Java 16中。

您现在可以在Java 15预览中运行以下示例代码。

private void demoLocalEnum ( )
{
    enum Color { PURPLE, SAFETY_ORANGE }
    System.out.println( Color.PURPLE );
}

在此屏幕截图中,我们可以看到局部枚举仅在其定义方法内如何存在。同级方法无法看到该枚举。尝试从另一个方法调用该枚举会产生错误。

Screenshot of an error caused by a sibling method trying to call a local enum defined in some other method.

请参见demo of such code running 2020.2 IntelliJ中的IDE

此功能是新的 Records 功能的一部分,在Java 15中也进行了预览。请参见JEP 384: Records (Second Preview)。请注意,记录,枚举和接口现在都可以是本地的。

鉴于本地记录的有用性,同样具有本地枚举和本地接口也将很有用。由于担心它们的语义,传统上在Java中不允许使用它们。具体来说,嵌套枚举和嵌套接口是隐式静态的,因此局部枚举和本地接口也应隐式静态的。但是,Java语言中的本地声明(本地变量,本地类)永远不会是静态的。但是,JEP 359中引入本地记录克服了这种语义上的担忧,允许本地声明为静态,并为本地枚举和本地接口打开了大门。

答案 5 :(得分:2)

http://mindprod.com/jgloss/enum.html给出了java枚举的良好描述 - 如前所述,枚举被定义为静态,因此它们不能被声明为本地