2011-09-29 117 views

回答

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 
+0

列表 objects =(List)integerList;为什么会发出警告?这是我的困惑所在。如果它是列表 objects =(List)integerList;甚至列表 objects =(List)integerList;但Object是这里最高的超类。所以我有点困惑 – yapkm01

+0

它给出了一个警告,因为你正在将一个泛型类型(_has_额外的编译时类型信息)转换为原始类型(它没有)。这是合法的(并且必须是出于遗产原因,不可否认的说),但不建议。你实质上是在告诉编译器:“你知道你在管理类型变更的List吗?别再担心了,我自己会这样做”,编译器会这样说:“嘿,你是否意识到你'这么做?你可能会把这件事搞得很糟糕。“ –

+0

感谢您的回复。从泛型类型到原始类型的警告我没有任何问题。这是从原始回到列表,这给了一个警告,让我困惑。看看我放在不可信的部分的评论 – yapkm01

0

我要说的是,推断出的类型将对象

+0

但是您不能将原始数据分配到列表,因为它已被擦除。 – yapkm01

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. 
    } 
} 

这证实了推断类型为对象类型。

+0

这是如何显示类型推断的对象?对不起,只是看不到它.. – yapkm01

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是什么,我们都应该将它视为错误,并且绝对不要编写这样的代码(即使它编译)。 A List<?> e会起作用。

+0

我希望我也可以检查你的答案。我如何检查超过1个答案作为答案? – yapkm01

0

T是一个通用的。它可以接受任何对象。

相关问题