Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/376.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 当使用不相关的接口类型调用时,编译器为什么选择这个带有类类型参数的泛型方法?_Java_Generics_Java 8_Language Lawyer_Javac - Fatal编程技术网

Java 当使用不相关的接口类型调用时,编译器为什么选择这个带有类类型参数的泛型方法?

Java 当使用不相关的接口类型调用时,编译器为什么选择这个带有类类型参数的泛型方法?,java,generics,java-8,language-lawyer,javac,Java,Generics,Java 8,Language Lawyer,Javac,考虑以下两个类和接口: 公共类Class1{} 公共类2{} 公共接口接口1{} 如果getInterface1和Interface1与Class2没有关系,为什么对mandatory的第二次调用调用调用了Class2的重载方法 公共类测试{ 公共静态void main(字符串[]args){ Class1=getClass1(); Interface1 Interface1=getInterface1(); 必需(getClass1());//打印“T不是类2” 必需(getInterfac

考虑以下两个类和接口:

公共类Class1{}
公共类2{}
公共接口接口1{}
如果
getInterface1
Interface1
Class2
没有关系,为什么对
mandatory
的第二次调用调用调用了
Class2
的重载方法

公共类测试{
公共静态void main(字符串[]args){
Class1=getClass1();
Interface1 Interface1=getInterface1();
必需(getClass1());//打印“T不是类2”
必需(getInterface1());//打印“T是类2”
必选(类别1);//打印“T不是类别2”
必需(接口1);//打印“T不是类2”
}
公共静态无效强制(TO){
System.out.println(“T不是类2”);
}
公共静态无效强制(TO){
System.out.println(“T是class2”);
}
公共静态T getClass1(){
返回null;
}
公共静态T getInterface1(){
返回null;
}
}
我知道Java 8和Java 7:

$ /usr/lib/jvm/java-8-openjdk-amd64/bin/javac -source 1.7 -target 1.7 *java; /usr/lib/jvm/java-8-openjdk-amd64/bin/java Test
warning: [options] bootstrap class path not set in conjunction with -source 1.7
1 warning
T is not class2
T is not class2
T is not class2
T is not class2
使用Java 8(也使用11和13进行了测试):


在Java8中,类型推理规则得到了重大的改进,最显著的是目标类型推理得到了很大的改进。因此,在Java 8之前,方法参数站点没有收到任何推断,默认为擦除类型(
Class1
对于
getClass1()
Interface1
对于
getInterface1()
),在Java 8中,推断出最具体的适用类型。jlsforjava8引入了jlsforjava7中缺少的一章


最具体的适用类型是
,其中
RequiredClass
是上下文所需的类,
BottomInterface
是所有接口的底部类型(包括
Interface1

注意:每个Java类型都可以表示为
SomeClass&SomeInterfaces
。由于
RequiredClass
SomeClass
的子类型,
BottomInterface
someInterface
的子类型,
X
是每个Java类型的子类型。因此,
X
是一种Java底层类型

X
匹配
公共静态无效强制(to)
公共静态无效强制(to)
方法签名,因为
X
是Java底部类型

因此,根据,
mandatory(getInterface1())
调用了
mandatory()
方法中最具体的重载,即
公共静态无效强制(to)
,因为
更具体

下面是如何显式指定
getInterface1()
type参数,使其返回与
publicstaticvoidmandatory(to)
方法签名匹配的结果:

public static <T extends Class2 & Interface1> void helper() {
    mandatory(Test.<T>getInterface1()); // prints "T is class2"
}
                       java: interface expected here
                                     ↓
public static <T extends Class1 & C̲l̲a̲s̲s̲2> void helper() {
    mandatory(Test.<T>getClass1());
}

一句话:Java中的方法重载带来了如此多的惊喜,在使用时应该非常小心。仅通过类型参数的界来区分两个重载是自找麻烦的,答案的复杂性就证明了这一点。您基本上是要求代码的每个读者在理解代码之前阅读并理解该答案。换言之:如果你的程序在类型推断得到改进时中断了,那么你就不在安全区域。祝你好运
                       java: interface expected here
                                     ↓
public static <T extends Class1 & C̲l̲a̲s̲s̲2> void helper() {
    mandatory(Test.<T>getClass1());
}