类泛型的类型不匹配 [英] Type mismatch for Class Generics

查看:259
本文介绍了类泛型的类型不匹配的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有下面的代码不能编译,虽然有一种方法可以编译,但我想知道它为什么不编译。有人能够启发我,特别是为什么我会在最后发布错误消息吗?

  public class Test {
public static void main(String args []){
Test t = new Test();
t.testT(null);
}

public< T扩展测试> void testT(Class< T> type){
Class< T> testType = type == null? Test.class:type; //错误在这里
System.out.println(testType);


code $

$ b $类型不匹配:不能转换从Class



通过将 Test.class 转换为 Class< T> 这个编译时带有一个未经检查的转换警告,并且完美运行。 原因是Test.class是Class< Test>类型的。您无法指定类型为Class< Test>的类型的引用到类型< T>的变量,因为它们不是一回事。然而,这是有效的:

  Class <?扩展测试> testType = type == null? Test.class:type; 

通配符允许Class< T>和Class< Test>引用将被分配给testType。



有关Java泛型行为的大量信息在 Angelika Langer Java泛型常见问题解答。我将根据那些使用 Number class heirarchy Java的核心API的一些信息提供示例。



请考虑以下方法:

  public< T extends Number> void testNumber(final Class< T> type)

这是为了让下列语句成功编译:

  testNumber(Integer.class); 
testNumber(Number.class);

但以下内容无法编译:

  testNumber(String.class); 

现在考虑以下语句:

 类<号> numberClass = Number.class; 
Class< Integer> integerClass = numberClass;

第二行无法编译并产生此错误类型不匹配:无法转换来自Class< Number>到Class< Integer> 。但是 Integer 扩展 Number ,那为什么会失败呢?看看下面两条语句,看看为什么:

  Number anumber = new Long(0); 
整数another = anumber;

很容易明白为什么第二行不能在这里编译。您无法将 Number 的实例分配给 Integer 类型的变量,因为无法保证 Number 实例是兼容类型。在这个例子中, Number 实际上是一个 Long ,它当然不能被分配给整数。实际上,错误也是类型不匹配:类型不匹配:无法从数字转换为整数



规则是一个实例不能被分配给一个变量,该变量是实例类型的子类,因为不能保证它是兼容的。



泛型行为在类似的方式。在通用方法签名中, T 只是一个占位符,用于指示该方法允许编译器使用的方法。当编译器遇到 testNumber(Integer.class)时,它实质上用 Integer替换 T code>。



通配符增加了额外的灵活性,如下所示:

 类< ;?扩展Number> wildcard = numberClass; 

由于 Class <? extends Number> 表示任何类型,它是 Number 或者是 Number 的子类,这是完全合法并且在许多情况下可能有用。


I have the following code that won't compile and although there is a way to make it compile I want to understand why it isn't compiling. Can someone enlighten me as to specifically why I get the error message I will post at the end please?

public class Test {
    public static void main(String args[]) {
        Test t = new Test();
        t.testT(null);
    }

    public <T extends Test> void testT(Class<T> type) {
        Class<T> testType = type == null ? Test.class : type; //Error here
        System.out.println(testType);
    }
}

Type mismatch: cannot convert from Class<capture#1-of ? extends Test> to Class<T>

By casting Test.class to Class<T> this compiles with an Unchecked cast warning and runs perfectly.

解决方案

The reason is that Test.class is of the type Class<Test>. You cannot assign a reference of type Class<Test> to a variable of type Class<T> as they are not the same thing. This, however, works:

Class<? extends Test> testType = type == null ? Test.class : type;

The wildcard allows both Class<T> and Class<Test> references to be assigned to testType.

There is a ton of information about Java generics behavior at Angelika Langer Java Generics FAQ. I'll provide an example based on some of the information there that uses the Number class heirarchy Java's core API.

Consider the following method:

public <T extends Number> void testNumber(final Class<T> type)

This is to allow for the following statements to be successfully compile:

testNumber(Integer.class);
testNumber(Number.class);

But the following won't compile:

testNumber(String.class);

Now consider these statements:

Class<Number> numberClass = Number.class;
Class<Integer> integerClass = numberClass;

The second line fails to compile and produces this error Type mismatch: cannot convert from Class<Number> to Class<Integer>. But Integer extends Number, so why does it fail? Look at these next two statements to see why:

Number anumber = new Long(0);
Integer another = anumber;

It is pretty easy to see why the 2nd line doesn't compile here. You can't assign an instance of Number to a variable of type Integer because there is no way to guarantee that the Number instance is of a compatible type. In this example the Number is actually a Long, which certainly can't be assigned to an Integer. In fact, the error is also a type mismatch: Type mismatch: cannot convert from Number to Integer.

The rule is that an instance cannot be assigned to a variable that is a subclass of the type of the instance as there is no guarantee that is is compatible.

Generics behave in a similar manner. In the generic method signature, T is just a placeholder to indicate what the method allows to the compiler. When the compiler encounters testNumber(Integer.class) it essentially replaces T with Integer.

Wildcards add additional flexibility, as the following will compile:

Class<? extends Number> wildcard = numberClass;

Since Class<? extends Number> indicates any type that is a Number or a subclass of Number this is perfectly legal and potentially useful in many circumstances.

这篇关于类泛型的类型不匹配的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆