带有 Class <T> 的 Java 泛型

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/932090/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 21:15:20  来源:igfitidea点击:

Java Generics with Class <T>

javagenerics

提问by Jay

So I have a map:

所以我有一张地图:

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

And I would add elements to it like this:

我会像这样添加元素:

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

I have a generic method as follows:

我有一个通用方法如下:

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

Now this piece of code works great with no compiler issues:

现在这段代码运行良好,没有编译器问题:

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

But, when I try this:

但是,当我尝试这样做时:

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

OR 

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

Compiler shows me this warning: Type safety: Unchecked invocation verifyType(String,Class) of the generic method verifyType(String, Class)

编译器向我显示此警告:类型安全:未检查的调用 verifyType(String,Class) of the generic method verifyType(String, Class)

That leaves me puzzled... please help...

这让我很困惑...请帮助...

采纳答案by cletus

Change:

改变:

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

to

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

By only declaring the type as 'Class', you're losing the generic parameter and the verifyType() method can't infer the class, thus the unchecked warning.

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

This problem:

这个问题:

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"));

can't really be solved due to type erasure. The compiler can't infer the type based on a generic parameter that is gone by runtime. This is because Java generics are little more than smoke and mirrors for casting.

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

回答by Nathaniel Flath

It is because your HashMap returns a

这是因为您的 HashMap 返回一个

Class 

object, but the verify function expects a

对象,但验证函数需要一个

Class<T> 

object.

目的。

回答by Yuval

Class Classis a generic class itself. If you try

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

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

it should work better. Generification of the input parameter convinces the compiler that you know what you're doing, enough to let your code compile without warning.

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

You can also convince the compiler by suppressing the warning using

您还可以通过使用以下命令抑制警告来说服编译器

@SuppressWarning("unchecked")

before the specific line of code or method.

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

回答by waxwing

The reason you get this error is that in the first case the compiler sees that you pass it a Class object and is able to bind T to Integer at compile time, but in the second case the compiler only sees that you are passing it a Class object.

您收到此错误的原因是,在第一种情况下,编译器看到您将 Class 对象传递给它,并且能够在编译时将 T 绑定到 Integer,但在第二种情况下,编译器只会看到您传递给它一个 Class目的。

At the end of the day, you will not be able to do

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

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

in a type-safe way, since the compiler can't know that you will get an Integer (what if someone does a format.put("Vendor Number", X.class) just before that call?)

以类型安全的方式,因为编译器无法知道您将获得一个 Integer(如果有人在该调用之前执行 format.put("Vendor Number", X.class) 怎么办?)

回答by Yishai

You have to genericize your references to Class. For example:

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

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

would work fine.

会工作得很好。

As would:

就像:

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

However, this will never work:

但是,这永远行不通:

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

Because format is not defined as:

因为格式没有定义为:

Map<String, Class<Integer>>

If it was, the casting would work, but the design would be pointless.

如果是这样,铸造会起作用,但设计将毫无意义。

The closest you can get is:

你能得到的最接近的是:

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

However, you will get a compiler warning doing it, as you must - it is an inherently unsafe cast. The compiler is taking your word for it that that format.get statement will return an integer. If you are sure of that, then that is what unsafe casts are for. If you want to get rid of the compiler warning, you could do this:

但是,这样做时您会收到编译器警告,这是必须的 - 它本质上是不安全的。编译器相信你的话,那个 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?
    }

回答by Tadeusz Kopec

It is strange for me, that your compiler on line

我很奇怪,你的编译器上线了

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

complains about unchecked invocation but doesn't show an error like "Type mismatch: cannot convert from Object to Integer".

抱怨未经检查的调用,但没有显示诸如“类型不匹配:无法从对象转换为整数”之类的错误。

This line just doesn't make sense to me. What do you expect verifyType to return if it receives Date.class as a second parameter? Also an Integer (then the return type of verifyType is invalid)? Or a Date? If you expect a Date, how is compiler expected to know that

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

format.get("Vendor Number");

returns Integer.class, but

返回 Integer.class,但是

format.get("Vendor Dispatch");

returns Date.class

返回日期.class

Invocation of

调用

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

must fail, as Date is not an Integer. So, in my opinion (and in opinion of my compiler) compilation of

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

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

must fail.

必须失败。