[英]How does java determine, which overloaded method will call, when one method with generic type parameter and other with non generic parameter?
Java class 不能有两个在类型擦除后具有相同签名的重载方法。 Java 将在以下情况下生成编译时错误:
public class Example {
public void print(Set<String> strSet) { }
public void print(Set<Integer> intSet) { }
}
但我的问题不是这样。 有两种情况1和2。我想知道,为什么他们的行为不一样?
Scenario 1
:
import java.util.ArrayList;
import java.util.List;
public class MethodOverload {
public static void main(String[] args) {
MethodOverload methodOverload = new MethodOverload();
//Point 1 - List here
List<Integer> mangoList = new ArrayList<Integer>();
mangoList.add(1);
mangoList.add(2);
System.out.println("Size List<Integer>:"+methodOverload.count(mangoList));
//Point 2 - ArrayList here
ArrayList<String> nameList = new ArrayList<String>();
nameList.add("Anex");
nameList.add("Alia");
nameList.add("Maxim");
System.out.println("Size List<String>:"+methodOverload.count(nameList));
}
public <T> int count(List<T> list) {
System.out.print("Ïn side generic; ");
return list.size();
}
}
Output,对于场景 1:
Inside generic block; Size List<Integer> : 2
Inside generic block; Size List<String> : 3
Scenario 2:
import java.util.ArrayList;
import java.util.List;
public class MethodOverload {
public static void main(String[] args) {
MethodOverload methodOverload = new MethodOverload();
//Point 3 - List here
List<Integer> mangoList = new ArrayList<Integer>();
mangoList.add(1);
mangoList.add(2);
System.out.println("Size List<Integer>:"+methodOverload.count(mangoList));
//Point 4 - ArrayList here
ArrayList<String> nameList = new ArrayList<String>();
nameList.add("Anex");
nameList.add("Alia");
nameList.add("Maxim");
System.out.println("Size List<String>:"+methodOverload.count(nameList));
}
public <T> int count(List<T> list) {
System.out.print("Inside generic block; ");
return list.size();
}
//Point 5
public int count(ArrayList<String> list) {
System.out.print("Inside non-generic block; ");
return list.size();
}
}
Output,对于场景 2:
Inside generic block; Size List<Integer> : 2
Inside non-generic block; Size List<String> : 3
现在,我的问题是,java 如何决定在scenario 2
的情况下调用哪个方法? 在scenario 1
中,java 调用单计数方法没有任何问题,那么为什么 java 不显示scenario 2
的类似行为?
在 Java 中,方法参数类型是方法签名的一部分
因此,该方法将在编译时根据参数类型进行绑定。 (这不应被误解为调用方法的参考变量的多态行为,比如methodOverload
在上面的代码中,
List
的第一个调用将绑定到以List
作为参数类型的方法List
作为参数类型的方法,并假设存在以ArrayList
作为参数的方法。 编译器如何保证List
在运行时实际上是一个ArrayList
以维护类型安全承诺。 既然不能,那就禁止这种绑定。ArrayList
类型的第二次调用将绑定到具有确切类型ArrayList
的方法(如果存在)。 如果该方法不存在,则将其映射到List
方法(如果考虑 generics,则具有相关的泛型)本质上,
最后的想法
因为类型擦除仅适用于泛型类型。 Java 不会“擦除”inheritance。
在场景 1 中,count() 方法签名在运行时有效地变为:
public int count(List<Object> list) {...}
因此 mangoList(声明为 List)和 nameList(声明为 ArrayList)都符合此签名。
在场景 2 中,方法签名在运行时有效地变为:
public int count(List<Object> list) {...}
public int count(ArrayList<Object> list) {...}
Java 早在 generics 出现之前就知道如何执行此(基于继承的)重载。 它不能做的是基于未绑定的泛型类型的重载,因为运行时类型擦除,这就是编译器阻止你这样做的原因。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.