When you override a method, the subclass method can be declared to return a refinement of the superclass return type. However, code that calls the superclass method has no way of knowing what the actual type is of the returned object. In your case, all it knows is that it's an Object
of some sort. That's why you have to cast it before assigning to a more specific variable.
Enum objects are a little weird. When you compile this code:
Strategy.STRING.execute();
the compiler generates this bytecode (output from javap -c
):
getstatic #2 // Field Strategy.STRING:LStrategy;
invokevirtual #3 // Method Strategy.execute:()Ljava/lang/Object;
As you can see, it treats Strategy.STRING
as a static field of class Strategy
, and that field is of type Strategy
. Thus, despite appearances, the calling code doesn't know that it's calling the STRING
version of execute()
.
I wonder, though, why you would want to do all this. Designing an API that requires a cast seems contrary to the spirit of object-oriented programming.