2016-08-18 74 views
4

我试图运行下面的代码被JDK8感谢下编译罚款类型推断:JDK8类型推断问题

public static <A,B> B convert(A a) { 
    return (B) new CB(); 
} 
public static void main(String[] args) { 
    CA a = new CA(); 
    CB b = convert(a); //this runs fine 
    List<CB> bl = Arrays.asList(b); //this also runs fine 
    List<CB> bl1 = Arrays.asList(convert(a)); //ClassCastException here 
} 

但是,在运行,这将引发ClassCastException异常:CB不能转换为[Ljava.lang .Object,但CB b = convert(a)正常工作。

任何想法为什么?

+3

等等,转换甚至在做什么?它的参数被忽略,所以传入的内容并不重要。 – Carcigenicate

+1

您使用哪个JRE版本?我在1.8.0_92上得到了一个操作数栈上的java.lang.VerifyError:Bad type。顺便说一句,使用类型见证对我有用:'List bl1 = Arrays.asList(Test。 convert(a));' –

+1

@StefanZobel确实有效,但我用了150次左右的用法并且手动更改并不容易 - 我希望JDK8能够自动进行推理 –

回答

3

无论何时您创建一个带有签名的泛型方法,该签名都会承诺返回调用者所希望的任何内容,这样您就会遇到麻烦。你应该从编译器得到一个“unchecked”警告,这基本上意味着:可能会出现意想不到的ClassCastException

你期望编译器来推断

List<CB> bl1 = Arrays.asList(YourClass.<CA,CB>convert(a)); 

而编译器实际上推断

List<CB> bl1 = Arrays.asList(YourClass.<CA,CB[]>convert(a)); 

据我知道,因为它更不需要一个可变参数的包装(这是兼容的方法调用pre-varargs代码)。

这会失败,因为您的convert方法不会返回预期的数组类型。