Differences in type inference JDK8 javac/Eclipse Luna?

后端 未结 2 487
天命终不由人
天命终不由人 2020-12-10 17:52

I\'m trying to switch a project to Java8, and encounter odd differences between Eclipse Luna and javac\'s type inference. With JDK 1.7.0_65 javac this code compiles just fin

2条回答
  •  囚心锁ツ
    2020-12-10 18:22

    Compilers can only inspect the method signatures, not the method body, so that part is irrelevant.

    This "reduces" your code to (psuedocode):

    public class TypeInferenceTest {
        public static String toString(Object obj);
    
        public static String toString(char[] ca);
    
        public static String toString(Throwable t);
    
        public static  U getKey(Object code, U defaultValue);
    
        public static void test() {
            Object code = "test";
            toString(getKey(code, null));
        }
    }
    

    Also note that the U getKey(...) really is: U getKey(...).

    All it knows that getKey(code, null) returns is: ? extends Object, so it returns a subtype of Object, or an Object itself.
    There are three signatures that match, namely Object, char[] and Throwable, where both char[] and Throwable match equally and better than Object, because you asked for an ? extends Object.

    So it cannot choose which is the correct one, because all three match the signature.

    When you change it to:

    public static Object getKey(Object code, Object defaultValue);
    

    then only public static String toString(Object obj); matches, because it matches better as any other ? extends Object that is not equal to Object.

    Edit, I looked over the original intent of the question: Why does it compile in Java 7, but not in Java 8?

    In Java 8 type inference got greatly improved.

    Whereas in Java 7 it could for example only infer that getKey returned an Object, it now in Java 8 infers that it returns an ? extends Object.

    When using Java 7 there was only one match, namely Object.

    To have the change visualized even better, consider this piece of code:

    public class TypeInferenceTest {
        public static String toString(Object obj) { return "1"; }
    
        public static String toString(Throwable t) { return "2"; }
    
        public static  U getKey(Object code, U defaultValue) { return defaultValue; }
    
        public static void test() {
            Object code = "test";
            String result = toString(getKey(code, null));
            System.out.println(result);
        }
    
        public static void main(String[] args) {
            test();
        }
    }
    

    On Java 7 it prints 1, on Java 8 it prints 2, exactly because of the reasons I have outlined above.

提交回复
热议问题