我有一个带有抽象类的Java枚举,如下所示:
public enum Strategy {
STRING {
@Override
public String execute() {
return "ABCDE";
}
},
INTEGER {
@Override
public Integer execute() {
return 12345;
}
};
public abstract Object execute();
}
当我使用它时,我希望能够这样做:
String text = Strategy.STRING.execute();
Integer num = Strategy.INTEGER.execute();
但是,我的IDE警告我,这些是不兼容的类型,不会编译。要解决它,我必须改为:
String text = (String) Strategy.STRING.execute();
Integer num = (Integer) Strategy.INTEGER.execute();
我宁愿不必投出execute()
方法的结果。有没有办法返回具体方法签名中指定的类型,而不是返回Object
?
答案 0 :(得分:5)
当重写方法时,可以声明子类方法以返回超类返回类型的细化。但是,调用超类方法的代码无法知道返回对象的实际类型。在你的情况下,它只知道它是某种Object
。这就是为什么你必须在分配一个更具体的变量之前进行转换。
枚举对象有点奇怪。编译此代码时:
Strategy.STRING.execute();
编译器生成此字节码(从javap -c
输出):
getstatic #2 // Field Strategy.STRING:LStrategy;
invokevirtual #3 // Method Strategy.execute:()Ljava/lang/Object;
如您所见,它将Strategy.STRING
视为类Strategy
的静态字段,该字段的类型为Strategy
。因此,尽管有外观,但调用代码并不知道它正在调用STRING
的{{1}}版本。
我想知道你为什么要这么做。设计需要强制转换的API似乎与面向对象编程的精神背道而驰。
答案 1 :(得分:1)
您的枚举常量被编译为static
个字段。像
public static final Strategy INTEGER = new Strategy() {
@Override
public Integer execute() {
return 12345;
}
};
因为它们只是Strategy
引用,您只能访问Strategy
'界面'它将execute()
方法声明为返回Object
。
所以,不,你不能做到这一点
Integer num = Strategy.INTEGER.execute();
以这种方式。