Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java permits primitive types in generics

Tags:

I know that java is not supposed support generic arguments which are primitive types, and sure enough something like:

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. Because of this, attempts to do calls on the object result in unexpected and strange behaviors/errors.

Is this a 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.

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);      }  } 
like image 608
S E Avatar asked Sep 07 '13 06:09

S E


1 Answers

Both Byte.class and Byte.TYPE are Class<Byte> objects. The latter are just used to distinguish between primitive type and object type.

Actually Byte.TYPE is defined as:

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.

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>.

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.

I have no way to test your code at the moment, which exceptions are thrown at runtime when adding items to the Vector?

like image 178
Jack Avatar answered Sep 19 '22 13:09

Jack