Class <t> </t>的Java泛型

时间:2009-05-31 14:04:27

标签: java generics

所以我有一张地图:

Map<String, Class> format = new HashMap<String, Class>();

我会像这样添加元素:

format.put("Vendor Number", Integer.class);
format.put("Vendor Dispatch", Date.class); 
....

我有一个通用的方法如下:

public static <T> T verifyType(String name, Class<T> type) {
    if (type == Integer.class) {
        return type.cast(new Integer(Integer.parseInt(name)));
    }
             ......
    return null;
}

现在这段代码很好用,没有编译器问题:

Integer i = verifyType("100",Integer.class);

但是,当我尝试这个时:

    Integer i = verifyType("100",format.get("Vendor Number"));

OR 

    Class type = Integer.class
    Integer i = verifyType("100",type);

编译器向我显示此警告: 类型安全:通用方法verifyType(String,Class)的未经检查的调用verifyType(String,Class)

这让我感到困惑......请帮助......

6 个答案:

答案 0 :(得分:8)

变化:

Class type = Integer.class
Integer i = verifyType("100",type);

Class<Integer> type = Integer.class
Integer i = verifyType("100",type);

通过仅将类型声明为“类”,您将丢失泛型参数,而verifyType()方法无法推断类,因此未经检查的警告。

这个问题:

Map<String, Class> format = new HashMap<String, Class>();
format.put("Vendor Number", Integer.class);
format.put("Vendor Dispatch", Date.class);
Integer i = verifyType("100",format.get("Vendor Number"));
由于类型擦除,

无法真正解决。编译器无法根据运行时消失的泛型参数来推断类型。这是因为Java泛型只不过是用于投射的烟雾和镜子。

答案 1 :(得分:4)

您必须对Class的引用进行泛化。例如:

Class<Integer> type = Integer.class
Integer i = verifyType("100",type);

会正常工作。

一如既往:

Map<String, Class<?>> format = new HashMap<String, Class<?>>();

然而,这将永远不会奏效:

Integer i = verifyType("100",format.get("Vendor Number"));

因为格式未定义为:

Map<String, Class<Integer>>

如果是的话,铸造会起作用,但设计毫无意义。

最接近的是:

Integer i = verifyType("100",(Class<Integer>) format.get("Vendor Number"));

但是,你必须得到一个编译器警告,你必须这样做 - 它本身就是一个不安全的演员。编译器正在接受你的说法,即format.get语句将返回一个整数。如果你确定,那就是不安全的演员阵容。如果你想摆脱编译器警告,你可以这样做:

    Class<?> type = format.get("Vendor Number");
    Integer i = null;
    if (type == Integer.class) {
        i = verifyType("100", Integer.class);
    } else {
        //What do you want to do?
    }

答案 2 :(得分:2)

这是因为你的HashMap返回了一个

Class 

对象,但验证函数需要

Class<T> 

对象。

答案 3 :(得分:1)

你得到这个错误的原因是,在第一种情况下,编译器看到你传递了一个Class对象,并且能够在编译时将T绑定到Integer,但在第二种情况下,编译器只看到你正在传递它是一个Class对象。

在一天结束时,你将无法做到

Integer i = verifyType("100",format.get("Vendor Number"));

以类型安全的方式,因为编译器不能知道你会得到一个Integer(如果有人在那次调用之前做了format.put(“Vendor Number”,X.class)会怎么样?)

答案 4 :(得分:1)

对我来说很奇怪,你的编译器在线

Integer i = verifyType("100",format.get("Vendor Number"));

抱怨未经检查的调用但未显示类似“类型不匹配:无法从Object转换为整数”的错误。

这条线对我来说没有意义。如果将Date.class作为第二个参数接收,您希望verifyType返回什么?还有一个Integer(那么verifyType的返回类型是无效的)?还是约会?如果您期望日期,编译器应该如何知道

format.get("Vendor Number");

返回Integer.class,但

format.get("Vendor Dispatch");

返回Date.class

调用

Integer i = verifyType("100",format.get("Vendor Dispatch"));

必须失败,因为Date不是整数。所以,在我看来(以及我的编译器的意见)编译

Integer i = verifyType("100",format.get("Vendor Number"));

必须失败。

答案 5 :(得分:0)

Class本身就是一个泛型类。如果你试试

Class<Integer> type = Integer.class;
Integer i = verifyType("100", type);

它应该更好。输入参数的泛化使编译器相信你知道自己在做什么,足以让你的代码在没有警告的情况下编译。

您还可以通过使用

抑制警告来说服编译器
@SuppressWarning("unchecked")

在特定的代码或方法行之前。