gpt4 book ai didi

Java 通配符与类型参数

转载 作者:搜寻专家 更新时间:2023-10-30 21:34:58 25 4
gpt4 key购买 nike

为什么 1 有效而 2 无效?

1:

public List<? extends Integer> l1;
public List<? extends Number> l2 = l1;

2:

public List<U> l1;
public List<S> l2 = l1;
//where U and S have been previously defined as: **S extends Number,U extends Integer**

最佳答案

Generics are not covariant .例如:

List<Integer> l1;
List<Number> l2;
l1 = l2; // incompatible types
l2 = l1; // also incompatible

但是,通配符类型提供了一种表达协变的方法:

List<? extends Integer> l1;
List<? extends Number> l2 = l1; //legal

l1 被表示为 某种未知类型List,它是或扩展 Integer。类似地,l2 是某种类型的 List,它是或扩展了 Number。由于 Integer 扩展了 Number,编译器知道将 l1 分配给 l2 一定没问题。

这种情况不同:

<S extends Number, U extends Integer> void someMethod() {

List<U> l1;
List<S> l2 = l1; //incompatible types
}

SU 是类型参数,这意味着它们由 someMethod(或类型推断)的调用者提供一些特定类型参数。这些类型参数可以是具体类型,如 Integer 或通配符捕获。

虽然它们也是有界的,但这与使用上面的有界通配符不同。类型参数在声明时有界——在方法体内它们被理解为不会改变。例如,假设 SU 通过调用解析为 Integer:

this.<Integer, Integer>someMethod();

在这种情况下,我们可以想象方法体看起来像这样:

List<Integer> l1;
List<Integer> l2 = l1; // okay why not?

这是合法的,但我们只是碰巧走运。有很多情况是不会的。例如:

this.<Double, Integer>someMethod();

现在我们重新构想方法体:

List<Integer> l1;
List<Double> l2 = l1; // danger!

因此您可以看到有界类型参数与有界通配符有很大不同,后者允许不同的泛型类型协变地“交换”:

List<Integer> l1;
List<Double> l2;
List<? extends Number> l3;
l3 = l1;
l3 = l2;

关于Java 通配符与类型参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15784344/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com