Java 允许在泛型中使用基元类型

2022-09-01 20:28:16

我知道java不应该支持基元类型的泛型参数,果然是这样的:

Vector<byte> test;

将无法编译。

但是,通过我在程序中意外执行的一点点手,我发现实际上可以创建具有基元类型的通用对象(如下所示的技术)

此外,java错误地允许将此实例分配给类型的变量,而正如print语句所示,byte.class和byte.class是两个独立的野兽。因此,尝试对对象进行调用会导致意外和奇怪的行为/错误。Vector<Byte>

这是一个java错误吗?还是这种疯狂有什么押韵或理由?似乎即使java允许创建基元类型泛型的意外行为,它们也不应该被分配给包装器类型的泛型,该泛型与原语的类不同。

import java.util.Vector;

public class Test
{
    //the trick here is that I am basing the return type of
    //the vector off of the type that was given as the generic
    //argument for the instance of the reflections type Class,
    //however the the class given by byte.class yields a non-class
    //type in the generic, and hence a Vector is created with a
    //primitive type
    public static <Type> Vector<Type> createTypedVector(Class<Type> type)
    {
        return new Vector<Type>(0,1);
    }

    public static void main(String ... args)
    {
        //these lines are to demonstrate that 'byte' and 'Byte'
        //are 2 different class types
        System.out.println(byte.class);
        System.out.println(Byte.class);

        //this is where I create an instance of type Vector<byte>
        //and assign it to a variable of type Vector<Byte>
        Vector<Byte> primitiveTypedGenericObject = createTypedVector(byte.class);

        //this line causes unexpected exceptions to be thrown
        //because primitiveTypedGenericObject is not actually type
        //Vector<Byte>, but rather Vector<byte>
        primitiveTypedGenericObject.set(0,(byte)0xFF);

    }

}

答案 1

两者都是对象。后者仅用于区分基元类型和对象类型。Byte.classByte.TYPEClass<Byte>

实际上,Byte.TYPE被定义为:

public static final Class<Byte> TYPE = (Class<Byte>) Class.getPrimitiveClass("byte");

并且是一种不透明方法,它从 VM 中检索类型,因此我们无法进一步调查它。getPrimitiveClass

因此,即使您认为您正在传递基元数据类型类,因为它们不存在(为什么它们应该存在,因为它们引用了根据对象的Java类型系统可键入的内容,其中不包括基元类型,直到它们被框入包装器类),您正在创建一个.Vector<Byte>

但最终这并不重要,到达运行时执行类型时,注释将被擦除,泛型类型没有任何意义。每当您添加一个它时,它都会自动装箱到一个对象中,仅此而已。byteByte

我目前没有办法测试你的代码,在向?Vector


答案 2

您偶然发现了自动装箱和取消装箱。查看 http://docs.oracle.com/javase/tutorial/java/data/autoboxing.html

坚果壳版本

List<Integer> list = new List<Integer>(); 
list.add(1); // works

byte.class、 等 解析为 、 等。请参阅 Java 语言规范 15.8.2int.classByteInteger

15.8.2. 类文字

......

的类型,其中 p 是基元类型 (§4.2) 的名称,其中 B 是装箱转换后 p 类型的表达式的类型 (§5.1.7)。p.classClass<B>

§8.4.5) 的类型是 。void.classClass<Void>


推荐