今天,我发现自己编写了这样的代码......
public class LocalEnums {
public LocalEnums() {
}
public void foo() {
enum LocalEnum {
A,B,C
};
// ....
// class LocalClass { }
}
}
当编译器在本地enum
上报告错误时,我感到很惊讶:
成员枚举LocalEnum不能 本地
为什么枚举不能像类那样被声明为本地?
我发现这在某些情况下非常有用。在我工作的情况下,其余代码不需要了解enum
。
是否有任何结构/设计冲突解释了为什么这不可能或者这可能是Java的未来功能?
答案 0 :(得分:37)
枚举是静态嵌套类,因为它们定义静态成员变量(枚举值),而不允许内部类:{ {3}}
更新:我正在查看JLS
( java语言规范),了解有关静态嵌套类限制的更多详细信息,但未找到它(虽然可能存在,隐藏在不同的主题下)。从纯粹的实现角度来看,没有理由不这样做。所以我怀疑这是一个语言哲学问题:不应该这样做,因此不会得到支持。但我不在那里,所以这是纯粹的推测。
作为评论:如果您的方法足够大以至于需要自己的枚举,则表明您需要重构。
答案 1 :(得分:15)
我很少发现自己在方法中编写任何类型,除非它是一个匿名的内部类。但是,您可以编写嵌套枚举:
public class NestedEnum
{
private enum MyEnum
{
X, Y, Z
}
public void foo()
{
}
}
我不认为我真的想要读取一个在其中声明了新类型的方法 - 你是否有任何具体的理由希望在方法中声明它而不仅仅是嵌套类型?我可以看到“没有其他方法需要知道”的论点,但我认为评论可以解决这个问题并且仍然会留下更易读的代码。
答案 2 :(得分:10)
“嵌套枚举类型是隐式的 静态。“8.9 Enums
推断这一点是合理的 嵌套的枚举类型隐式包含 静态访问修饰符。
答案 3 :(得分:3)
这很奇怪,因为java内部类定义说编译时常量可以声明为静态,而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
}
答案 4 :(得分:3)
其他答案将很快过时。
Java 15中的现在预览功能是支持本地枚举的一项新功能。据推测,如果一切顺利,此功能将出现在Java 16中。
您现在可以在Java 15预览中运行以下示例代码。
private void demoLocalEnum ( )
{
enum Color { PURPLE, SAFETY_ORANGE }
System.out.println( Color.PURPLE );
}
在此屏幕截图中,我们可以看到局部枚举仅在其定义方法内如何存在。同级方法无法看到该枚举。尝试从另一个方法调用该枚举会产生错误。
请参见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枚举的良好描述 - 如前所述,枚举被定义为静态,因此它们不能被声明为本地