我只是好奇在将raw传递给T类型时生成的推断T类型是什么。它确实编译但有警告。
public class GenericMethodInference {
static <T> void test5(List<T t>){} // clause (5)
public static void main(String [] args) {
List e = new ArrayList<Integer>();
test5(e); // clause (6) // ok but with warning.
}
答案 0 :(得分:2)
这是为了向后兼容。在泛型之前,
static void test5(List t){}
List e = ...;
test5(e);
引入泛型时,他们需要对List
和test5()
等方法进行格式化,而不要求重写和重新编译test5(e)
之类的所有用法。因此test5(e)
必须仍然有效。
这是通过放宽类型推断规则和方法签名匹配规则来实现的。
推论:List << List<T>
这不能保持在亚型意义上;然而,推理规则只是忽略它; T
没有约束,只是选择Object
方法签名:List e
不是方法参数类型List<Object>
的子类型,但它可以被“方法调用转换”接受,它允许从List
到“{未修复的转换” List<Whatever>
; “未经检查的转换”会触发强制编译器警告。
这只是历史的兴趣;今天没有程序员应该关心。很明显,List
无法成为List<T>
的子类型,无论T
是什么,我们实际上应该将其视为错误,并且永远不要编写类似的代码(即使它编译)。 List<?> e
可以使用。
答案 1 :(得分:2)
将原始类型分配给泛型类型将假定没有泛型约束(默认为Object),但删除可能存在的任何编译时类型安全保证。
但是你不能将原始版本分配给
List <Object>
擦除
这听起来似乎存在对类型擦除的基本误解。原始类型是泛型类型的最终结果。您指定了List<Integer>
,编译器会根据该类型信息进行验证,然后删除其中的<Integer>
部分,根据对原始类型List的操作,根据需要将强制转换插入Integer。
这意味着这两个检索操作完全相同。
List<Integer> integerList = new ArrayList<Integer>();
integerList.add(5);
Integer i = integerList.get(0);
Integer ii = (Integer)((List)integerList).get(0);
例如,以下是合法的。这只会发出警告(而不是导致编译器错误或运行时错误),因为我们正在对Object执行操作,并且仍在所包含类型的适当范围内。
List<Object> objects = (List)integerList;
Object value = objects.get(0);
System.out.println(value);
它将打印出5.类型系统有帮助的地方是你尝试做这样的事情。
List<String> badStringList = integerList;
它会给你一个编译错误,说明存在类型不匹配。但是,直接使用原始类型会将所有类型的安全性抛弃,并完全依赖于您对应使用的正确类型的判断。如果你弄错了,这可以让你轻松地在脚下射击。
List<String> badStringList = (List)integerList;
String badValue = badStringList.get(0); //ClassCastException is thrown at runtime
答案 2 :(得分:0)
我会说推断的类型是Object
答案 3 :(得分:0)
public class GenericMethodInference {
static <T> void test5(List<T> xx) {
System.out.println(xx.getClass()); //class java.util.ArrayList
System.out.println(xx.get(0).getClass()); //class java.lang.Integer
System.out.println(xx.get(1).getClass()); //class java.lang.String
} // clause (5)
public static void main(String[] args) {
List e = new ArrayList<Long>();
e.add(1);
e.add("2");
test5(e); // clause (6) // ok but with warning.
}
}
这确认推断的类型是对象类型。
答案 4 :(得分:0)
T是通用的。它可以接受任何对象。