java如果构造函数参数不是泛型的,自动类型推断是如何工作的
案例1:
class Gen3<T extends Number> {
T val;
<T extends String> Gen3(String ob){
}
}
这里编译器并没有给出任何错误,但它应该给出正确的答案吗?因为这里有两个相互矛盾的界限,请帮助我理解
案例2:
class Gen3<T extends Number> {
T val;
<T extends String> Gen3(String ob) {
}
}
假设我写下面的代码来测试上面的类
Gen<Integer> a = new Gen<>("r");
现在,自动类型推断在这里是如何工作的
请帮助理解这一点
# 1 楼答案
因为这里有两个相互矛盾的T的界限,没有。仅仅是
T
的两个独立的定义彼此没有任何关系。构造函数上的T
隐藏类的T
,与局部变量和同名字段相同。一个“适当的”IDE会告诉您,内部T
隐藏了外部T
并且没有使用# 2 楼答案
不存在两个相互矛盾的界
T
。有两个类型变量恰好具有相同的名称。在构造函数中,类型参数T
隐藏类级别的类型参数请注意,问题不在于不同的类型边界。如果您确实尝试使用类型参数执行某些操作,例如:
即使两个
T
具有相同的类型绑定,这也不会通过编译,因为ob
的类型参数不同于val
的类型参数# 3 楼答案
泛型的这个“用例”在多个方面都没有意义。通过
<T extends String>
子句,您引入了一个不使用的类型变量,并且在给定的调用情况下,编译器没有机会用具体的类型替换它您的定义相当于以下内容(我刚刚重命名了两个不同类型的变量,使其具有不同的名称,使讨论更容易):
<U extends String>
子句告诉编译器:“下面的构造函数将使用类型参数U
,我只允许U
为String
或String
的子类。”。正如其他人已经说过的,字符串是最终的,所以U
只能是String
,所以它实际上不是一个变量类型,并且声明一个不能变化的变量类型是没有意义的。我将继续使用修改后的版本:如果您执行
Gen<Integer> a=new Gen<Integer>("r");
,编译器应该如何找到要替换U
的具体类?<Integer>
部分应用于T
变量,因此它对U
没有帮助。由于您没有在任何参数中引用U
,因此没有编译器提示泛型的思想是,类有一些元素,您希望在这些元素中允许不同的类型,并允许编译器标记误用,例如,将
Integer
添加到List<String>
:这里,编译器可以将泛型
List<E>
类型参数E
匹配为String
(来自List<String>
声明)。在此上下文中,gegericList.add(E e)
方法声明变成了add(String e)
,并且与new Integer(12345)
的用法不匹配,后者不是String
,允许编译器标记错误摘要:
只有在编译器有机会从调用参数推断类型参数时,才引入类型参数