想象一下,我们有以下泛型类:
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中泛型的重要性,但......
该答案的第一部分将解决您问题的类型推断部分
\n\n在您的示例中自动推断类型的唯一地方是调用genericMethod.
的定义genericMethod声明了两个泛型类型参数:an unbound BT和T which should be a subclass of BT。
类型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
在您的示例中,您提供了一个 String 类型的对象作为 类型的参数T。\n根据上面的规则,T将被推断为等于String。
现在问题T已解决,推理将继续进行BT。该类型是通过以下第 18.3.1 节推断的,该节表示类型的表达式:
T extends BT, T == String
暗示
\n\nString extends BT
这种关系允许编译器绑定BT到String,因此您最终会得到以下隐式调用:
genericMethod<String,String>("text")\nRun Code Online (Sandbox Code Playgroud)\n\n希望这能让事情澄清一点。
\n\n回答你问题的第二部分:
\n\n\n\n\n尽管 T 扩展了 BT,但它们是不同的类型,并且 GenericClass\n 可能具有内部逻辑,其中确切的类型名称起着重要\n 的作用(例如,在某些映射等中用作字符串键)。
\n
在不添加更多约束的情况下,编译器将视为T等效BT并允许您仅调用定义为类型一部分的方法BT。
除非您使用反射做一些非常奇怪的事情,否则代码不应依赖于类型参数的运行时值。\nGenericClass当前的情况并不是很有用,因为U没有任何约束,因此编译器将允许您只能做对所有对象都有效的事情。\n您可以U在该上下文中考虑与Object。
| 归档时间: |
|
| 查看次数: |
563 次 |
| 最近记录: |