加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

Java 8模糊方法引用通用类

发布时间:2020-12-14 05:23:14 所属栏目:Java 来源:网络整理
导读:下面的代码在 Java 7中编译并运行正常,但无法在Java 1.8.0中编译u25: public class GenericTest { public static class GenericClassT { T value; public GenericClass(T value) { this.value = value; } } public static class SecondGenericClassT { T va
下面的代码在 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

我已经查看了以下所有更改:
https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.12.2
https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.12.2

但是我没有注意到这个行为的确切原因.

编辑:

只是为了回答一些意见,很清楚,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是一个难读,但包含一个有趣的总结:

The informal intuition is that one method is more specific than another if any invocation handled by the first method could be passed on to the other one without a compile-time type error.

我们可以轻易地为您的案例反驳,具体如下:

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(显着地)改变的最具体的方法的选择,而是由于改进的类型推断的适用性.一旦这两种方法都适用,调用是不明确的,因为这两种方法都不比其他方法更具体.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读