如果我使用raw类型作为参数调用泛型方法,将使用什么类型参数?

时间:2011-09-29 03:52:13

标签: java generics

我只是好奇在将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.

}

5 个答案:

答案 0 :(得分:2)

这是为了向后兼容。在泛型之前,

static void test5(List t){}

List e = ...;
test5(e);  

引入泛型时,他们需要对Listtest5()等方法进行格式化,而不要求重写和重新编译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是通用的。它可以接受任何对象。