假设我有以下课程:
public class Either<A, B> {
public Object get();
}
Either
是一种存储A或B类型对象的类型。get()
检索该对象。
问题是是否可以使用泛型来改变get()
的方法签名,以便返回的类型不仅仅是Object
,而是A和B的任何常见超类型。例如,Either<Integer, Long>
可以get()
返回Number
,Either<Deque<T>, Set<T>>
可以get()
返回Iterable<T>
或Collection<T>
,等等上。 (显然,Either<Foo,Foo>
应该get()
返回Foo
。)
如果可能的话,如果我有Either<List<A>, List<B>>
,那么最具体的get()
类型可以返回什么?它是原始List
,通配符List<?>
还是完全不同的东西?
答案 0 :(得分:2)
Java推理确实有类似的东西,我们可以做到
public static <C, A extends C, B extends C> C get(Either<A,B> e)
{ return (C)e.get(); }
inference:
A=Integer, B=Long ==> C=Number
A=List<Integer>, B=List<Long> ==> C=List<? extends Number>
usage:
Either<Integer, Long> x = ...;
get(x); // the return type is Number
但是,可能无法将其转换为实例方法。我们需要写
public class Either<A,B>
public <C super A|B> C get() { ... }
or simply
public A|B get(){ ... }
在Java
中不受支持答案 1 :(得分:1)
为什么不定义一个抽象类C,包含你认为必要的A和B共同的逻辑,并在你的Either类中引用它:
public class Either<C> {
public C get();
}
这似乎不是一个答案,但是因为Java在编译时会删除你的类型信息(也就是说,你的编译代码只能看到Object
而不是A
或者B
),那么您最有可能定义应该在显式公共类中保留的内容。
答案 2 :(得分:1)
据我所知,这是不可能的:你的Either<A,B>
类假设一个通用的第三种类型(我们称之为C
),A和B都会扩展:可以编写类似public class Either<A extends MyNonFinalClass, B extends MyNonFinalClass> {}
的内容,Java不允许前向引用泛型类型,因此您甚至无法编写类似Either<A extends C, B extends C, C>
的内容。显然是一种耻辱,因为你的Either
课真的很方便:)
答案 3 :(得分:1)
你需要确保A和B共享一个共同的祖先。
public class Either<A extends CommonAncestor, B extends CommonAncestor> {
public CommonAncestor get() {....}
}
或
public class Either<C, A extends C, B extends C> {
public C get() {....}
}