Java 8模糊方法引用通用类
下面的代码在
Java 7中编译并运行正常,但无法在Java 1.8.0中编译u25:
public class GenericTest { public static class GenericClass<T> { T value; public GenericClass(T value) { this.value = value; } } public static class SecondGenericClass<T> { T value; public SecondGenericClass(T value) { this.value = value; } } public static<T >void verifyThat(SecondGenericClass<T> actual,GenericClass<T> matcher) { } public static<T >void verifyThat(T actual,GenericClass<T> matcher) { } @Test public void testName() throws Exception { verifyThat(new SecondGenericClass<>(""),new GenericClass<>("")); } } Java 8中的错误消息如下所示: Error:(33,9) java: reference to verifyThat is ambiguous both method <T>verifyThat(com.sabre.ssse.core.dsl.GenericTest.SecondGenericClass<T>,com.sabre.ssse.core.dsl.GenericTest.GenericClass<T>) in com.sabre.ssse.core.dsl.GenericTest and method <T>verifyThat(T,com.sabre.ssse.core.dsl.GenericTest.GenericClass<T>) in com.sabre.ssse.core.dsl.GenericTest match 我已经查看了以下所有更改: 但是我没有注意到这个行为的确切原因. 编辑: 只是为了回答一些意见,很清楚,Java 7和8中的编译器将能够处理这种调用(签名类似于编译时类型擦除之后留下的签名: public static void verifyThat(SecondGenericClass actual,GenericClass matcher) { } public static void verifyThat(Object actual,GenericClass matcher) { } @Test public void testName() throws Exception { verifyThat(new SecondGenericClass<>(""),new GenericClass<>("")); } 为通用方法生成的字节码和已擦除的字节码是一样的,如下所示: public static verifyThat(Lcom/sabre/ssse/core/dsl/GenericTest$SecondGenericClass;Lcom/sabre/ssse/core/dsl/GenericTest$GenericClass;)V public static verifyThat(Ljava/lang/Object;Lcom/sabre/ssse/core/dsl/GenericTest$GenericClass;)V EDIT2: javac 1.8.0_40下的编译失败,出现相同的错误 解决方法
JLS,chapter §15.12.2.5 Choosing the Most Specific Method是一个难读,但包含一个有趣的总结:
我们可以轻易地为您的案例反驳,具体如下: GenericTest.<String>verifyThat( // invokes the first method new SecondGenericClass<>(""),new GenericClass<>("")); GenericTest.<SecondGenericClass<String>>verifyThat( // invokes the second new SecondGenericClass<>(""),new GenericClass<>(null)); 所以这里没有最具体的方法,但是,如示例所示,可以使用使其他方法不适用的参数来调用任一方法. 在Java 7中,由于编译器尝试(参见编译器)有限的寻找类型参数以使更多方法适用(也称为有限类型推断),因此更容易使方法不适用.新的SecondGenericClass(“”)表达式具有SecondGenericClass< String>从它的论证推断“”就是这样.因此,对于调用verifyThat(new SecondGenericClass(“”),新的GenericClass(“”)),参数的类型为SecondGenericClass< String>和GenericClass< String>这使得方法< T> void verifyThat(T,GenericClass
GenericTest.<Object>verifyThat(new SecondGenericClass<>(""),new GenericClass<>("")); 毫无疑问(在Java 8中),即使Eclipse也同意这一点.相反,调用 verifyThat(new SecondGenericClass<>(""),new GenericClass<String>("")); 具体足以使第二种方法不适用并调用第一种方法,这给我们提供了一个关于Java 7中发生的情况的提示,其中新的GenericClass(“”)的类型被固定为GenericClass< String>就像新的GenericClass< String>(“”). 底线是,它不是从Java 7到Java 8(显着地)改变的最具体的方法的选择,而是由于改进的类型推断的适用性.一旦这两种方法都适用,调用是不明确的,因为这两种方法都不比其他方法更具体. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- Android 获取SD卡路径和空间使用情况
- 运行JMS使用者时的java.lang.NoClassDefFoundError
- java – 生成的Web服务客户端类,没有setter
- java – appengine-maven-plugin配置选项,如jvm标志
- Java论证的奇怪行为*
- JAVA WEB项目目录结构以及web应用部署的根目录,编译路径和
- 如何用组合框和2个按钮制作一个java swing弹出窗口?
- java – 你可以批量选择IntelliJ IDEA中的引号之间的文本吗
- maven 隐式依赖引起的包冲突解决办法
- JSP config.getInitParameter()方法获取初始参数的值