8

假设我有以下课程:

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

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

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

如果这是可能的,如果我有,可以返回Either<List<A>, List<B>>的最具体的类型是什么?get()它是 raw List, wildcardList<?>还是完全其他的东西?

4

4 回答 4

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不支持

于 2012-09-01T22:28:51.497 回答
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() {....}
}
于 2012-09-01T21:46:04.080 回答
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课真的很方便:)

于 2012-09-01T19:44:26.247 回答
1

为什么不定义一个抽象类 C,其中包含您认为必要的 A 和 B 共有的逻辑,并在您的 Either 类中引用它:

public class Either<C> {
    public C get();
}

这似乎不是一个很好的答案,但是由于 Java 在编译时无论如何都会删除您的类型信息(也就是说,您的编译代码只能看到Object而不是 anA或 a B),那么您最适合定义应该保留在显式公共类中。

于 2012-09-01T18:20:34.413 回答