首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >返回类型中推断的通配符泛型

返回类型中推断的通配符泛型
EN

Stack Overflow用户
提问于 2009-08-18 14:24:48
回答 1查看 2.8K关注 0票数 15

Java通常可以根据参数(甚至是返回类型,而不是C#)来推断泛型。

一个恰当的例子:我有一个泛型类Pair<T1, T2>,它只存储一对值,可以按以下方式使用:

代码语言:javascript
复制
Pair<String, String> pair = Pair.of("Hello", "World");

方法of看起来就像这样:

代码语言:javascript
复制
public static <T1, T2> Pair<T1, T2> of(T1 first, T2 second) {
    return new Pair<T1, T2>(first, second);
}

非常好。但是,这不再适用于以下需要通配符的用例:

代码语言:javascript
复制
Pair<Class<?>, String> pair = Pair.of((Class<?>) List.class, "hello");

(请注意使List.class成为正确类型的显式转换。)

代码失败,并显示以下错误(由Eclipse提供):

类型不匹配:无法从TestClass.Pair<Class<capture#1-of ?>,String>转换为TestClass.Pair<Class<?>,String>

但是,显式调用构造函数仍然可以按预期工作:

代码语言:javascript
复制
Pair<Class<?>, String> pair =
    new Pair<Class<?>, String>((Class<?>) List.class, "hello");

有人能解释这种行为吗?这是设计出来的吗?这是通缉令吗?是我做错了什么,还是我偶然发现了编译器设计/ bug中的一个缺陷?

胡乱猜测:“捕获#1-of?”不知何故,似乎暗示着通配符是由编译器动态填充的,使类型成为Class<List>,从而导致转换(从Pair<Class<?>, String>Pair<Class<List>, String>)失败。是这样的吗?有没有办法解决这个问题?

为了完整起见,下面是Pair类的简化版本:

代码语言:javascript
复制
public final class Pair<T1, T2> {
    public final T1 first;
    public final T2 second;

    public Pair(T1 first, T2 second) {
        this.first = first;
        this.second = second;
    }

    public static <T1, T2> Pair<T1, T2> of(T1 first, T2 second) {
        return new Pair<T1, T2>(first, second);
    }
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2009-08-18 15:08:21

构造函数工作的原因是您显式地指定了类型参数。如果这样做,静态方法也会起作用:

代码语言:javascript
复制
Pair<Class<?>, String> pair = Pair.<Class<?>, String>of(List.class, "hello");

当然,首先使用静态方法的全部原因可能只是为了获得类型推断(这根本不适用于构造函数)。

这里的问题(正如您所建议的)是编译器正在执行capture conversion。我相信这是 [§15.12.2.6 of the JLS]的结果

_

  • 所选方法的结果类型如下确定:_
    • 如果被调用的方法是用返回类型
    • 声明的,则结果是空的。如果该方法需要未经检查的转换才能适用,则结果类型是该方法声明的返回type.
    • Otherwise,的擦除(§4.6)。如果被调用的方法是泛型的,则对于1in,设Fi是该方法的形式类型参数,设Ai是为该方法调用推断的实际类型参数,设R是被调用的方法的声明返回类型。结果类型是通过对方法declaration.

中给定的类型应用捕获转换(§5.1.10)到RF1 := A1,...,Fn :=获得的。结果类型是通过对方法declaration.中给定的类型应用捕获转换(§5.1.10)获得的

如果您真的想要推断,一种可能的解决方法是这样做:

代码语言:javascript
复制
Pair<? extends Class<?>, String> pair = Pair.of(List.class, "hello");

变量pair将具有更宽的类型,这确实意味着需要在变量的类型名中键入更多内容,但至少您不再需要在方法调用中进行强制转换。

票数 12
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1294227

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档