我有一Storage
堂课:
class Storage<E> {
void add(E e) {
// add element
};
void addAll(Iterable<? extends E> src) {
for (E e : src)
add(e);
}
}
class 有两个类Child
extends
Parent
:
Parent
class Parent implements Comparable<Parent> {
@Override
public int compareTo(Parent o) {
return 0; // some comparison logic
}
}
Child
class Child extends Parent {
}
驱动类:
import java.util.Arrays;
import java.util.List;
public class GenericTest {
public static void main(String[] args) {
/******** CASE 1 *********/
Storage<Parent> ds = new Storage<Parent>();
ds.add(new Parent());
ds.addAll(Arrays.asList(new Parent()));
// Type params are invariant.
// But List<Child> is possible due to bounded wildcard type on addAll
ds.addAll(Arrays.asList(new Child())); // Makes sense
/******** CASE 2 *********/
List<Child> t = Arrays.asList();
max(t);
}
static <T extends Comparable<T>> T max(List<T> list) {
return null; // Return null so code can compile
}
}
因为Storage
是泛型类,对其方法的操作是有意义的;我知道案例 1 是如何工作的。
在第 2 种情况下,使用上面的max
in签名GenericTest
,我收到编译错误:
The method max(List<T>) in the type GenericTest is not applicable for the arguments (List<Child>)
我知道这Comparable<Child>
不是Comparable<Parent>
(Typed params are invariant)的子类型。
所以,我将签名更新为
// update Comparable<T> to Comparable<? super T>
static <T extends Comparable<? super T>> T max(List<T> list)
现在,代码编译并推断签名是
<Child> Child GenericTest.max(List<Child> list)
这是有道理的。
当我将签名更新为
// update List<T> to List<? extends T>
static <T extends Comparable<T>> T max(List<? extends T> list)
代码编译和推断的签名是
<Parent> Parent GenericTest.max(List<? extends Parent> list)
我无法理解如何更新List<T>
以List<? extends T>
使编译器推断类型Parent
。
我的意思是,对于泛型方法(使用 type 直接调用Child
),? extends T
帮助编译器如何引用 的父类Child
?请注意,此签名具有Comparable<T>
(而不是Comparable<? super T
)。
不是extends
关于T
本身及其子类的类型吗?
编辑:
Java 8 带有更新的类型推断规则。以下内容足以用于 Java 8 及更高版本中的类型推断,但不适用于 Java 7 及更低版本:
static <T extends Comparable<T>> T max(List<? extends T> list)
它给出了编译错误:
Bound mismatch: The generic method max(List<? extends T>) of type GenericTest is not applicable for the arguments (List<Child>). The inferred type Child is not a valid substitute for the bounded parameter <T extends Comparable<T>>
签名
static <T extends Comparable<? super T>> void max(List<T> list)
不过对于 Java 7 来说已经足够了。
为了使事情更清楚,类Child
:
extends Parent
implements Comparable<Parent>
static <T extends Comparable<T>> T max(List<T> list)
T
是 Child
Child
不是Comparable<Child>
static <T extends Comparable<? super T>> T max(List<T> list)
T
是 Child
?
是 Parent
Child implements Comparable<Parent super Child>
static <T extends Comparable<T>> T max(List<? extends T> list)
T
是 Parent
?
是 Child
Child extends Parent implements Comparable<Parent>
在案例 3) 中,找到一个有效的T
类可以看作是:“找到Child
实现 a Comparable
of 自身的第一个超类”。
与情况 1) 一样,它不可能是Child
因为它不是Comparable<Child>
. 其自身Child
实现的第一个(也是唯一一个)超类Comparable
是Parent
.
我无法理解如何更新
List<T>
以List<? extends T>
使编译器推断类型Parent
。
List<T>
被迫T
成为Child
List<? extends T>
强迫?
成为Child
,不是T
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句