Java 如何调用枚举单个方法?
我有一个枚举,可能看起来像下面的枚举。我的目标是拥有一个Java 如何调用枚举单个方法?,java,enums,Java,Enums,我有一个枚举,可能看起来像下面的枚举。我的目标是拥有一个enum,其中包含一些常用方法(我通过添加一个抽象方法实现了这一点)和一些“enum-value-individual”方法 编译以下代码: public enum MyEnum { VALUE { @Override public void syso() { System.out.println("VALUE syso"); } }, SP
enum
,其中包含一些常用方法(我通过添加一个抽象方法实现了这一点)和一些“enum-value-individual”方法
编译以下代码:
public enum MyEnum {
VALUE {
@Override
public void syso() {
System.out.println("VALUE syso");
}
},
SPECIAL_VALUE {
@Override
public void syso() {
System.out.println("SPECIAL_VALUE syso");
}
public void sayHello() {
System.out.println("Hello");
}
};
public abstract void syso();
public static void main(String... args) {
MyEnum.VALUE.syso();
MyEnum.SPECIAL_VALUE.syso();
}
}
运行此操作将打印以下内容:
VALUE syso
SPECIAL_VALUE syso
但是,尝试调用我在特殊值
中定义的sayHello()
,是行不通的
将以下内容添加到main方法后,将不再编译:
public static void main(String... args) {
MyEnum.SPECIAL_VALUE.sayHello(); // does not work
}
为什么呢?这对我来说似乎很好,但找不到方法。有没有办法调用这个方法?也许是通过思考
我希望避免将此方法抽象化,因为它对任何其他枚举值都没有意义。在继承常用方法的同时,我也无法扩展此枚举并添加此特殊方法。我还希望避免添加某种类型的单例类来“模拟”这一点
运行这个有可能吗?如果不是,我的最佳选择是什么
为什么呢
原因如下:
8.9.1。枚举常量
仅当枚举类主体中声明的实例方法重写封闭枚举类型(§8.4.8)中的可访问方法时,才可以在封闭枚举类型的外部调用它们
有没有办法调用这个方法?也许是通过思考
鉴于上述约束,如果不想在封闭的枚举类中公开方法,反射是唯一的选择。每个枚举常量都创建为一个内部类,如示例中的MyEnum$1
和MyEnum$2
。因此,您可以通过常量的getClass()
方法检索Class
,然后通过反射调用您的方法(省略异常处理):
我很可能会尝试避免反射并在enum类中公开该方法,并让它抛出一个UnsupportedOperationException
:
...
public void sayHello() {
throw new UnsupportedOperationException();
}
...
这至少可以在运行时捕获意外调用-它仍然不允许编译器在编译时捕获它们,但反射方法也不允许。因为
特殊值
是枚举的一个实例,并且枚举
只有方法syso()
。您正在调用
以下是与类相同的内容:
interface Foo {
Foo inst1 = new Foo() {
@Override
public void doFoo() {
}
public void doAnonymous() {
}
};
void doFoo();
}
您不能像Foo.inst1.doAnonymous()那样调用方法doAnonymous(),您只能通过反射来访问doAnonymous您将最终能够通过反射来调用它。不要声明方法抽象,只需将其设为空即可。并在特殊_值中
覆盖它。我认为可以使用反射,但为什么?@AndrewLogvinov以一种空的方式实现它也会导致我能够调用MyEnum.VALUE.sayHello()
,这不会做任何事情。这似乎不是一个好主意。原因如下:枚举类主体中声明的实例方法只有在覆盖封闭枚举类型中的可访问方法时才能在封闭枚举类型外部调用(§8.4.8).
@没有人可以抛出一个不支持的操作异常
-这是一个比使用ReflectionTanks更干净的设计,我认为这足以解释它。我想我会使用您的解决方案,通过抛出一个不支持操作异常
并在特殊值
中重写它来实现它。但我仍然不理解JLS中这条语句背后的原因。@如果您考虑到以下事实,JLS所说的没有一条是有意义的:枚举的唯一公共接口是由枚举类本身声明的,这意味着编译器无法知道“特殊”的含义方法只在客户端代码中的一个/部分常量中声明。在使用“普通”类的其他情况下,您可以通过向下转换来解决这个问题,但是由于以这种特定样式实现的枚举是匿名类,因此您不能执行这样的转换(没有反射(我甚至不确定这是否可行))。好吧,我不是说MyEnum.sayHello()
,我的意思是MyEnum.SPECIAL\u VALUE.sayHello()
。因此,与您的代码相比,我仍然至少给编译器一个关于“子类型”的提示。MyEnum.SPECIAL_值感觉不像是一个“匿名”子类型,因为我显式地给它起了一个名字。是的,但编译器将它视为MyEnum的一个实例。MyEnum没有一个方法sayHello()。是的,它看起来确实是这样。Java编译器开发人员可能太懒了,无法完成这项工作
interface Foo {
Foo inst1 = new Foo() {
@Override
public void doFoo() {
}
public void doAnonymous() {
}
};
void doFoo();
}