类型推断的差异JDK8 javac / Eclipse Luna? [英] Differences in type inference JDK8 javac/Eclipse Luna?

查看:137
本文介绍了类型推断的差异JDK8 javac / Eclipse Luna?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试将项目切换到Java8,并在Eclipse Luna和javac的类型推断之间遇到奇怪的差异。使用JDK 1.7.0_65 javac这段代码编译很好。 JDK 1.8.0_11抱怨toString(char [])和toString(Throwable)都匹配toString(getKey(code,null));线。 Eclipse Luna 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(){
对象代码=test;
toString(getKey(code,null));
}
}

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



当然我可以简单地向Object添加一个转换,但我想知道为什么javac不能自己违反类型(而eclipse),以及为什么javac认为Throwable和char []适合匹配,而不是Object。



这是Eclipse或javac中的错误吗? (我的意思是只有一个编译器可以在这里,无论是编译还是不编译)



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

  C:\XXXX\Workspace\XXXX\src> javac -cp。 TypeInferenceTest.java 
TypeInferenceTest.java:22:error:引用toString是不明确的
toString(getKey(code,null));
^
TypeInferenceTest中的方法toString(char [])和TypeInferenceTest中的方法toString(Throwable)匹配
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(){
对象代码=test;
toString(getKey(code,null));
}
}

另请注意, ; U> U getKey(...)的确是:< U extends Object> U getKey(...)



所有它都知道 getKey(code,null)返回是:?扩展Object ,所以它返回一个子类型 Object 或一个 Object 本身。 br>
有三个匹配的签名,即 Object char [] Throwable ,其中 char [] Throwable code> Object ,因为你要求一个?扩展对象



所以它不能选择哪一个是正确的,因为所有三个匹配的签名。



当您将其更改为:

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

然后只有 public static String toString(Object obj); 匹配,因为它与更好地匹配任何其他?扩展对象不等于 Object



编辑,我查看了这个问题的原始意图:为什么它在Java 7中编译,但不是在Java 8中编译?



在Java 8中,类型推断得到很大的改善



而在Java 7中,例如只能推断出 getKey 返回一个对象,它现在在Java 8推测它返回一个?扩展对象



当使用Java 7时,只有一个匹配,即 Object



为了使更改可视化更好,请考虑这段代码:

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

public static String toString(Throwable t){return2; }

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

public static void test(){
对象代码=test;
String result = toString(getKey(code,null));
System.out.println(result);
}

public static void main(String [] args){
test();
}
}

在Java 7上打印 1 ,在Java 8上,它打印 2 ,正是由于上述原因。


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 fine. JDK 1.8.0_11 complains that both toString(char[]) and toString(Throwable) match for the "toString(getKey(code, null));" line. Eclipse Luna 4.4 (I20140606-1215) compiles it happily with either 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));
    }
}

I think the only signature that could possibly match is toString(Object).

Of course I could simply add a cast to Object, but I wonder why javac can't infere the type by itself (while eclipse does), and why the heck javac considers Throwable and char[] suitable matches, but not Object.

Is this a bug in Eclipse or javac? (I mean only one compiler can be right here, either it compiles or it doesn't)

Edit: Error message from 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

解决方案

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> U getKey(Object code, U defaultValue);

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

Also note that the <U> U getKey(...) really is: <U extends Object> 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> 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.

这篇关于类型推断的差异JDK8 javac / Eclipse Luna?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆