如何在将泛型Collection传递给legacy方法时避免类型转换?

时间:2015-02-02 09:09:21

标签: java generics

我有以下代码

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>)

因此,我必须修改遗留方法以接受类型化参数,或者每次调用方法时强制转换方法参数。 为什么上述代码不起作用?有没有其他更清洁的方法来使这项工作?

4 个答案:

答案 0 :(得分:3)

问题在于Set<T extends Number>(来自地图)和Set<Number>someLegacyMethod参数)之间的兼容性。

T extends Number可以在运行时使用IntegerLongDouble等替换,然后map.keySet()将返回Set<Integer>Set<Long>Set<Double>

现在的问题是

  

Set<Double>(例如)是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);
}

答案 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>();