Java 泛型好奇心

发布于 2024-08-06 19:24:40 字数 669 浏览 7 评论 0原文

我有一个接口 A,由类 B 实现。

以下通用方法有效,

public static <T, U extends T> List<T> listFactory(Collection<U> source) {
    return new ArrayList<T>(source);
}

public static <T> List<T> listFactory(Collection<? extends T> source) {
    return new ArrayList<T>(source);
}

不起作用(编译错误,类型不匹配),

List<A> tester = listFactory(B.defaultCollectionFactory(3));

当我将输出定向到defaultCollectionFactory(int count) 静态提供 B 的集合时, 使用默认的标签方案。

关于为什么会这样的任何见解吗?看起来通用 U 和通配符正在做同样的事情。

I have an interface A, which class B implements.

The following generic method works

public static <T, U extends T> List<T> listFactory(Collection<U> source) {
    return new ArrayList<T>(source);
}

but

public static <T> List<T> listFactory(Collection<? extends T> source) {
    return new ArrayList<T>(source);
}

does not (compilation error, type mismatch), when I am directing the output into

List<A> tester = listFactory(B.defaultCollectionFactory(3));

defaultCollectionFactory(int count) statically provides a collection of Bs, with a default labeling scheme.

Any insights as to why that is? It seems like the generic U and wildcard are doing the same thing.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

流殇 2024-08-13 19:24:40

编译器为 listFactory 方法推断出与您预期不同的类型参数。它推断 T 是类型 B,因此签名实际上是 List listFactory(Collectionsource)。通过在方法调用中显式指定类型参数 A

List<A> tester = Test.<A> listFactory(B.defaultCollectionFactory(3));

The compiler is inferring a different type parameter for the listFactory method than you expect. It infers that T is type B, so the signature is effectively List<B> listFactory(Collection<? extends B> source). Specify the type parameter A by being explicit in the method invocation:

List<A> tester = Test.<A> listFactory(B.defaultCollectionFactory(3));
作业与我同在 2024-08-13 19:24:40

在第一个构造中,您指定要返回传入项目的接口的 List。您在 中指定传入的 Object 和返回的 Object 类型之间的关系。 >U 延伸 T 方向。在这种情况下,编译器可以将 AB 分别与 TU 关联起来。

在第二种情况下,没有这样的区别,因此编译器假设 T 引用 B 并将返回值键入为 List >。然后您就会陷入陷阱,尽管 BA 的实例,但 List 不是 List< 的实例;A>。编译器会抱怨:

类型不匹配:无法从列表转换;到列表


您会发现,使用第一个构造,您可以自由指定 B 实现的任何接口或 B 中的任何超类的 List > 层次结构(例如 List),编译器不会抱怨。

In the first construct, you are specifying that you are returning a List of the interface of the item that was passed in. You specify the relationship between the passed in Object and the return Object type in the U extends T direction. In this case, the compiler can associate A and B with T andU respectively.

In the second, there is no such differentiation, so the compiler assumes that T refers to B and will type the return value as List<B>. You then fall into the trap where, although B is an instance of A, List<B> is not an instance of List<A>. The compiler will complain:

Type mismatch: cannot convert from List<B> to List<A>

You will find that, with the first construct, you have the liberty of specifying a List of any interface the B implements or any superclass in the B hierarchy (List<Object>, for example), and the compiler will not complain.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文