具有多个类的Java泛型通配符

Ale*_*ley 369 java generics class bounded-wildcard

我想要一个Class对象,但我想强制它所代表的任何类来扩展A类并实现接口B.

我可以:

Class<? extends ClassA>
Run Code Online (Sandbox Code Playgroud)

要么:

Class<? extends InterfaceB>
Run Code Online (Sandbox Code Playgroud)

但我不能两者兼顾.有没有办法做到这一点?

Edd*_*die 584

实际上,你可以做你想做的事.如果要提供多个接口或类加接口,则必须使用通配符,如下所示:

<T extends ClassA & InterfaceB>
Run Code Online (Sandbox Code Playgroud)

请参阅sun.com上的Generics Tutorial,特别是页面底部的Bounded Type Parameters部分.如果您愿意,您实际上可以列出多个界面,使用& InterfaceName您需要的每个界面.

这可能会变得任意复杂.为了演示,请参阅JavaDoc声明Collections#max,其中(包含在两行中)是:

public static <T extends Object & Comparable<? super T>> T
                                           max(Collection<? extends T> coll)
Run Code Online (Sandbox Code Playgroud)

为什么这么复杂?正如Java Generics FAQ中所述:保持二进制兼容性.

看起来这对变量声明不起作用,但是当在类上放置泛型边界时它确实有效.因此,要做你想做的事,你可能不得不跳过几个圈.但你可以做到.你可以这样做,在你的类上放置一个通用的边界,然后:

class classB { }
interface interfaceC { }

public class MyClass<T extends classB & interfaceC> {
    Class<T> variable;
}
Run Code Online (Sandbox Code Playgroud)

得到variable那个有你想要的限制.有关更多信息和示例,请查看Java 5.0泛型的第3页.请注意,<T extends B & C>类名必须首先出现,接口如下.当然,你只能列出一个班级.

  • 这很有帮助.值得一提的是,_must_类首先出现,你不能说'<T extends InterfaceB&ClassA>'. (90认同)
  • 你如何做同样的T应该扩展一个类或实现一个接口? (4认同)
  • 答案的第一行说"让你的通配符看起来像这样." 那个表达式中没有`?`,它真的是一个"通配符"吗?我问,因为当type参数确实是通配符时,我无法将整个"一次扩展两件事"的概念用于工作. (4认同)
  • @RagunathJawahar:你不能对此太过开放。您必须有一些边界,其中之一是提前知道哪里将有接口,哪里将有类,以及如何使用继承。您几乎必须知道类型参数是类还是接口。 (2认同)
  • 是的,它不是真正的通配符,您无法使用通配符执行 OP 要求的操作。你 ** 可以** 做 OP 想要的,有效的,只是不用通配符。 (2认同)

小智 16

您不能使用"匿名"类型参数(即使用的通配符?)来执行此操作,但您可以使用"命名"类型参数执行此操作.只需在方法或类级别声明类型参数即可.

import java.util.List;
interface A{}
interface B{}
public class Test<E extends B & A, T extends List<E>> {
    T t;
}
Run Code Online (Sandbox Code Playgroud)

  • 为什么不允许使用通配符?即我不明白为什么这应该是无效的:ArrayList &lt;?扩展ClassA和InterfaceB&gt;列表;然后,如果将元素从列表中拉出,则可以将其分配给ClassA或InterfaceB类型的变量 (2认同)