我有以下代码
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>)
因此,我必须修改遗留方法以接受类型化参数,或者每次调用方法时强制转换方法参数。 为什么上述代码不起作用?有没有其他更清洁的方法来使这项工作?
答案 0 :(得分:3)
问题在于Set<T extends Number>
(来自地图)和Set<Number>
(someLegacyMethod
参数)之间的兼容性。
T extends Number
可以在运行时使用Integer
,Long
,Double
等替换,然后map.keySet()
将返回Set<Integer>
,Set<Long>
,Set<Double>
。
现在的问题是
Set<Double>
(例如)是Set<Number>
的子类吗?
从您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);
}
答案 1 :(得分:0)
map.keySet()
为someLegacyMethod返回类型为T
的键集
将Set<Number>
更改为Set<T>
。
答案 2 :(得分:0)
你应该创建一个新的包装器方法来检查是否是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
}
答案 3 :(得分:0)
因为它无法识别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 "";
}
}
然后以这种方式实现你的课程:
new GenericText<ExtendsNumber>();