[英]Java permits primitive types in generics
I know that java is not supposed support generic arguments which are primitive types, and sure enough something like: 我知道java不应该支持通用参数,这些参数是原始类型,并且确实如下:
Vector<byte> test;
will fail to compile. 将无法编译。
however with a little slight-of-hand that I accidentally performed in a program, I found that it is actually possible to create a generic object with a primitive type (technique shown below) 然而,我偶然在一个程序中执行了一点点手,我发现实际上可以用原始类型创建一个通用对象(技术如下所示)
Furthermore, java falsely allows this instance to be assigned to a variable of type Vector<Byte>
when as the print statements show, byte.class and Byte.class are two separate beasts. 此外,java错误地允许将此实例分配给
Vector<Byte>
类型的变量,而当print语句显示时,byte.class和Byte.class是两个独立的野兽。 Because of this, attempts to do calls on the object result in unexpected and strange behaviors/errors. 因此,尝试对对象进行调用会导致意外和奇怪的行为/错误。
Is this a java bug? 这是一个java bug吗? or is there some rhyme or reason to this madness?
还是有些押韵或理由让这种疯狂? It seems like even if java allowed the unexpected behavior of creating primitive-typed generics, they should not be assignable to a generic of the wrapper type which is of a distinct class from the primitive.
似乎即使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);
}
}
Both Byte.class
and Byte.TYPE
are Class<Byte>
objects. Byte.class
和Byte.TYPE
都是Class<Byte>
对象。 The latter are just used to distinguish between primitive type and object type. 后者仅用于区分原始类型和对象类型。
Actually Byte.TYPE is defined as: 实际上,Byte.TYPE定义为:
public static final Class<Byte> TYPE = (Class<Byte>) Class.getPrimitiveClass("byte");
and getPrimitiveClass
is an opaque method which retrieves the type from the VM so we can't investigate it further. 和
getPrimitiveClass
是一个不透明的方法,它从VM中检索类型,因此我们无法进一步调查它。
So, even if you think that you are passing a primitive data type Class, since they don't exist (why should they, since they refer to something that is typable according to the Java typing system for objects, which doesn't include primitive types until they are boxed into wrapper classes), you are creating a Vector<Byte>
. 因此,即使您认为您正在传递原始数据类型Class,因为它们不存在(为什么它们应该是,因为它们引用的是根据对象的Java类型系统而不是包含原语的类型。类型,直到它们被装入包装类),你正在创建一个
Vector<Byte>
。
But in the end this doesn't matter much, upon reaching run-time execution type annotations are erased and the generic type doesn't mean anything. 但最终这并不重要,在达到运行时执行时,类型注释被删除,泛型类型并不意味着什么。 Whenever you'll add a
byte
it will be autoboxed to a Byte
object and that's it. 每当你添加一个
byte
,它将被自动装箱到Byte
对象,就是这样。
I have no way to test your code at the moment, which exceptions are thrown at runtime when adding items to the Vector
? 我目前无法测试您的代码,在向
Vector
添加项目时会在运行时抛出哪些异常?
You've stumbled upon autoboxing and unboxing. 你偶然发现了自动装箱和拆箱。 See http://docs.oracle.com/javase/tutorial/java/data/autoboxing.html
请参阅http://docs.oracle.com/javase/tutorial/java/data/autoboxing.html
The nutshell version 坚果壳版本
List<Integer> list = new List<Integer>();
list.add(1); // works
byte.class
, int.class
, etc. resolve to Byte
, Integer
, etc. See the Java Language Specification, 15.8.2 : byte.class
, int.class
等解析为Byte
, Integer
等。请参阅Java语言规范,15.8.2 :
15.8.2.
15.8.2。 Class Literals
类文字
......
......
The type of
p.class
, where p is the name of a primitive type ( §4.2 ), isClass<B>
, where B is the type of an expression of type p after boxing conversion ( §5.1.7 ).p.class
的类型,其中p是基本类型的名称(第4.2节 ),是Class<B>
,其中B是在装箱转换(第5.1.7节 )之后类型p的表达式的类型。The type of
void.class
( §8.4.5 ) isClass<Void>
.void.class
( §8.4.5 )的类型是Class<Void>
。
No! 没有! It is not bug.
这不是错误。 It is called Autoboxing .
它被称为Autoboxing 。 When you pass byte to a generic method that expects Byte , the compiler automatically Autoboxes it to Byte which is an instance of Object.
当您将byte传递给期望Byte的泛型方法时,编译器会自动将其Autoboxes为Byte,这是Object的一个实例。 The antithesis of that operation is called Auto Unboxing and that is why operations like the one shown below are legal.
该操作的对立面称为自动取消装箱 ,这就是为什么像下面所示的操作是合法的。
int a = new Integer(5);
Integer b = 5;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.