繁体   English   中英

Java允许泛型中的原始类型

[英]Java permits primitive types in generics

我知道java不应该支持通用参数,这些参数是原始类型,并且确实如下:

Vector<byte> test;

将无法编译。

然而,我偶然在一个程序中执行了一点点手,我发现实际上可以用原始类型创建一个通用对象(技术如下所示)

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

这是一个java bug吗? 还是有些押韵或理由让这种疯狂? 似乎即使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);

    }

}

Byte.classByte.TYPE都是Class<Byte>对象。 后者仅用于区分原始类型和对象类型。

实际上,Byte.TYPE定义为:

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

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

因此,即使您认为您正在传递原始数据类型Class,因为它们不存在(为什么它们应该是,因为它们引用的是根据对象的Java类型系统而不是包含原语的类型。类型,直到它们被装入包装类),你正在创建一个Vector<Byte>

但最终这并不重要,在达到运行时执行时,类型注释被删除,泛型类型并不意味着什么。 每当你添加一个byte ,它将被自动装箱到Byte对象,就是这样。

我目前无法测试您的代码,在向Vector添加项目时会在运行时抛出哪些异常?

你偶然发现了自动装箱和拆箱。 请参阅http://docs.oracle.com/javase/tutorial/java/data/autoboxing.html

坚果壳版本

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

byte.classint.class等解析为ByteInteger等。请参阅Java语言规范,15.8.2

15.8.2。 类文字

......

p.class的类型,其中p是基本类型的名称(第4.2节 ),是Class<B> ,其中B是在装箱转换(第5.1.7节 )之后类型p的表达式的类型。

void.class§8.4.5 )的类型是Class<Void>

没有! 这不是错误。 它被称为Autoboxing 当您将byte传递给期望Byte的泛型方法时,编译器会自动将其Autoboxes为Byte,这是Object的一个实例。 该操作的对立面称为自动取消装箱 ,这就是为什么像下面所示的操作是合法的。

int a = new Integer(5);
Integer b = 5;

暂无
暂无

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

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