将泛型 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 可以在运行时替换为 IntegerLongDouble 等,然后 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>();