【发布时间】:2013-08-18 21:12:30
【问题描述】:
假设我有一个方法“mix”,它接受两个可能不同类型 T 和 S 的列表,并返回一个包含两者元素的列表。为了类型安全,我想指定返回的 List 是 R 类型,其中 R 是 T 和 S 共有的超类型。例如:
List<Number> foo = mix(
Arrays.asList<Integer>(1, 2, 3),
Arrays.asList<Double>(1.0, 2.0, 3.0)
);
要指定这一点,我可以将方法声明为
static <R, T extends R, S extends R> List<R> mix(List<T> ts, List<S> ss)
但是,如果我想在 List2<T> 类上将 mix 设为实例方法而不是静态方法怎么办?
<R, T extends R, S extends R> List<R> mix ...
在List2 的实例上隐藏<T>,所以这不好。
<R, T extends S&T, S extends R> List<R> mix ...
解决了阴影问题,但不被编译器接受
<R super T, S extends R> List<R> mix ...
被编译器拒绝,因为下界通配符不能存储在命名变量中(仅用于? super X 表达式)
我可以将参数移动到类本身,例如List2<R, T extends R, S extends R>,但是类型信息在实例级别上确实没有用,因为它只用于一个方法调用,你必须重新转换每次你想在不同的参数上调用方法时对象。
据我所知,泛型无法做到这一点。我能做的最好的事情就是返回一个原始的List2 并将其投射到调用点,就像在引入泛型之前一样。有人有更好的解决方案吗?
【问题讨论】:
-
为什么你有
S extends T而不是S extends R? -
另外,如果你能展示你的方法的主体会更好 -
mix。你到底在做什么?你真的需要那些类型参数吗?看起来您可以改用有界通配符。 -
其实我不明白
R类型参数的必要性。既然你只是打算返回一个List<Number>,那么就把它作为返回类型。坦率地说,我在这里没有看到任何泛型方法的使用。 -
R 旨在成为 T 和 S 共有的一些超类。对于 Double 和 Integer,它可以是 Number。对于 StringBuilder 和 String,它可以是 CharSequence。对于 Scanner 和 Comparator,它可以是 Object。
-
+1 这个不错。我不认为有办法做到这一点。除非你在
List2类型的声明中声明了T与R的关系。这只是将方法声明中的类型参数移动到类声明中:class List2<R, T extends R, S extends R>,我认为这不是您想要的。
标签: java generics bounded-wildcard