有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java在类型推断上的差异JDK8 javac/Eclipse Luna?

我试图将一个项目切换到Java8,但在EclipseLuna和javac的类型推断之间遇到了奇怪的差异。使用JDK 1.7.0_65 javac,这段代码可以很好地编译。JDK 1.8.0_11抱怨toString(char[])和toString(Throwable)都与“toString(getKey(code,null));”匹配线EclipseLuna 4.4(I20140606-1215)使用以下任一JDK轻松编译:

public class TypeInferenceTest {
    public static String toString(Object obj) {
        return "";
    }

    public static String toString(char[] ca) {
        return "";
    }

    public static String toString(Throwable t) {
        return "";
    }

    public static <U> U getKey(Object code, U defaultValue) {
        return defaultValue;
    }

    public static void test() {
        Object code = "test";
        toString(getKey(code, null));
    }
}

我认为唯一可能匹配的签名是toString(对象)

当然,我可以简单地向对象添加一个cast,但我想知道为什么javac不能自己推断类型(而eclipse可以),为什么heck javac认为Throwable和char[]匹配,而不是Object

这是Eclipse还是javac中的错误?(我的意思是这里只能有一个编译器,要么编译,要么不编译)

编辑:来自javac(JDK8)的错误消息:

C:\XXXX\Workspace\XXXX\src>javac -cp . TypeInferenceTest.java
TypeInferenceTest.java:22: error: reference to toString is ambiguous
                toString(getKey(code, null));
                ^
  both method toString(char[]) in TypeInferenceTest and method toString(Throwable) in TypeInferenceTest match
1 error

共 (1) 个答案

  1. # 1 楼答案

    编译器只能检查方法签名,而不能检查方法体,因此部分是无关的

    这将“减少”您的代码为(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> U getKey(Object code, U defaultValue);
    
        public static void test() {
            Object code = "test";
            toString(getKey(code, null));
        }
    }
    

    还要注意<U> U getKey(...)实际上是:<U extends Object> U getKey(...)

    它只知道getKey(code, null)返回的是:? extends Object,所以它返回Object的一个子类型,或者Object本身
    有三个匹配的签名,即Objectchar[]Throwable,其中char[]Throwable匹配相同,并且比Object更好,因为您要求的是? extends Object

    因此,它无法选择哪个是正确的,因为这三个都与签名匹配

    当您将其更改为:

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

    然后只有public static String toString(Object obj);匹配,因为它比其他不等于Object? extends Object匹配得更好

    编辑,我查看了这个问题的初衷:为什么它是用Java 7编译的,而不是用Java 8编译的

    在Java8中,类型推断得到了极大的改进

    例如,在Java 7中,它只能推断getKey返回一个Object,而在Java 8中,它现在推断它返回一个? extends Object

    使用Java7时,只有一个匹配项,即^{

    <> P>为了使变化更加形象化,请考虑这段代码:

    public class TypeInferenceTest {
        public static String toString(Object obj) { return "1"; }
    
        public static String toString(Throwable t) { return "2"; }
    
        public static <U> 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();
        }
    }
    

    在Java 7上它打印1,在Java 8上它打印2,正是因为我上面概述的原因