I have a piece of code where I need to pass the class of a field in a method. Because of the mechanics of my code I can only handle reference objects and not primitives. I w
(Idea) Get class name and make first letter capital, then call Class.forInstance(className).newInstance(primitive). Exceptions are "char" -> Character and "int" -> Integer
Class c=Primitive class object
if (c.isPrimitive()) {
if (c == char.class) {
Object wrapper=new Character(primitive var);
}
if (c == int.class) {
Object wrapper=new Integer(primitive var);
}
else {
String name=c.getName();
try {
Class<?> c2=Class.forName("java.lang."+name.substring(0,1).toUpperCase()+name.substring(1,name.length()));
Object wrapper=c2.getConstructor(c).newInstance(primitve_var);
} catch (ClassNotFoundException ex) {
System.out.println("RROR");
}
}
}
Apache Commons Lang has a utility method to do this (ClassUtils.primitiveToWrapper()), which will be just as ugly under the covers, but at least you can pretend it's nice.
There's also com.sun.beans.finder.PrimitiveWrapperMap#getType(primitiveName). But of course using classes from the "com.sun" package is not really recommended...
You can call class.isPrimitive() to know if it is a primitive or not, however, there is no boxing method to convert the classes within the JDK. There is at least one open bug relating to this.
We are retrieving a field and then find it contains a primitive type.
Field f = getTheField(); // Dummy method that returns my Field
Class<?> c = f.getType();
But instead we want the wrapper type.
Now as you already found out the only thing a primitive class is good for is to return true for c.isPrimitive();
.
From wiki books - java programming:
Primitive types are the most basic data types available within the Java language. There are 8: boolean , byte , char , short , int , long , float and double . These types serve as the building blocks of data manipulation in Java. Such types serve only one purpose — containing pure, simple values of a kind.
Attempting to use them any other way and you are in for a lot of hurt.
Field f = getTheField();
Class<?> c = f.getType();
Object wrapper = c.newInstance();
// java.lang.InstantiationException thrown: int
// at Class.newInstance (Class.java:545)
Field f = getTheField();
Class<?> c = f.getType();
Object wrapper = c.cast(0);
// java.lang.ClassCastException thrown: Cannot cast java.lang.Integer to int
// at Class.cast (Class.java:3578)
Field f = getTheField();
Class<?> c = f.getType();
Object wrapper = c.cast(null);
No exceptions and the variable wrapper
is of type class java.lang.Integer
but with a value of null
, a whole lot of good that will do us.
boolean isSuperClass = Integer.class.isAssignableFrom(int.class); // false
This is obviously not getting us anywhere lets rather take a step back from the problem and have a look at the bigger picture.
Lets recap: We are retrieving a field which has to come from somewhere since java.lang.reflect.Field
is marked final and exposes no public constructors.
If we were to fill in the gaps it might look something like this.
public class Simple {
public static int field;
public static void main(String[] args) {
Field f = Simple.class.getField("field"); // Actual method that returns my Field
Class<?> c = f.getType();
}
}
Instead of fighting against the machine lets rather work with it. One of the perks of primitives are that they will initialise to a default value 0
instead of null
. Lets see if we can use that.
public class Simple {
public static int field;
public static void main(String[] args) {
Simple boxer = new Simple();
Field f = Simple.class.getField("field");
Object wrapped = f.get(null); // Integer value 0
Class<?> c = wrapped.getClass(); // class java.lang.Integer
}
}
That was much easier than before and we didn't even have to do anything, everything was done for us. Yet another perk for not trying to go against the stream.
Lets improve on that, refactor and make it a little more reusable by extracting a method.
public class Simple {
public static int field;
public static <T> T wrap(T t) {
return t;
}
public static void main(String[] args) {
Field f = Simple.class.getField("field");
Class<?> c = Simple.wrap(f.get(null)).getClass(); // class java.lang.Integer
}
}
A simple primitive wrap without ever having to look at the types or use look up tables because java already does it anyway.
Field f = getTheField(); // Dummy method that returns my Field
Class<?> c = f.get(null).getClass();
Or you can replace null with an instance if the field is not static.
nJoy!
With a more recent jdk, this is a one-liner now:
@SuppressWarnings("unchecked")
public static <T> Class<T> wrap(Class<T> c) {
return (Class<T>) MethodType.methodType(c).wrap().returnType();
}
@SuppressWarnings("unchecked")
public static <T> Class<T> unwrap(Class<T> c) {
return (Class<T>) MethodType.methodType(c).unwrap().returnType();
}
Here is a test that I wrote using JMH
and here are the results:
Benchmark Mode Cnt Score Error Units
PrimitiveToWrapper.ifStatements avgt 30 42.112 ± 0.716 ns/op
PrimitiveToWrapper.map avgt 30 45.018 ± 0.923 ns/op
PrimitiveToWrapper.wrap avgt 30 52.369 ± 0.836 ns/op
The difference is rather small.