Here is a very simple case: I am trying to cast an Object type to a primitive like this:
Object object = Integer.valueOf(1234);
int result1 = int.class.cast(object); //throws ClassCastException: Cannot convert java.lang.integer to int
int result2 = (int)object; //works fine
This is the source code of cast method of class 'Class'
public T cast(Object obj) {
if (obj != null && !isInstance(obj))
throw new ClassCastException(cannotCastMsg(obj));
return (T) obj;
}
private String cannotCastMsg(Object obj) {
return "Cannot cast " + obj.getClass().getName() + " to " + getName();
}
Why is this happening? Same is happening with other primitives too.
Live Example
cast can't really work well for primitives, given that it can't return a value of the actual primitive type, due to generics in Java... so it would end up boxing again anyway. And if you're not assigning straight to an int value, it would have to be boxed for that reason too.
So basically, if you want to convert to int, just cast directly.
isInstance is documented to always return false for primitives:
If this Class object represents a primitive type, this method returns false.
... cast probably should be too.
Related
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
}
}
I'm trying to make a method that accepts a number of any primitive type (either byte, int, float, long, double or short). Then after a certain checking method either returns that very same number (i.e., for example, it accepts double and returns double) or it returns a zero.
So far I've come to this:
<AnyNumType> AnyNumType cancelAdd(AnyNumType val, String point) {
if (checkModuleMatchAndOff(point) == true) return 0;
else return val;
}
But I get a type mismatch error (with 0 underlined and explained: "Cannot convert from int to AnyNumType"). Is there a way to cope with this zero problem? I intend to use this method in equations so I really need it to return primitive types.
EDIT: Thank you very much for all your replies, guys!
No, you're not accepting any primitive type; you're accepting any object type. You may think you're accepting primitive types, but Java generics can use only reference types. Your values are being boxed when passed into this method. You could pass a String in as val.
That should indicate why 0 can't be converted to AnyNumType -- AnyNumType can be any reference type.
The best way to accept any primitive type is to have overloads for every primitive type, like many methods in the core library do. You can return the equivalent of 0 in each overload, e.g.
byte cancelAdd(byte val, String point)
{
if (checkModuleMatchAndOff(point) == true) return (byte) 0;
else return val;
}
The overloads for the other primitive types will look very similar.
You could change your method type to:
<AnyNumType extends Number> AnyNumType cancelAdd(AnyNumType val, String point);
I don't know exactly what you want do do inside the method, but this should allow you to pass in primitives via auto-boxing.
But it is not generally possible to use generics for primitive types in Java, autoboxing is, I think, the only way.
Returning a value other than the object you got in is possible, but you'd need some ugly reflection and casts, unfortunately. And it would not support all possible types.
(Maybe there is some library for this somewhere?)
For any doubters out there, here's sample code fresh out of Eclipse, without compilation errors, that demonstrates this:
public class NumberGenerix {
#SuppressWarnings("unchecked")
public static <Any extends Number> Any f(Any x) {
Class<?> k = x.getClass();
if (k == Integer.class) {
return (Any) Integer.valueOf(0);
} else if (k == Double.class) {
return (Any) Double.valueOf(0.0);
} else if (k == Long.class) {
return (Any) Long.valueOf(0L);
} else {
// and so on.
throw new RuntimeException("unsupported number type: " + k);
}
}
public static void main(String...args) {
Integer a = f(42);
System.out.println("a == " + a);
Long b = f(42L);
System.out.println("b == " + b);
Double c = f(42.0);
System.out.println("c == " + c);
}
}
Here is a table of primitive types and their equivalent wrapper class.
Primitive type Wrapper class
============== =============
boolean Boolean
byte Byte
char Character
float Float
int Integer
long Long
short Short
double Double
I would like to create a method that would convert any given primitive variable into an appropriate class. I have tried something like below, but that obviously does not work. Any help would be appreciated:
public static <T> T forceBox(T t) {
switch (T) {
case boolean.class : return new Boolean(t);
case int.class : return new Integer(t);
// etc
}
}
the caller code looks like:
int x = 3;
System.out.println("x wrapper type: " + forceBox(x).getClass());
Though this is completely unnecessary in most cases, just use
public static <T> T forceBox(T t) { // compiler will add the conversion at the call site
return t;
}
Though you can also just use
Object o = <some primitive>;
The conversion is already done when needed as part of the boxing process.
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");
}
}
}
In below program I fail to understand why there is ClassCastException for cast from int.class
Update:
I should specify I know what primitive types are. What I don't understand is why int.class is provided with broken implementation?
public static void main(String[] args) {
System.out.println(DataType.INT.getValue(Integer.class));
System.out.println(DataType.INT.getValue(int.class));//Class cast exception here
}
enum DataType {
INT {
#Override
public <T> T getValue(Class<T> toClass) {
return toClass.cast(1000);//ClassCastException here for int.class
}
};
public abstract <T> T getValue(Class<T> toClass);
}
This happens because cast() operation of Class uses isInstance() method which returns false for primitive classes.
If this Class object represents a primitive type, this method returns false.
Code for cast() method is below
public T cast(Object obj) {
if (obj != null && !isInstance(obj))//It fails here since isInstance returns false
throw new ClassCastException();
return (T) obj;
Ok, after going through some links, and trying out some code, I found out that: -
int.class == Integer.TYPE == int
int.class != Integer.class
So, the value of int.class is Class object representing the type int.
So, when you invoke your DataType.INT with int.class, the toClass containts int, on which you cannot invoke cast. May be because it does not extend from Object class. Because, cast method internally uses isinstance to check whether the invoking type is an Object type or not.
public T cast(Object obj) {
if (obj != null && !isInstance(obj))
throw new ClassCastException();
return (T) obj;
}
So, if the type that invokes cast is not an instance of Object, which of course primitive types are not, it will return false, and hence a ClassCastException.
Integer is a class wrapper for int values, while int is a primitive type, not a class. Don't confuse between primitive types and classes, for example, in code when you must use classes:
List<int> lstInteger; //won't compile!
List<Integer> lstInteger; //compiles fine
More info:
Java: int versus Integer
Java: int or integer
Think of int type as a primitive C/C++ int type. Knowing this, the int is not a class, thus not having any attributes, any methods, just holding a integer value. On the other hand, java.lang.Integer is a class wrapper for int primitive type. This is in order to use the int in cases where only object instances could be used. A good example of this is the generic system in Java that works only for classes (as proposed in your code example).
For deeper info in this, you can read from the Oracle Java Tutorial: Primitive Data Types.
A class cast exception is thrown by Java when you try to cast an Object of one data type to another. Here int is not an Object, it's a primitive which gets instantiated by some native code at runtime.
I think this is what happening:
When you call return toClass.cast(1000);, the literal 1000 is getting promoted to Integer. Promotion rules are mentioned here : Java Language Specification.
Now when, cast method is called on intClass, its checks if argument(1000) is of same instance i.e. int.class and it fails because its not.
On the other hand, when you cast to Integer.class, it is successful as instance type does match.
So the ClassCastException is coming because of Promotion of literal 1000 to Integer.
I think it's because of the fact that int.class is not same as Integer.class.
Update
We can look at the cast method, it parameter is an Object so it's obvious that 1000 get autoboxed, thus the actual argument to the method is an instance of Integer:
public T cast(Object obj) {
if (obj != null && !isInstance(obj))
throw new ClassCastException();
return (T) obj;
}