调用泛型方法时未指定的类型参数

Ale*_*hin 6 java generics

想象一下,我们有以下泛型类:

public class GenericClass<U> {
    private U value;

    public GenericClass(U value) {
        this.value = value;
    }
}
Run Code Online (Sandbox Code Playgroud)

和其他一些类MyClass中的以下泛型方法:

public <T extends BT, BT> void genericMethod(T arg) {
    Object genericClass = new GenericClass<BT>(arg);
}
Run Code Online (Sandbox Code Playgroud)

如果我们打电话,BT类型参数将获得哪个值

genericMethod("text");
Run Code Online (Sandbox Code Playgroud)

一些说明:

上面的代码编译没有错误或警告,这对我来说似乎很奇怪.反编译(通过IntelliJ IDEA 2016)显示以下代码:

public <T extends BT, BT> void genericMethod(T arg) {
    new MyClass.GenericClass(arg);
}
Run Code Online (Sandbox Code Playgroud)

请注意new GenericClass<BT>(arg)并不相同,new GenericClass(arg)因为后者等同于new GenericClass<T>(arg)(类型推导),虽然T extends BT这些是不同的类型,并且GenericClass可能具有内部逻辑,其中确切的类型名称起着重要作用(例如,用作字符串键)一些地图等).所以对我来说奇怪的是,为什么编译器静默使用类型推导而不是产生一些警告(或者甚至是错误),指出没有指定BT类型参数.也许我错过了什么.关于Java中泛型的重要性,但......

Den*_*sca 3

该答案的第一部分将解决您问题的类型推断部分

\n\n

在您的示例中自动推断类型的唯一地方是调用genericMethod.

\n\n

的定义genericMethod声明了两个泛型类型参数:an unbound BTT which should be a subclass of BT

\n\n

类型T将根据Java 语言规范第 18.2.4 节中指定的规则推断中指定的规则推断:

\n\n
\n

\xe2\x80\xb9S = T\xe2\x80\xba 形式的约束公式(其中 S 和 T 是类型)简化如下:

\n\n

...

\n\n

否则,如果 T 是推理变量 \xce\xb1,并且 S 不是基本类型,则约束简化为边界 S = \xce\xb1。

\n
\n\n

在您的示例中,您提供了一个 String 类型的对象作为 类型的参数T。\n根据上面的规则,T将被推断为等于String

\n\n

现在问题T已解决,推理将继续进行BT。该类型是通过以下第 18.3.1 节推断的,该节表示类型的表达式:

\n\n

T extends BT, T == String

\n\n

暗示

\n\n

String extends BT

\n\n

这种关系允许编译器绑定BTString,因此您最终会得到以下隐式调用:

\n\n
genericMethod<String,String>("text")\n
Run Code Online (Sandbox Code Playgroud)\n\n

希望这能让事情澄清一点。

\n\n

回答你问题的第二部分:

\n\n
\n

尽管 T 扩展了 BT,但它们是不同的类型,并且 GenericClass\n 可能具有内部逻辑,其中确切的类型名称起着重要\n 的作用(例如,在某些映射等中用作字符串键)

\n
\n\n

在不添加更多约束的情况下,编译器将视为T等效BT并允许您仅调用定义为类型一部分的方法BT

\n\n

除非您使用反射做一些非常奇怪的事情,否则代码不应依赖于类型参数的运行时值。\nGenericClass当前的情况并不是很有用,因为U没有任何约束,因此编译器将允许您只能做对所有对象都有效的事情。\n您可以U在该上下文中考虑与Object

\n