gpt4 book ai didi

Java Generics Wildcard 与 Typed Generics 用法

转载 作者:搜寻专家 更新时间:2023-10-31 20:34:08 24 4
gpt4 key购买 nike

我正在阅读 Java 教程中的以下部分:http://docs.oracle.com/javase/tutorial/java/generics/capture.html

它首先说明以下代码由于无法将捕获转换为对象而产生错误,因此 set 方法无法确认对象的类型为捕获#1:

import java.util.List;

public class WildcardError {

void foo(List<?> i) {
i.set(0, i.get(0));
}
}

有点理解这背后的原因。 i.get 返回一个对象,并且编译器无法确定该对象是否属于 capture#1 类型,因此它无法以类型安全的方式将其与第二个参数匹配。

然后建议使用以下代码使此方法起作用:

public class WildcardFixed {

void foo(List<?> i) {
fooHelper(i);
}


// Helper method created so that the wildcard can be captured
// through type inference.
private <T> void fooHelper(List<T> l) {
l.set(0, l.get(0));
}

}

有点明白为什么这段代码也能正常工作,在这段代码中,l.get 保证是 T 类型,所以它可以作为参数传递类型 T。

我不明白的是为什么你不能只使用这样的方法,没有帮助:

class GenericsTest {
static <K> void bar(List<K> l) {
l.set(0, l.get(l.size() - 1));
}

public static void main(String[] args) {
List<Integer> lst = Arrays.asList(1, 2, 3, 4);
bar(lst);
System.out.println(lst); // [4, 3, 2, 4]
}
}

即如果您要使用类型推断,为什么不直接使用显式类型泛型而不是通配符和辅助函数呢?在这种情况下使用通配符有什么好处吗?在哪些情况下您实际上更愿意使用通配符而不是类型泛型?

最佳答案

首先注意void foo(List<?> i)void <K> foo(List<K> i)两者都接受完全相同的参数集——假设您没有明确指定 K在泛型方法的情况下,任何可以传递给一个函数签名的参数都可以传递给另一个函数签名,反之亦然。所以对于“外部代码”,两种签名都同样有用。

鉴于它们是等价的,类型参数较少的那个更简单,应该始终是首选。当向外部代码提供公共(public) API 时,您应该始终以最简单的形式提供它,只使用确保其安全所需的最少类型内容。类型List<?>足以表达它可以接受任何类型的 List , 所以这就是我们应该使用的。

我们碰巧使用了类型参数K在内部解决一些泛型问题,但这只是一个不幸的内部实现细节,外部代码不需要关心。因此,我们应该在制作公共(public) API 时隐藏这种丑陋之处,并将其包装在更好的函数签名中。

除了抽象目的之外,您可能需要特定签名的另一个原因是它是否覆盖具有该签名的父类(super class)方法。覆盖时不能添加类型参数。

关于Java Generics Wildcard 与 Typed Generics 用法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25796921/

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