Can overridden methods differ in return type?

前端 未结 12 1715
礼貌的吻别
礼貌的吻别 2020-11-22 16:11

Can overridden methods have different return types?

12条回答
  •  鱼传尺愫
    2020-11-22 16:47

    well, the answer is yes... AND NO.

    depends on the question. everybody here answered regarding Java >= 5, and some mentioned that Java < 5 does not feature covariant return types.

    actually, the Java language spec >= 5 supports it, but the Java runtime does not. in particular, the JVM was not updated to support covariant return types.

    in what was seen then as a "clever" move but ended up being one of the worst design decisions in Java's history, Java 5 implemented a bunch of new language features without modifying the JVM or the classfile spec at all. instead all features were implemented with trickery in javac: the compiler generates/uses plain classes for nested/inner classes, type erasure and casts for generics, synthetic accessors for nested/inner class private "friendship", synthetic instance fields for outer 'this' pointers, synthetic static fields for '.class' literals, etc, etc.

    and covariant return types is yet more syntactic sugar added by javac.

    for example, when compiling this:

    class Base {
      Object get() { return null; }
    }
    
    class Derived extends Base {
      @Override
      @SomeAnnotation
      Integer get() { return null; }
    }
    

    javac will output two get methods in the Derived class:

    Integer Integer:Derived:get() { return null; }
    synthetic bridge Object Object:Derived:get() { return Integer:Derived:get(); }
    
    

    the generated bridge method (marked synthetic and bridge in bytecode) is what actually overrides Object:Base:get() because, to the JVM, methods with different return types are completely independent and cannot override each other. to provide the expected behavior, the bridge simply calls your "real" method. in the example above, javac will annotate both bridge and real methods in Derived with @SomeAnnotation.

    note that you cannot hand-code this solution in Java < 5, because bridge and real methods only differ in return type and thus they cannot coexist in a Java program. but in the JVM world, method return types are part of the method signature (just like their arguments) and so the two methods named the same and taking the same arguments are nonetheless seen as completely independent by the JVM due to their differing return types, and can coexist.

    (BTW, the types of fields are similarly part of the field signature in bytecode, so it is legal to have several fields of different types but named the same within a single bytecode class.)

    so to answer your question fully: the JVM does not support covariant return types, but javac >= 5 fakes it at compile time with a coating of sweet syntactic sugar.

提交回复
热议问题