Here is a literal class that allows one to get a value of a specified type:
public class Literal {
private final String value;
public Literal(String value) {
this.value = value;
}
public <T> T getValue(Class<T> type) {
if (type == Boolean.class || type == Boolean.TYPE) {
return type.cast("true".equalsIgnoreCase(value));
}
throw new UnsupportedOperationException();
}
}
It works fine for object types:
new Literal("true").getValue(Boolean.class);
But it throws the error for primitive types:
new Literal("true").getValue(Boolean.TYPE);
java.lang.ClassCastException: Cannot cast java.lang.Boolean to boolean
Is it possible to return a boolean value without the exception?
Or maybe I can transform a primitive type to a corresponding object type before calling the method? Is there a method to transform boolean type to java.lang.Boolean.class, int type to java.lang.Integer.class, ...? Something like this:
new Literal("true").getValue(toObjectType(Boolean.TYPE));
Yes.. and no.
In basis what you say is a non-sequitur. Your question is: "How do I put this round green in this square hole" - concepts that don't even align.
"An object" cannot become a primitive value, and "an object" cannot be used where a primitive is required. This: Object o = 5; is illegal plain and simple.
Except.. it isn't. And the reason it isn't, is only because of syntax sugar. The compiler KNOWS it is illegal but assumes you MEANT to write Object o = Integer.valueOf(5); so, it just assumes you meant that and generates code accordingly. Just go compile that, run javap -c -v and lo! A call to integer.valueOf you never wrote.
You can do the same thing here: Write an 8-nested if/elseif:
if (type == boolean.class /* or Boolean.TYPE - same thing */) {
return (T) "true".equals(value);
}
The type.cast part only buys you a runtime check, which is literally pointless as you already just did so with an if, thus, (T) foo is superior to type.cast(foo) here. Even though (T) thing produces a warning - ignore it, you know the warning is irrelevant. The heap corruption it is warning you about cannot happen / the type.cast wouldn't fix it.
In other words, get rid of type.cast(x) and make that (T) x and the error goes away (and a warning comes in trade; but that one you can #SuppressWarnings). The code will do what you want:
boolean v = new Literal("true").getValue(boolean.class);
But note that the system auto-boxes and auto-unboxes anyway. You can't stop that from happening unless you make a new method for it:
boolean v = new Literal("true").getBooleanValue();
Where you can implement getBooleanValue as return "true".equals(value); of course.
"I do not want the overhead of autoboxing" and "... you will be making 8 additional methods then" go hand in hand. It's why e.g. IntStream exists instead of just having a Stream<Integer>.
NB: The cast operator is used for 3 utterly unrelated things. 2 of those 3 are about assertions (is this thing type X already? If yes do nothing, if no, throw an exception / break the JVM, depending on which of the 2) - only one actually converts things, and it's primitive conversion: the thing in the () has to be a primitive type. You can't get that kind of cast here, that kind of cast fundamentally is not dynamic. Hence, no conversion can take place, hence, trying to 'cast an object to lower-case-b boolean' is an error. "cast" the operator cannot do that.
rzwitserloot already explained quite well how and why you should adjust the casting and the difference between primitives and objects.
I just wanted to give you a small executable example on top of that. You could do something like the following:
public class Literal {
private final String value;
public Literal(String value) {
this.value = value;
}
public <T> T getValue(Class<T> type) {
if (type == Boolean.class || type == Boolean.TYPE) {
return (T) new Boolean(this.value); // or Boolean.valueOf(this.value)
} else if (type == boolean.class) {
return (T) this.value;
}
// [add other type checks here, if you want]
throw new UnsupportedOperationException();
}
public boolean getBooleanValue() {
return new Boolean(this.value); // or Boolean.valueOf(this.value)
}
/** This method is just here for demo purpose */
public static void main(String[] args) {
// Use it like this
Boolean obj = new Literal("true").getValue(Boolean.TYPE);
Boolean obj2 = new Literal("FALSE").getValue(Boolean.TYPE);
boolean primitive = new Literal("true").getValue(boolean.class);
boolean primitive2 = new Literal("FALSE").getValue(boolean.class);
System.out.println(obj); // true
System.out.println(obj2); // false
System.out.println(primitive); // true
System.out.println(primitive2); // false
// Or this
boolean primitive3 = new Literal("true").getBooleanValue();
System.out.println(primitive3); // true
}
}
Related
When generics were added to 1.5, java.lang.reflect added a Type interface with various subtypes to represent types. Class is retrofitted to implement Type for the pre-1.5 types. Type subtypes are available for the new types of generic type from 1.5.
This is all well and good. A bit awkward as Type has to be downcast to do anything useful, but doable with trial, error, fiddling and (automatic) testing. Except when it comes to implementation...
How should equals and hashCode be implemented. The API description for the ParameterizedType subtype of Type says:
Instances of classes that implement this interface must implement an equals() method that equates any two instances that share the same generic type declaration and have equal type parameters.
(I guess that means getActualTypeArguments and getRawType but not getOwnerType??)
We know from the general contract of java.lang.Object that hashCode must also be implemented, but there appears to be no specification as what values this method should produce.
None of the other subtype of Type appear to mention equals or hashCode, other than that Class has distinct instances per value.
So what do I put in my equals and hashCode?
(In case you are wondering, I am attempting to substitute type parameters for actual types. So if I know at runtime TypeVariable<?> T is Class<?> String then I want to replace Types, so List<T> becomes List<String>, T[] becomes String[], List<T>[] (can happen!) becomes List<String>[], etc.)
Or do I have to create my own parallel type type hierarchy (without duplicating Type for presumed legal reasons)? (Is there a library?)
Edit: There's been a couple of queries as to why I need this. Indeed, why look at generic type information at all?
I'm starting with a non-generic class/interface type. (If you want a parameterised types, such as List<String> then you can always add a layer of indirection with a new class.) I am then following fields or methods. Those may reference parameterised types. So long as they aren't using wildcards, I can still work out actual static types when faced with the likes of T.
In this way I can do everything with high quality, static typing. None of these instanceof dynamic type checks in sight.
The specific usage in my case is serialisation. But it could apply to any other reasonable use of reflection, such as testing.
Current state of code I am using for the substitution below. typeMap is a Map<String,Type>. Present as an "as is" snapshot. Not tidied up in anyway at all (throw null; if you don't believe me).
Type substitute(Type type) {
if (type instanceof TypeVariable<?>) {
Type actualType = typeMap.get(((TypeVariable<?>)type).getName());
if (actualType instanceof TypeVariable<?>) { throw null; }
if (actualType == null) {
throw new IllegalArgumentException("Type variable not found");
} else if (actualType instanceof TypeVariable<?>) {
throw new IllegalArgumentException("TypeVariable shouldn't substitute for a TypeVariable");
} else {
return actualType;
}
} else if (type instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType)type;
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
int len = actualTypeArguments.length;
Type[] actualActualTypeArguments = new Type[len];
for (int i=0; i<len; ++i) {
actualActualTypeArguments[i] = substitute(actualTypeArguments[i]);
}
// This will always be a Class, wont it? No higher-kinded types here, thank you very much.
Type actualRawType = substitute(parameterizedType.getRawType());
Type actualOwnerType = substitute(parameterizedType.getOwnerType());
return new ParameterizedType() {
public Type[] getActualTypeArguments() {
return actualActualTypeArguments.clone();
}
public Type getRawType() {
return actualRawType;
}
public Type getOwnerType() {
return actualOwnerType;
}
// Interface description requires equals method.
#Override public boolean equals(Object obj) {
if (!(obj instanceof ParameterizedType)) {
return false;
}
ParameterizedType other = (ParameterizedType)obj;
return
Arrays.equals(this.getActualTypeArguments(), other.getActualTypeArguments()) &&
this.getOwnerType().equals(other.getOwnerType()) &&
this.getRawType().equals(other.getRawType());
}
};
} else if (type instanceof GenericArrayType) {
GenericArrayType genericArrayType = (GenericArrayType)type;
Type componentType = genericArrayType.getGenericComponentType();
Type actualComponentType = substitute(componentType);
if (actualComponentType instanceof TypeVariable<?>) { throw null; }
return new GenericArrayType() {
// !! getTypeName? toString? equals? hashCode?
public Type getGenericComponentType() {
return actualComponentType;
}
// Apparently don't have to provide an equals, but we do need to.
#Override public boolean equals(Object obj) {
if (!(obj instanceof GenericArrayType)) {
return false;
}
GenericArrayType other = (GenericArrayType)obj;
return
this.getGenericComponentType().equals(other.getGenericComponentType());
}
};
} else {
return type;
}
}
I've been solving this problem in unsatisfying ways for 10 years. First with Guice’s MoreTypes.java, copy-pasted and revised with Gson’s GsonTypes.java, and again in Moshi’s Util.java.
Moshi has my best approach, which isn't to say that it's good.
You can't call equals() on arbitrary implementations of Type and expect it to work.
This is because the Java Types APIs offers multiple incompatible ways to model arrays of simple classes. You can make a Date[] as a Class<Date[]> or as a GenericArrayType whose component type is Date. I believe you’ll get the former from reflection on a field of type Date[] and the latter from reflection as the parameter of a field of type List<Date[]>.
The hash codes aren't specified.
I also got to work on the implementation of these classes that Android uses. Very early versions of Android have different hash codes vs. Java, but everything you'll find in the wild today uses the same hash codes as Java.
The toString methods aren't good
If you're using types in error messages it sucks to have to write special code to print them nicely.
Copy Paste and Be Sad
My recommendation is to not use equals() + hashCode() with unknown Type implementations. Use a canonicalize function to convert into a specific known implementation and only compare within the ones you control.
Here is a little experiment that relies directly on the Sun API and reflection (that is, it uses reflection to work with classes that implement reflection):
import java.lang.Class;
import java.lang.reflect.*;
import java.util.Arrays;
import sun.reflect.generics.reflectiveObjects.*;
class Types {
private static Constructor<ParameterizedTypeImpl> PARAMETERIZED_TYPE_CONS =
((Constructor<ParameterizedTypeImpl>)
ParameterizedTypeImpl
.class
.getDeclaredConstructors()
[0]
);
static {
PARAMETERIZED_TYPE_CONS.setAccessible(true);
}
/**
* Helper method for invocation of the
*`ParameterizedTypeImpl` constructor.
*/
public static ParameterizedType parameterizedType(
Class<?> raw,
Type[] paramTypes,
Type owner
) {
try {
return PARAMETERIZED_TYPE_CONS.newInstance(raw, paramTypes, owner);
} catch (Exception e) {
throw new Error("TODO: better error handling", e);
}
}
// (similarly for `GenericArrayType`, `WildcardType` etc.)
/** Substitution of type variables. */
public static Type substituteTypeVariable(
final Type inType,
final TypeVariable<?> variable,
final Type replaceBy
) {
if (inType instanceof TypeVariable<?>) {
return replaceBy;
} else if (inType instanceof ParameterizedType) {
ParameterizedType pt = (ParameterizedType) inType;
return parameterizedType(
((Class<?>) pt.getRawType()),
Arrays.stream(pt.getActualTypeArguments())
.map((Type x) -> substituteTypeVariable(x, variable, replaceBy))
.toArray(Type[]::new),
pt.getOwnerType()
);
} else {
throw new Error("TODO: all other cases");
}
}
// example
public static void main(String[] args) throws InstantiationException {
// type in which we will replace a variable is `List<E>`
Type t =
java.util.LinkedList
.class
.getGenericInterfaces()
[0];
// this is the variable `E` (hopefully, stability not guaranteed)
TypeVariable<?> v =
((Class<?>)
((ParameterizedType) t)
.getRawType()
)
.getTypeParameters()
[0];
// This should become `List<String>`
Type s = substituteTypeVariable(t, v, String.class);
System.out.println("before: " + t);
System.out.println("after: " + s);
}
}
The result of substitution of E by String in List<E> looks as follows:
before: java.util.List<E>
after: java.util.List<java.lang.String>
The main idea is as follows:
Get the sun.reflect.generics.reflectiveObjects.XyzImpl classes
Get their constructors, ensure that they are accessible
Wrap the constructor .newInstance invocations in helper methods
Use the helper methods in a simple recursive method called substituteTypeVariable that rebuilds the Type-expressions with type variables substituted by concrete types.
I didn't implement every single case, but it should work with more complicated nested types too (because of the recursive invocation of substituteTypeVariable).
The compiler doesn't really like this approach, it generates warnings about the usage of the internal Sun API:
warning: ParameterizedTypeImpl is internal proprietary API and may be removed in a future release
but, there is a #SuppressWarnings for that.
The above Java code has been obtained by translating the following little Scala snippet (that's the reason why the Java code might look a bit strange and not entirely Java-idiomatic):
object Types {
import scala.language.existentials // suppress warnings
import java.lang.Class
import java.lang.reflect.{Array => _, _}
import sun.reflect.generics.reflectiveObjects._
private val ParameterizedTypeCons =
classOf[ParameterizedTypeImpl]
.getDeclaredConstructors
.head
.asInstanceOf[Constructor[ParameterizedTypeImpl]]
ParameterizedTypeCons.setAccessible(true)
/** Helper method for invocation of the `ParameterizedTypeImpl` constructor. */
def parameterizedType(raw: Class[_], paramTypes: Array[Type], owner: Type)
: ParameterizedType = {
ParameterizedTypeCons.newInstance(raw, paramTypes, owner)
}
// (similarly for `GenericArrayType`, `WildcardType` etc.)
/** Substitution of type variables. */
def substituteTypeVariable(
inType: Type,
variable: TypeVariable[_],
replaceBy: Type
): Type = {
inType match {
case v: TypeVariable[_] => replaceBy
case pt: ParameterizedType => parameterizedType(
pt.getRawType.asInstanceOf[Class[_]],
pt.getActualTypeArguments.map(substituteTypeVariable(_, variable, replaceBy)),
pt.getOwnerType
)
case sthElse => throw new NotImplementedError()
}
}
// example
def main(args: Array[String]): Unit = {
// type in which we will replace a variable is `List<E>`
val t =
classOf[java.util.LinkedList[_]]
.getGenericInterfaces
.head
// this is the variable `E` (hopefully, stability not guaranteed)
val v =
t
.asInstanceOf[ParameterizedType]
.getRawType
.asInstanceOf[Class[_]] // should be `List<E>` with parameter
.getTypeParameters
.head // should be `E`
// This should become `List<String>`
val s = substituteTypeVariable(t, v, classOf[String])
println("before: " + t)
println("after: " + s)
}
}
Say I have a generic class Foo which can hold an object of type T. Furthermore, let's say I only want to be able to instantiate the class with objects that are one of two types. Finally, let's say that the lowest common upper bound of these two types is a type that has many more subclasses than those two types that I want to allow, so I can't simply specify an upper bound for the type parameter (as in class Foo<T extends Something>), because then I would allow to instantiate the class with other types than the two I expect.
For illustration, let's say I want Foo to hold only either a String or an Integer. The lowest common upper bound is Object, so specifying an upper bound won't do the trick.
Certainly, I could do something along the lines of
class Foo<T> {
private T obj;
public Foo(T obj) throws IllegalArgumentException {
if (!(obj instanceof String || obj instanceof Integer)) {
throw new IllegalArgumentException("...");
}
this.obj = obj;
}
}
However, in this case, I can still call the constructor with any object; if I try to instantiate it with something that is neither a String nor an Integer, I will get an exception at runtime.
I would like to do better. I would like the compiler to infer statically (i.e., at compile time) that I can only instantiate this class with objects that are either String or Integer.
I was thinking something along those lines might do the trick:
class Foo<T> {
private T obj;
public Foo(String s) {
this((T) s);
}
public Foo(Integer i) {
this((T) i);
}
private Foo(T obj) {
this.obj = obj;
}
}
This works, but it looks really, really odd. The compiler warns (understandably) about unchecked casts. Of course I could suppress those warnings, but I feel this is not the way to go. In addition, it looks like the compiler can't actually infer the type T. I was surprised to find that, with the latter definition of class Foo, I could do this, for instance:
Foo<Character> foo = new Foo<>("hello");
Of course, the type parameter should be String here, not Character. But the compiler lets me get away with the above assignment.
Is there a way to achieve what I want, and if yes, how?
Side question: why does the compiler let me get away with the assignment to an object of type Foo<Character> above without even so much as a warning (when using the latter definition of class Foo)? :)
Try using static factory method to prevent compiler warning.
class Foo<T> {
private T obj;
public static Foo<String> of(String s) {
return new Foo<>(s);
}
public static Foo<Integer> of(Integer i) {
return new Foo<>(i);
}
private Foo(T obj) {
this.obj = obj;
}
}
Now you create instance using:
Foo<String> foos = Foo.of("hello");
Foo<Integer> fooi = Foo.of(42);
Foo<Character> fooc = Foo.of('a'); // Compile error
However the following are still valid since you can declare a Foo of any type T, but not instantiate it:
Foo<Character> fooc2;
Foo<Character> fooc3 = null;
Foo<Object> fooob1;
Foo<Object> fooob2 = null;
one word: interface. You want your Z to wrap either A or B. Create an interface implementing the smallest common denominator of A and B. Make your A and B implement that interface. There's no other sound way to do that, AFAIK. What you already did with your constructors etc. is the only other possibility, but it comes with the caveats you already noticed (having to use either unchecked casts, or static factory wrappers or other code smells).
note: If you can't directly modify A and/or B, create wrapper classes WA and WBfor them beforehand.
example:
interface Wrapper {
/* either a marker interface, or a real one - define common methods here */
}
class WInt implements Wrapper {
private int value;
public WInt( int value ) { this.value = value; }
}
class WString implements Wrapper {
private String value;
public WString( String value ) { this.value = value; }
}
class Foo<T> {
private Wrapper w;
public Foo(Wrapper w) { this.w = w; }
}
because you call your private Foo(T obj) due to diamond type inference. As such, it's equal to calling Foo<Character> foo = new Foo<Character>("hello");
Long story short: You are trying to create a union of two classes in java generics which is not possible but there are some workarounds.
See this post
Well the compiler uses the Character class in T parameter. Then the String constructor is used where String is casted to T (Character in this case).
Trying to use the private field obj as a Character will most likely result in an error as the saved value is an instance of the final class String.
Generics is not suitable here.
Generics are used when any class can be used as the type. If you only allow Integer and String, you should not use generics. Create two classes FooInteger and FooString instead.
The implementations should be pretty different anyway. Since Integers and Strings are very different things and you would probably handle them differently. "But I am handling them the same way!" you said. Well then what's wrong with Foo<Double> or Foo<Bar>. If you can handle Integer and String with the same implementation, you probably can handle Bar and Double and anything else the same way as well.
Regarding your second question, the compiler will see that you want to create a Foo<Character>, so it tries to find a suitable overload. And it finds the Foo(T) overload to call, so the statement is perfectly fine as far as the compiler is concerned.
I understand generics pretty well, but came across a seemingly simple problem that I don't quite understand. Take a look at the following example.
public <T extends Object> T getSetting(String settingName) {
return settings.getJsonObject(settingName).getValue("value");
}
settings is a instance attribute from type vertx.core.json.JsonObject. The result of getValue is Object.
I thought by setting the return type to T I would be able to return any type that is Object or an super type like String or Integer. This code however gives me the following error message.
incompatible types: java.lang.Object cannot be converted to T
What am I overlooking here?
That code does not compile because whatever T is, decided at compilation time, does not need to match what getValue will return which is determined at run-time
which is not restricted at all.
You can add a (T) cast and that would transform the error in a warning but that would not prevent the potential run-time cast error and that is why it stays as a warning.
I don't think there is any real workaround for this as you can never be certain of the type of the getValue return ... however you can provide some methods that at least would:
a. fail more gracefully (with a nicer error message),
b. return a default value if the type is not the one expected,
c. give the user the chance to provide the casting lambda to transform
any possible input type into the expected return value class.
E.g.
public <T> T getSetting(String settingName, Class<T> clazz) {
final Object obj = settings.getJsonObject(settingName).getValue("value");
if (obj == null)
return null;
else if (!clazz.isInstance(obj))
throw new IllegalArgumentException(String.format("wrong setting class; was expecting %s but found %s", clazz.getSimpleName(), obj.getClass().getName());
else {
return clazz.cast(obj);
}
}
...
Integer x = getSetting("mysetting", Integer.class);
Or:
public <T> T getSetting(String settingName, Function<Object, T> cast) {
final Object obj = settings.getJsonObject(settingName).getValue("value");
return obj == null ? null : cast.apply(obj);
}
...
Integer x = getSetting("mysetting", o -> Integer.parseInt(o.toString()));
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 want an easy way of determining if a Field's type is primitive and swap it with the appropriate wrapper class. So in code what I do so far is something like this:
Field f = getTheField(); // Dummy method that returns my Field
Class<?> c = f.getType();
if (c == int.class) {
c = Integer.class;
}
else if (c == float.class) {
c = Float.class;
}
// etc
myMethod(c);
This works fine, except for the fact that I need to explicitly check for all the primitive types and swap them with the appropriate wrapper class. Now I know that there are not so many primitive types and it won't be a problem to simply list them all, but I was wondering if there was an easier and more elegant way of doing it.
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.
I think this answer is probably the right way now
Or, Guava has this:
http://google.github.io/guava/releases/21.0/api/docs/com/google/common/primitives/Primitives.html
It has the wrap() method, plus unwrap() and a few other incidental things.
If you don't use Guava, you can follow the example of its implementation.
Here is another way if you don't need highly optimized code:
Class<?> primitive=long.class;
Class<?> boxed=Array.get(Array.newInstance(primitive,1),0).getClass();
System.out.println(primitive.getName());
System.out.println(boxed.getName());
(Editing/adding explanation)
At first, it was to see if Java has a method to give you the wrapper class when given a primitive type. Couldn't find any.
Then, it was to see if you can have Java create a primitive value when give a primitive type (then you can somehow get an object out of it). Couldn't find a way to do this.
But then it was found out that you CAN have Java create an array of primitive values when given a primitive type. And then there is a Java method that gives you an object of the wrapping type of the array element(which is primitive). Once you have the object, you can then get the type.
So here is how the whole thing work:
The method Array.newInstance() creates a array of whatever type you specify, whether it is primitive or object. In the case of object, all elements are object type but initialized to null. In the case of primitive, elements are primitive type. But primitive variable/array element can't be null, so they have the default value of the primitive type, e.g. int will be zero. Thus no elements will be null. And now if you try to get the value of an element by using Array.get(), Array.get() has no choice but box that primitive value to an object, e.g. int to Integer, because Array.get() can't return primitive value. Now you have an object of the boxing(wrapping) type of you original primitive type. Finally calling Object.getClass() gives you the boxing(wrapping) type.
This trick works with any primitive type you have in Java today and in the future.
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.
Since Java 7, this is a one-liner:
#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.
Class<?> toWrapper(Class<?> clazz) {
if (!clazz.isPrimitive())
return clazz;
if (clazz == Integer.TYPE)
return Integer.class;
if (clazz == Long.TYPE)
return Long.class;
if (clazz == Boolean.TYPE)
return Boolean.class;
if (clazz == Byte.TYPE)
return Byte.class;
if (clazz == Character.TYPE)
return Character.class;
if (clazz == Float.TYPE)
return Float.class;
if (clazz == Double.TYPE)
return Double.class;
if (clazz == Short.TYPE)
return Short.class;
if (clazz == Void.TYPE)
return Void.class;
return clazz;
}
So you want to get the wrapper class type, ok.
No need to query the types or reference look up tables because java already does it anyway. Let's walk through the problem together...
Synopsis
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(); // Gets the declared primitive type
But instead we want the wrapper type.
Primitive types in Java
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.
So why do we want to know the wrapper type?
Attempting to use primitives in any other way and you are in for a lot of hurt.
Cannot make a new instance of a primitive.
Field f = getTheField();
Class<?> c = f.getType();
Object wrapper = c.newInstance();
// java.lang.InstantiationException thrown: int
// at Class.newInstance (Class.java:545)
Cannot cast to a primitive type.
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)
Can cast to a null wrapper type. Yeah! \o/
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.
Primitives are not even inherited from wrappers.
boolean isSuperClass = Integer.class.isAssignableFrom(int.class); // false
This is obviously not getting us anywhere so lets rather take a step back from the problem and have a look at the bigger picture.
When at first you don't succeed...
Lets recap: We are retrieving a field which has to come from somewhere so if we were to fill in the gaps left out in the question it might look something like this.
public class Simple {
public static int field;
public static Field getTheField() {
return Simple.class.getField("field"); // Actual method that returns our Field
}
public static void main(String[] args) {
Field f = getTheField();
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.
Get wrapper class from wrapped instance.
public class Simple {
public static int field;
public static Field getTheField() {
return Simple.class.getField("field"); // Actual method that returns our Field
}
public static void main(String[] args) {
Field f = getTheField();
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, auto boxing, 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.
Implement a manual boxing method.
We can do the same auto boxing with generics:
public class Simple {
public static int field;
public static Field getTheField() {
return Simple.class.getField("field"); // Actual method that returns our Field
}
public static <T> T wrap(T t) {
return t;
}
public static void main(String[] args) {
Field f = getTheField();
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.
Conclusion
The simple solution using pure java to get the wrapper class from a primitive field:
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!
(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");
}
}
}
How do I do this? Because you can only extend one class so it can only have one upper bound.
In my case I need the generic type to be bounded in String and int. If I use an Integer wrapper instead of int and rely on auto-boxing, I can make it but the problem is other classes can be passed as a type parameter as well.
What's the best way to do this?
You could use the non generic variants of collections (e.g List), or
more cleanly explicitly List<Object> to show code's intention.
Wrap that in a MyList class, and create add(), get() methods for each type you want to support:
add(Integer elem);
add(String elem);
But Object get() cannot be typed, such that it makes sense.
So finally you also can use Object with List, and omit the wrapper.
I don't think you can do it. String also is a final class and all that stuff. As #NimChimpsky said, you are probably better using Object itself. Another solution is a wrapper for both classes, but you will still have a resulting object which you will probably need to cast around and rely on instanceof:
class StringInt {
private String string;
private Integer integer;
public StringInt(String s) { this.string = s; }
public StringInt(Integer i) { this.integer = i; }
public Object getValue() { return string != null ? string : integer; }
}
Or with an ugly verification, which, obviously, will only apply at runtime...
class StringIntGen<T> {
private T t;
public StringIntGen(T t) {
if (!(t instanceof String) && !(t instanceof Integer))
throw new IllegalArgumentException(
"StringIntGen can only be Integer or String");
this.t = t;
}
public T getValue() { return t; }
}