接受不同的Set-implementation作为参数

时间:2014-04-13 18:25:58

标签: java

我正在尝试编写一个能够接受这两个对象中的任何一个作为参数的函数:

private static TreeSet<String> TREESET = new TreeSet<String>();
private static HashSet<String> HASHSET = new HashSet<String>();

我试过这样的

public static void printSet(Set s) {
  //
}

public static void printSet(Set<String> s) {
  //
}

即使在调用时转换集合,我也会收到错误。这样做的正确方法是什么?

更新1

我已尝试过无铸造:

printSet(SET);
printSet((Set) SET);
printSet((Set<String> SET);

更新2

错误:

  

线程中的异常&#34; main&#34; java.lang.ClassCastException:无法在HashTreeSetClient.main(HashTreeSetClient.java:34)中将TreeSet强制转换为java.util.Set

2 个答案:

答案 0 :(得分:1)

就像你一样使用泛型。

public static <T> void printSet(Set<T> s) {
  //
}

避免原始类型。


或者只是Set<String> s正如其他人所说的那样。

public static void printSet(Set<String> s) {
  //
}

Set是一个接口,在方法中接受实现此接口的每个类。

答案 1 :(得分:0)

我认为你误解了Set界面的目的。任何实现Set的类都可以视为 a Set

这就是为什么这些声明是合法的:

Set<String> stringSet = new HashSet<>();
Set<String> treeSet = new TreeSet<>();

现在让我们考虑你的方法:

public static void printSet(Set<String> s) {
    // logic
}

这种方法告诉我的是,你并不关心你使用的Set的具体类型,但实际上它可以被认为是Set

实际上,这意味着这两个方法调用都是合法的:

printSet(TREESET);
printSet(HASHSET);

...并且绝对不需要强制转换,因为TreeSetHashSet都实现了Set接口。

非常重要但是,您的集合上的泛型类型参数与方法签名匹配。

例如,这不起作用:

HashSet<Integer> hashSet = new HashSet<>();
printSet(hashSet); // compilation error

如果出于某种原因,您希望接受带有任何泛型类型参数的Set,则可以使用此语法来实现此目的:

public static void printSet(Set<?> s) {
    // logic
}

?通配符类型。它隐式扩展Object,可以用来接受任何通用类型。