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

Sha*_*vil 2 java generics abstract-class casting

我有一个带有抽象类的Java枚举,如下所示:

public enum Strategy {
    STRING {
        @Override
        public String execute() {
            return "ABCDE";
        }
    },
    INTEGER {
        @Override
        public Integer execute() {
            return 12345;
        }
    };
    public abstract Object execute();
}
Run Code Online (Sandbox Code Playgroud)

当我使用它时,我希望能够这样做:

String text = Strategy.STRING.execute();
Integer num = Strategy.INTEGER.execute();
Run Code Online (Sandbox Code Playgroud)

但是,我的IDE警告我,这些是不兼容的类型,不会编译.要解决它,我必须改为:

String text = (String) Strategy.STRING.execute();
Integer num = (Integer) Strategy.INTEGER.execute();
Run Code Online (Sandbox Code Playgroud)

我宁愿不必投出我的execute()方法的结果.有没有办法返回具体方法签名中指定的类型,而不是返回Object

Ted*_*opp 5

覆盖方法时,可以声明子类方法以返回超类返回类型的细化.但是,调用超类方法的代码无法知道返回对象的实际类型.在你的情况下,它只知道它Object是某种形式.这就是为什么你必须在分配给一个更具体的变量之前进行转换.

枚举对象有点奇怪.编译此代码时:

Strategy.STRING.execute();
Run Code Online (Sandbox Code Playgroud)

编译器生成此字节码(输出自javap -c):

getstatic     #2 // Field Strategy.STRING:LStrategy;
invokevirtual #3 // Method Strategy.execute:()Ljava/lang/Object;
Run Code Online (Sandbox Code Playgroud)

如您所见,它将其视为Strategy.STRING类的静态字段Strategy,并且该字段属于类型Strategy.因此,尽管出现了,但调用代码并不知道它正在调用它的STRING版本execute().

不过,我想知道你为什么要这么做.设计需要强制转换的API似乎与面向对象编程的精神背道而驰.