多个通配符边界

时间:2012-09-01 17:49:35

标签: java generics bounded-wildcard

假设我有以下课程:

public class Either<A, B> {
    public Object get();
}

Either是一种存储A或B类型对象的类型。get()检索该对象。

问题是是否可以使用泛型来改变get()的方法签名,以便返回的类型不仅仅是Object,而是A和B的任何常见超类型。例如,Either<Integer, Long>可以get()返回NumberEither<Deque<T>, Set<T>>可以get()返回Iterable<T>Collection<T>,等等上。 (显然,Either<Foo,Foo>应该get()返回Foo。)

如果可能的话,如果我有Either<List<A>, List<B>>,那么最具体的get()类型可以返回什么?它是原始List,通配符List<?>还是完全不同的东西?

4 个答案:

答案 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() {....}
}