Java 8泛型函数应该是不明确的,但在运行时失败
我正在尝试将
Java 7代码迁移到
Java 8,所以我的代码类似于:
package tests; import java.util.Arrays; import java.util.Map; public class Tests { private static interface ComparableMap<K,V> extends Map<K,V>,Comparable {} public static void main(String[] args) { func(getString()); } private static void func(Comparable...input){ System.out.println(Arrays.toString(input)); } private static void func(ComparableMap <?,?> m){ System.out.println(m); } private static <T extends Comparable> T getString(){ return (T) "aaa"; } } 在java 7中它正常工作,在java 8中我得到:
如果我将一个函数定义更改为: private static <T> T getString(){ return (T) "aaa"; } 编译将失败:错误:
为什么Java 8编译器在第一种情况下没有失败? (看起来对我有误) 解决方法
编译错误
在第一种情况下,需要方法getString来返回Comparable实例.编译器查找func方法的重载,它只找到一个可以接受Comparable:func(Comparable … input)的方法. Map没有实现该接口,因此第二个重载不适用.没有含糊之处. 在第二种情况下,getString可以返回任何内容.这两个重载都有效,因此存在歧义.但请注意,在这两种情况下,对T的强制转换是不安全/错误的. USAfe演员 你编写的泛型方法基本上告诉编译器“我可以返回你想要实现Comparable的任何类的实例”.但你实际上不能遵守这个承诺. 可以说我有以下代码: String str = getString(); Integer num = getString(); 这段代码将编译,String和Integer都实现了Comparable接口.第二行在运行时会失败:代码尝试将String转换为Integer. 你的第二个案例也是错误的,原因与我上面解释的相同.它承诺它可以返回任何你想要的类型.它似乎也不能保持这个承诺(Runnable这里是一个随机的例子,它可以是任何东西): Runnable run = getString() 您更新的代码 编译器看到两个可能的重载,它们都匹配,func(Comparable … input)和func(ComparableMap<?,?> m).它更喜欢第二个,因为varargs方法总是最后选择(for compatebility reasons).所有这些都是核心行为. 然后代码抛出ClassCastException,因为你的getString方法没有保证它的承诺(让调用者决定返回什么类型的Comparable). 怎么解决? 根本问题是你的getString方法犯了一个假承诺.因此,我真的不知道该代码试图完成什么.如果你能详细说明,我们可以帮助你进一步发展. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |