我刚刚测试了它,作业本身编译。变化的是你是否真的可以调用.predicate.test()
让我们退后一步,使用占位符进行解释。对于类型参数,扩展和扩展 。GenericClass<T>
Foo
Bar
Bar
Baz
扩展:当你声明一个时,你是在说“我不知道它的泛型类型参数实际上是什么,但它是的子类。实际实例将始终具有非通配符类型参数,但在代码的这一部分中,您不知道它的值是什么。现在考虑一下这对方法调用意味着什么。GenericClass<? extends Bar>
Bar
你知道你实际得到的要么是 a,要么是 .考虑一个返回 的方法。在前一种情况下,其返回类型为 。在后者中,.无论哪种方式,它都是 的子类型,并且可以安全地分配给变量。GenericClass<Foo>
GenericClass<Bar>
T
Foo
Bar
Bar
Bar
考虑一个具有参数的方法。如果它是 a ,则传递给 a 是一个错误 - 不是 的子类型。T
GenericClass<Foo>
Bar
Bar
Foo
因此,对于上限,您可以使用泛型返回值,但不能使用泛型方法参数。
Super:当你声明一个 时,你是在说“我不知道它的泛型类型参数实际上是什么,但它是一个超类。现在考虑一下这对方法调用意味着什么。GenericClass<? super Bar>
Bar
你知道你实际得到的要么是 a,要么是 .考虑一个返回 的方法。在前一种情况下,它将返回 。在后者中,.如果它返回 一个 ,则将该值赋给变量是错误的。你不知道它是哪个,所以你不能安全地在这里假设任何东西。GenericClass<Bar>
GenericClass<Baz>
T
Bar
Baz
Baz
Bar
考虑一个具有参数的方法。如果它是一个,那么通过它是合法的。如果它是 一个 ,那么传递它 a 仍然是合法的,因为它是 的子类型。T
GenericClass<Bar>
Bar
GenericClass<Baz>
Bar
Bar
Baz
因此,使用下限,您可以使用泛型方法参数,但不能使用泛型返回值。
总而言之:意味着您可以使用通用返回值,但不能使用参数。 表示您可以使用泛型参数,但不能返回值。 有一个泛型参数,因此您需要 .<? extends T>
<? super T>
Predicate.test()
super
需要考虑的另一件事:通配符声明的边界是关于对象的实际类型参数。它们对可以与该对象一起使用的类型的影响正好相反。上限通配符 () 是可以为其分配返回值的变量类型的下限。下限通配符 () 是可以作为参数传入的类型的上限。 不会编译,因为下限为 ,它将只接受 的子类。extends
super
predicate.test(new Object())
String
String