简体   繁体   English

为什么Java泛型不允许对泛型类型进行类型转换?

[英]Why does Java generics not allow type conversion on generic types?

public class Main {

    public static <T> void foo(T[] bar) {
        double d = (double) bar[0]; // Error : incompatible types
    }

    public static void main(String[] args) {
        int[] int_buf = new int[8];
        foo(int_buf);
    }
}

The issue is indicated in the code. 问题在代码中指出。

Why does Java generics not allow type conversion on generic types? 为什么Java泛型不允许对泛型类型进行类型转换?

The problem is deeper than this. 问题比这更深刻。 Even without the line you highlighted, this program is broken: 即使没有突出显示的行,此程序也会被破坏:

public class Main {
    public static <T> void foo(T[] bar) {
        // do nothing
    }

    public static void main(String[] args) {
        int[] int_buf = new int[8];
        foo(int_buf);   <-- problem is here
   }
}

Java generics only support reference types as type parameters; Java泛型仅支持引用类型作为类型参数; the generic method foo() could be rewritten as follows: 泛型方法foo()可以重写如下:

<T extends Object> void foo(T[] bar) { ... }

And here's your problem: there's no T that extends Object such that an int[] is a T[] . 这是你的问题:没有T扩展Object ,因此int[]T[]

Secondarily, the reason the conversion also fails is that we know nothing about T , so we don't know that there exists a conversion from T to double . 其次,转换失败的原因是我们对T一无所知,所以我们不知道存在从Tdouble的转换。

This is because you are not specifiying what the generic type T is. 这是因为您没有指定通用类型T是什么。 So by default it will think T is an object type, not a number. 因此,默认情况下,它会认为T是对象类型,而不是数字。 It's not possible to cast an object to a double, this makes no sense. 将对象强制转换为double是不可能的,这没有任何意义。

If you change to <T extends Number> this should work just fine. 如果您更改为<T extends Number>这应该可以正常工作。 Although, you might need to have an Integer array rather than a int array 虽然,您可能需要一个Integer数组而不是一个int数组

The Java compiler erases all type parameters in generic code. Java编译器擦除通用代码中的所有类型参数。 A direct consequence of this is that you cannot verify which parameterized type for a generic is currently is use. 这样做的直接后果是您无法验证当前使用的通用参数化类型。 If you test, instanceof will not work either. 如果你测试, instanceof也不会工作。 Since, runtime does not keep track of a type parameters in java, there is no difference between HashSet<Integer> and HashSet<Double> . 由于运行时没有跟踪java中的类型参数,因此HashSet<Integer>HashSet<Double>之间没有区别。 You can do a ..instanceof HashSet<?> at the most to check if it is an instance of a HashSet. 您最多可以执行一个..instanceof HashSet<?>来检查它是否是HashSet的实例。

If something is not clear in what I have written, please refer to the docs . 如果我所写的内容不明确,请参阅文档

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM