Java:枚举'内方法和变量的定义;s常数
我在做一些实验,不小心写了一个代码,这很奇怪,我不完全明白。我甚至惊讶于我能编译它。看起来是这样的:Java:枚举'内方法和变量的定义;s常数,java,oop,inheritance,enums,language-design,Java,Oop,Inheritance,Enums,Language Design,我在做一些实验,不小心写了一个代码,这很奇怪,我不完全明白。我甚至惊讶于我能编译它。看起来是这样的: enum Foo { VALUE_1 { public int myVariable = 1; }, VALUE_2 { public void myMethod() { // } }, VALUE_3; } interface Bar { void myMethod();
enum Foo {
VALUE_1 {
public int myVariable = 1;
},
VALUE_2 {
public void myMethod() {
//
}
},
VALUE_3;
}
interface Bar {
void myMethod();
}
enum Foo implements Bar {
VALUE_1 {
public void myMethod() {
System.err.println("val1");
}
};
}
private SoundPack soundPack = SoundPack.CLASSICAL;
正如预期的那样,无法通过以下方式访问此类元素:
Foo.VALUE_2.myMethod();
原因是,编译器将在枚举本身中查找该方法
我假设不可能从枚举之外访问这些方法和变量。因此,我尝试创建一个参数化构造函数,并使用一些内部变量调用它:
enum Foo {
VALUE(internalVariable) {
int internalVariable = 1;
};
private Foo(int param) {
//
}
}
编写这样的结构是不可能的。现在我在想,如果无法访问常数,那么在常数中定义一些东西有什么意义呢
我试图在常量中以及枚举本身中创建相同的命名方法,以检查它是否以某种方式发生冲突。没有
enum Foo {
VALUE_1 {
int myVariable = 1;
public int myMethod() {
return myVariable;
}
},
VALUE_2 {
//
};
public int myMethod() {
return 0;
}
}
有趣的时刻来了!我尝试在枚举中继续调用myMethod(),并实际了解了Java魔术的工作原理。在常量中定义的方法重写在枚举中定义的方法
Foo.VALUE_1.myMethod(); // Returns 1
Foo.VALUE_2.myMethod(); // Returns 0
然而,我们不能重写变量,对吗?所以我很好奇,它是如何只处理变量的
enum Foo {
VALUE_1 {
public int myVariable = 1;
},
VALUE_2 {
//
};
public int myVariable = 0;
}
....
System.out.println(Foo.VALUE_1.myVariable); // Returns 0
System.out.println(Foo.VALUE_2.myVariable); // Returns 0
现在我终于开始回答我的问题了:
enum Foo {
VALUE {
class MyClass {
// OK
}
abstract class MyAbstractClass {
// OK
}
interface MyInterface {
// FAIL. It won't compile.
}
}
}
$ java -version
java version "1.7.0_21"
OpenJDK Runtime Environment (IcedTea 2.3.9) (7u21-2.3.9-0ubuntu0.12.10.1)
OpenJDK 64-Bit Server VM (build 23.7-b01, mixed mode)
谢谢你的时间和回答 从
枚举常量的可选类主体隐式定义
匿名类声明(§15.9.5),立即扩展
封闭枚举类型
创造这样的东西
VALUE_2 {
public void myMethod() {
//
}
},
当枚举本身(或其超类型)中没有声明myMethod()
时,只会将方法的作用域设置为抽象类,即不能在该主体之外调用。类似的行为也适用于此主体内声明的字段。public
标识符不会改变任何内容
编辑
对于第三个问题,因为您正在声明一个匿名类,所以没有其他组件可以访问(实现)接口。另一方面,类提供行为,因此可以在匿名类中使用
查看一些匿名类
结束编辑
至于4。我在实践中从未见过这样的代码。如果希望某个助手方法执行仅与该特定枚举相关的特定行为,则该方法非常有用。这将是非常奇怪的,可能更适合一个真正的类
请看下面的图片。您可能希望有许多单例,每个单例都有自己的实现。使用重写方法的匿名枚举类声明可以实现这一点
[…]我刚才定义的方法根本无法调用。还是我错了
正确,您错了:Javaenum
s可以实现接口,如下所示:
enum Foo {
VALUE_1 {
public int myVariable = 1;
},
VALUE_2 {
public void myMethod() {
//
}
},
VALUE_3;
}
interface Bar {
void myMethod();
}
enum Foo implements Bar {
VALUE_1 {
public void myMethod() {
System.err.println("val1");
}
};
}
private SoundPack soundPack = SoundPack.CLASSICAL;
现在您可以访问myMethod
内部的VALUE\u 1
。当然,您将被迫实施
public enum SoundPack {
CLASSICAL {
@Override
public String getSoundPickUp() {
return "res/sounds/classical/pick.wav";
}
@Override
public String getSoundNewLevel() {
return "res/sounds/classical/success.wav";
}
@Override
public String getSoundFail() {
return "res/sounds/fail.wav";
}
},
UNHEALTHY {
@Override
public String getSoundPickUp() {
return "res/sounds/unhealthy/quick_fart.wav";
}
@Override
public String getSoundNewLevel() {
return "res/sounds/unhealthy/toilet_flush.wav";
}
@Override
public String getSoundFail() {
return "res/sounds/unhealthy/vomiting.wav";
}
};
public abstract String getSoundPickUp();
public abstract String getSoundNewLevel();
public abstract String getSoundFail();
}
private SoundPack soundPack = SoundPack.CLASSICAL;
configuration.getSoundPack().getSoundNewLevel();