Java 为什么可以';是否在方法中本地声明枚举?

Java 为什么可以';是否在方法中本地声明枚举?,java,enums,Java,Enums,今天,我发现自己正在编写这样的代码 public class LocalEnums { public LocalEnums() { } public void foo() { enum LocalEnum { A,B,C }; // .... // class LocalClass { } } } 当编译器在本地enum上报告错误时,我有点惊讶: 成员enum Loc

今天,我发现自己正在编写这样的代码

public class LocalEnums {

    public LocalEnums() {
    }

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

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

    }
}
当编译器在本地
enum
上报告错误时,我有点惊讶:

成员enum LocalEnum不能为空 本地的

为什么不能将枚举声明为与类类似的本地类

我发现这在某些情况下非常有用。在我正在工作的情况下,其余的代码不需要知道有关
enum
的任何信息


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

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

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


作为注释:如果您的方法足够大,它们需要自己的枚举,那么这就是您需要重构的强烈信号。

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

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

    public void foo()
    {
    }
}

我不认为我真的想读一个在方法中声明了新类型的方法——你有什么具体的理由想在方法中声明它而不是仅仅作为嵌套类型?我可以看到“没有其他方法需要知道”的论点,但我认为一条注释可以解决这个问题,并且仍然可以留下更可读的代码。

很好地描述了java枚举-如前所述,枚举被定义为静态的,所以不能声明为局部变量。这很奇怪,因为java内部类定义说编译时常量可以声明为静态的,枚举的一个成员显然是编译时常量,加上枚举是静态类,所以

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
}
  • “嵌套的枚举类型是隐式的 静态。”

  • 可以合理地推断 嵌套枚举类型隐式包含 静态访问修饰符

  • “如果 本地类声明包含任何 以下访问权限之一 修改器:公共、受保护、, 私人的,或静态的。”

  • 其他答案在2021-03-16发布的Java16中已经过时

    更新:Java16中的本地枚举 作为中新功能的一部分,现在可以在本地定义枚举。实际上,记录、枚举和接口现在都可以是本地的

    引用JEP 395:

    引入了声明本地记录类、本地枚举类和本地接口的功能

    添加本地记录类是添加其他类型的隐式静态本地声明的一个机会

    嵌套的枚举类和嵌套接口已经是隐式静态的,因此为了一致性,我们定义了本地枚举类和本地接口,它们也是隐式静态的

    现在可以运行以下示例代码来使用在方法中定义的枚举

    private void demoLocalEnum ( )
    {
        enum Color { PURPLE, SAFETY_ORANGE }
        System.out.println( Color.PURPLE );
    }
    
    在这个屏幕截图中,我们可以看到本地枚举如何仅存在于其定义方法中。同级方法无法看到该枚举。尝试从另一个方法调用该枚举会生成错误

    见2020.2中的a

    隐式
    static
    本地定义的枚举有一个限制:无法访问周围类中的状态

    正如上面的JEP 395引用中所提到的,本地枚举隐式地
    静态
    。因此,在本地枚举上定义的任何方法都无法访问周围外部类的状态

    引用JEP 395,关于本地记录,但也适用于本地枚举:

    本地记录类是嵌套记录类的一种特殊情况。与嵌套记录类一样,本地记录类也是隐式静态的。这意味着他们自己的方法不能访问封闭方法的任何变量;反过来,这又避免了捕获一个立即封闭的实例,该实例将默默地向记录类添加状态。本地记录类是隐式静态的这一事实与不是隐式静态的本地类相反。事实上,局部类从来都不是静态的——隐式或显式的——并且总是可以访问封闭方法中的变量


    kdgregory,我的方法不必太大就可以使用枚举的功能。。。枚举可以简化/澄清代码。所以重构在这里可能不是问题,哲学并不是排除某个特性的理由。缺乏实用性、导致危险代码的可能性(意外或未定义的行为)以及包含的技术困难是有效的原因。但是我不明白为什么这些都适用于这里。@dhardy-语言哲学就是一切:包括什么,排除什么,以及语言的外观。如果你没有哲学,你就会得到PHP。@达迪哲学让我们相信某个功能是无用的,它可能会导致危险的代码,等等。这不能客观地评估,Java有时也有一点不对劲+Jon,我也不经常编写本地类。但是,在C#中,您可以使用类似var v=new{Prop=“Hello!!!”};这在某些情况下是有用的。您可以使用Java中的本地类来近似这种行为。所以,如果是类,为什么不使用枚举呢?私有嵌套枚举(作为方法中的枚举声明可能应该是)可以被内联