将泛型 Collection 传递给遗留方法时如何避免类型转换?
How to avoid type casting while passing generic Collection to legacy method?
我有以下代码
public class GenericTest {
public <T extends Number> void someMethod(){
Map<T, String> map = new HashMap<>();
someLegacyMethod(map.keySet()); // COMPILER ERROR
}
public String someLegacyMethod(Set<Number> nums){
//some logic
return "";
}
}
我原以为 someLegacyMethod 可以按原样调用,因为 T 是 Number 类型。但是编译器给我一个错误。
The method someLegacyMethod(Set<Number>) in the type GenericTest is not applicable for the arguments (Set<T>)
所以要么我必须修改遗留方法以接受它的类型化参数,要么在每次调用该方法时强制转换方法参数。
为什么上面的代码不起作用?还有其他更简洁的方法来完成这项工作吗?
问题在于 Set<T extends Number>
(来自地图)和 Set<Number>
(someLegacyMethod
参数)之间的兼容性。
T extends Number
可以在运行时替换为 Integer
、Long
、Double
等,然后 map.keySet()
将 return分别是 Set<Integer>
、Set<Long>
、Set<Double>
。
现在的问题是
Is the Set<Double>
(for instance) a subclass of Set<Number>
?
The answer is no.
从你的名字 someLegacyMethod()
我可以假设你不能为它引入泛型。您唯一可以做的就是将键集的内容复制到 Set<Number>
:
public <T extends Number> void someMethod() {
Map<T, String> map = new HashMap<>();
Set<Number> set = new HashSet<Number>(map.keySet());
someLegacyMethod(set);
}
map.keySet()
returns 您的 someLegacyMethod 类型为 T
的键集
将 Set<Number>
更改为 Set<T>
。
您应该创建新的包装方法来检查是否是 instanceOf 或抛出 illegalArgumentException。
public String wrapperOfSomeLegacyMethod(Set<T extends Number> nums) throws IllegalArgumentException{
//itervate over num. check if isntance of Number
//if yes, call someLegacyMethod
//if no , throw illegalArgumentException
}
因为它不识别 T
我会这样做:
public class GenericTest <T extends Number> {
public T void someMethod(){
Map<T, String> map = new HashMap<>();
someLegacyMethod(map.keySet()); // COMPILER ERROR
}
public String someLegacyMethod(Set<T> nums){
//some logic
return "";
}
}
然后以这种方式实例化您的 class:
new GenericText<ExtendsNumber>();
我有以下代码
public class GenericTest {
public <T extends Number> void someMethod(){
Map<T, String> map = new HashMap<>();
someLegacyMethod(map.keySet()); // COMPILER ERROR
}
public String someLegacyMethod(Set<Number> nums){
//some logic
return "";
}
}
我原以为 someLegacyMethod 可以按原样调用,因为 T 是 Number 类型。但是编译器给我一个错误。
The method someLegacyMethod(Set<Number>) in the type GenericTest is not applicable for the arguments (Set<T>)
所以要么我必须修改遗留方法以接受它的类型化参数,要么在每次调用该方法时强制转换方法参数。 为什么上面的代码不起作用?还有其他更简洁的方法来完成这项工作吗?
问题在于 Set<T extends Number>
(来自地图)和 Set<Number>
(someLegacyMethod
参数)之间的兼容性。
T extends Number
可以在运行时替换为 Integer
、Long
、Double
等,然后 map.keySet()
将 return分别是 Set<Integer>
、Set<Long>
、Set<Double>
。
现在的问题是
Is the
Set<Double>
(for instance) a subclass ofSet<Number>
?
The answer is no.
从你的名字 someLegacyMethod()
我可以假设你不能为它引入泛型。您唯一可以做的就是将键集的内容复制到 Set<Number>
:
public <T extends Number> void someMethod() {
Map<T, String> map = new HashMap<>();
Set<Number> set = new HashSet<Number>(map.keySet());
someLegacyMethod(set);
}
map.keySet()
returns 您的 someLegacyMethod 类型为 T
的键集
将 Set<Number>
更改为 Set<T>
。
您应该创建新的包装方法来检查是否是 instanceOf 或抛出 illegalArgumentException。
public String wrapperOfSomeLegacyMethod(Set<T extends Number> nums) throws IllegalArgumentException{
//itervate over num. check if isntance of Number
//if yes, call someLegacyMethod
//if no , throw illegalArgumentException
}
因为它不识别 T
我会这样做:
public class GenericTest <T extends Number> {
public T void someMethod(){
Map<T, String> map = new HashMap<>();
someLegacyMethod(map.keySet()); // COMPILER ERROR
}
public String someLegacyMethod(Set<T> nums){
//some logic
return "";
}
}
然后以这种方式实例化您的 class:
new GenericText<ExtendsNumber>();