我想定义一个通用参数,它应该扩展 Map 或 Collection,但我不知道该怎么做:
public <T> void test(T t) {}
我可以这样写:
public <T extends Map> void test(T t) {}
或者
public <T extends Collection> void test(T t) {}
但我不知道是否可以让 T 在单个方法中扩展 Map 或 Collection。
简短的回答:没有。
您打算如何处理t
方法中的参数?由于Map
and Collection
have 仅Object
作为它们的共同超类型,因此您可以调用的唯一方法t
将是那些 on Object
。(即使两个接口上的方法,例如size()
,也会被编译器拒绝。)
考虑到这一点,在这种情况下您是否有任何理由不能重载该方法?也就是说,为每个所需的参数类型定义一个实现:
public void test(Map<?,?> t) { ... }
public void test(Collection<?> t) { ... }
如果您出于某种原因不想这样做,那么您似乎同样可以声明要采用的方法Object
并执行该类的运行时类型检查。这在语义上是等效的,因为无论如何您都必须强制转换为 callMap
或Collection
-specific 方法,尽管这确实意味着类型检查是在编译时而不是运行时完成的。Java 的类型系统不允许您表达这种联合类型的依赖关系,所以我看不到任何其他选择。
不,这是不可能的,但您可以创建两个单独的方法:
public <T extends Map> void test(T t) {
// do the map part
}
public <T extends Collection> void test(T t) {
// do the collection part
}
如果你想将它们混合在一个处理方法中,你也可以这样写:
private void mixedTest(Object t) {
if (t instanceof Map) {
// map part
} else if (t instanceof Collection) {
// collection part
} else {
throw new RuntimeException("Unknown object");
}
}
并致电:
public <T extends Map> void test(T t) {
mixedTest(t);
}
public <T extends Collection> void test(T t) {
mixedTest(t);
}
但我不确定它是否会导致一个很好的代码。对于不同类型的对象,我会坚持使用不同实现的第一部分。
关于什么
public <T extends Map> void test(Map t) {}
和
public <T extends Collection> void test(Collection t) {}
...然后让 Java 选择正确的使用?