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中的本地类来近似这种行为。所以,如果是类,为什么不使用枚举呢?私有嵌套枚举(作为方法中的枚举声明可能应该是)可以被内联