Java:如果抽象类Foo返回Object,具体类Bar可以返回String还是Integer?

时间:2014-03-20 21:52:52

标签: java generics casting abstract-class

我有一个带有抽象类的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

2 个答案:

答案 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();

以这种方式。