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;
}
Related
Although I know this is not the most efficient way to creating a hash code, I am working to make hash codes by converting data to integers and this will be their hash codes. I am approaching this with data types that are only 32 bits or less(thus just byte,integer,character,short and float). While creating a program I have run across a problem that has to due with generics. I have a class that accepts only the data types that I talked about above by using the instanceof keyword in java within an if as such:
public class HashCode<T>
{
public static void main(String[]args)
{
codeAsInt(2);
codeAsInt('C');
codeAsInt("name");
}
public int codeAsInt(T value)
{
if(value instanceof Integer || value instanceof Character || value instanceof Short || value instanceof Float || value instanceof Byte)
{
int hashcode = (int)value;
return hashcode;
}
else
{
//you cannot use this method return -1
return -1;
}
}
Doing this cause an error as I cannot convert "value" of any of these types to T. Is there anyway I can pass different data types to a method using generics? I know I could solve this problem using method overloading(creating different methods that accept different data types) but from what I have learnt method overloading is used with methods that do different things, for my method it does the same thing(converts data to ints). I also know I could have created a separate class to do this but I think this would be inefficient for such a simple task.
Error at compiling time:
error: incompatible types: int cannot be converted to T
codeAsInt(2);
^
where T is a type-variable:
T extends Object declared in class HashCodes
error: incompatible types: char cannot be converted to T
codeAsInt('C');
^
where T is a type-variable:
T extends Object declared in class HashCodes
error: incompatible types: String cannot be converted to T
codeAsInt("name");
^
where T is a type-variable:
T extends Object declared in class HashCodes
Note: Some messages have been simplified; recompile with -Xdiags:verbose to get full output
3 errors
Tool completed with exit code 1
Any help would be appreciated as well as any approach that would be better then the approach I am using.
The error message
The error you got comes from calling a generic non static method from a static context, i guess. To make your code compile, but not directly work ;), you should change your calls in the main method to something like this:
new HashCode<Integer>().codeAsInt(2);
new HashCode<Character>().codeAsInt('C');
new HashCode<String>().codeAsInt("name");
So in your case it is required to instantiate the class and specifiy the type of T when creating the object. It seems you want to let the compiler infer the type by the arguments.
Here Oracle gives hints about java's type inference mechanics, which would you allow to use your class as follows.
HashCode<Integer> i = new HashCode<>().codeAsInt(2);
HashCode<Character> c = new HashCode<>().codeAsInt('C');
HashCode<String> s = new HashCode<>().codeAsInt("name");
i.codeAsInt(2);
c.codeAsInt('C');
s.codeAsInt("name");
Thus you could leave out the type information on the instantiation, but not on the declaration. I am not 100% sure if it is possible with java 1.8's type inference to write this in an even cleaner way.
A possible solution
Since java 1.7 and earlier it is possible to use java's type literals to achieve something similar. But then you'll have to pas that literal explicitly always to the method. Your whole class doesn't explicitly requires to be generic, if you want to select the type on every individual method call, it is sufficient to make a single method generic instead.
public class SomeClass {
public static <T> int codeAsInt(Class<T> type, T value) {
// here you can use the type object
if(type.isInstance(value)) {
// ...
}
public static void main(String... args) {
codeAsInt(Integer.class, 2);
codeAsInt(Character.class, 'C');
codeAsInt(String.class, "name");
}
}
The Class type gives you an object for the type T at runtime, because that isn't usually available anymore after compilation. With the type object you can do casting to T at runtime. There is some cast method, which takes an Object and returns a T. Furthermore you can check with the isInstance method if an object is of type T. However choosing the described approach makes the type check obsolete, because the compiler will inform you if you accidentally pass something to the method which is not of type T.
I am still not sure what you are exactly looking for, but I hope this helps. If you just want to cast an object of any type dynamically into a T just use the type literals cast method directly.
Just written blindly, no warranties for typos or compile errors ;)
I think you're talking about serialization
Here is a class using reflection, you'll have to deal with the throwed exception and manage them :
public class Test {
public static void main(String[] args) { // Manage command line argument
try
{
System.out.println(getHashCode("java.lang.String", "10")); // For simplicity
}
catch(Exception e)
{
System.err.println("There's a problem with this test ! Here is the details :\n"+e.getMessage());
}
}
public static int getHashCode(String className, String value) throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{
Class<?> clazz = Class.forName(className);
Constructor<?> c = clazz.getConstructor(String.class);
Object o = c.newInstance(value);
return o.hashCode();
}
}
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.
I'm having a problem with a generic method since i upgrade my java version to 8.
The call is the following:
Operator o;
Comparable a;
Comparable<?> b;
boolean match = o.evaluate(a, b)
and the method
public enum Operator{
public <T extends Comparable<T>> boolean evaluate(T value1, T value2) {
if (value1 == null && value2 != null) {
return false;
}
switch (this) {
//some code here
}
}
}
And the exception is:
The method evaluate(T, T) in the type Operator is not applicable for the arguments (Comparable, Comparable)
Thanks in advance!
evaluate expects to arguments that are known to be the same type, which can be compared to itself, but that's just not the case here.
Your generic method imposes two conditions:
That its return type extends the Comparable interface with respect to itself.
That its two parameters (and return type) are all of the same type.
However, you are passing two parameters which are not, strictly speaking, the same type. One of them is a raw Comparable object (whose base type is Object), and the other is a Comparable which is not raw, but has an unknown base type.
In reality you could assign an Integer to b, and that is not strictly compatible with a raw Comparable.
Using a.compareTo(b) would not result in a compile-time error, because a is a raw Comparable that will accept any Comparable object but will consider it to be Comparable and b can be cast to Object. That's how it works with raw types. You get only a warning, and a runtime error if the two objects do not match.
However, using b.compareTo(a) would result in a compile-time error, because b is known to have a base type, it's just not known what it is at the moment. So it's not known whether a Comparable<Object> can or cannot be cast to it.
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");
}
}
}
public static String instanceTest(Comparable cmp) {
if (cmp == null) {
return "null";
}
else return cmp.toString();
}
public static void main(String[] args) {
Comparable comp = null;
//comp = new FileReader(""); cannot be converted
System.out.println(null instanceof Comparable);
System.out.println(comp instanceof Comparable);
System.out.println(instanceTest(null));
}
This example confuses me. The instanceTest method accepts only Comparable.null is not an object and cannot be instance of Comparable.But passing null to instanceTest is compiled and even can be executed.Why? Even more confusing - I can create a Comparable object comp that points to null. The instanceof fails with the comp instanceof Comparable but I cannot convert the object to another type that is not Comparable.Obviously instanceof checks the object but not the reference? But the reference also contains some information about it's type ? So is there a way to check the type of the reference??
The Java Language Specification states
The null reference can always undergo a widening reference conversion
to any reference type.
where widening reference conversion is defined as
A widening reference conversion exists from any reference type S to
any reference type T, provided S is a subtype (§4.10) of T.
So although null isn't an instance of type Comparable (it's not an instance at all, it's a reference), it can be used in the place of a reference of type Comparable (or any other reference type).
So is there a way to check the type of the reference??
You are already doing it with == and instanceof.