Java泛型:使用类和接口 - 一起

436

我想要一个Class对象,但是我希望它所代表的类强制继承类A并实现接口B。

我可以这样做:

Class<? extends ClassA>

或:

Class<? extends InterfaceB>

但我不能两者兼顾,有什么办法可以做到这一点吗?

2个回答

698

实际上,你是可以做你想要的事情的。如果你想提供多个接口或者一个类加接口,你需要让你的通配符看起来像这样:

<T extends ClassA & InterfaceB>

请查看sun.com上的泛型教程,特别是页面底部的有界类型参数部分。您实际上可以列出多个接口,如果需要每个接口使用& InterfaceName
这可能会变得任意复杂。为了演示,请参见Collections#max的JavaDoc声明,它(换行成两行)是:
public static <T extends Object & Comparable<? super T>> T
                                           max(Collection<? extends T> coll)

为什么这么复杂?正如Java泛型FAQ中所说:为了保持二进制兼容性。看起来这在变量声明时不起作用,但在将泛型边界放在类上时却有效。因此,要做你想做的事情可能需要跨越一些障碍,但你可以做到。你可以像这样,在你的类上放一个泛型边界。
class classB { }
interface interfaceC { }

public class MyClass<T extends classB & interfaceC> {
    Class<T> variable;
}

要获取符合你要求的变量。更多信息和示例,请查看Java 5.0中的泛型第3页。请注意,在<T extends B & C>中,类名必须放在前面,接口紧随其后。当然,你只能列出一个类。


109
有帮助。值得一提的是,类必须放在最前面,你不能写成'<T extends InterfaceB & ClassA>'。 - EricS
7
针对T如何实现相同的功能,您需要扩展一个类或实现一个接口。 - Ragunath Jawahar
2
@RagunathJawahar:在这方面,你不能太开放。你必须有一些边界,其中之一是事先知道你将在哪里拥有接口和类,以及如何使用继承。你几乎必须知道类型参数是类还是接口。 - Eddie
4
您的问题中提到第一行回答说“让您的通配符看起来像这样”,那个表达式中没有?,所以它真的是一个“通配符”吗?我问这个问题是因为当类型参数真的是通配符时,我无法使“同时扩展两个东西”的整个概念正常工作。 - The111
2
是的,它并不是真正的通配符,你不能使用通配符来完成OP所要求的操作。实际上,你可以有效地完成OP想要的操作,只是不能使用通配符。 - Eddie
显示剩余13条评论

21
你无法使用“匿名”类型参数(即使用?的通配符)来完成此操作,但可以使用“命名”类型参数。只需在方法或类级别声明类型参数即可。
import java.util.List;
interface A{}
interface B{}
public class Test<E extends B & A, T extends List<E>> {
    T t;
}

6
为什么不允许使用通配符?即我不明白为什么以下代码不被认为是有效的: ArrayList<? extends ClassA & InterfaceB> list; 如果你从列表中获取了一个元素,你可以将其赋给类型为ClassA或InterfaceB的变量。 - Mark
将通配符替换为变量是一种很棒的技巧!但它并不总是适用。例如,Java不允许在注释值类型中使用命名类型变量,而允许使用通配符。 - sigpwned

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接