5

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);

}
Amit Deshpande
  • 19,001
  • 4
  • 46
  • 72
  • enum `INT` is not allowed in java so I am trying to do it other way. But as you can see it is error prone if some once passes `int.class` it will raise an `ClassCastException`. And compiler does restrict `INT` but this way it does not. – Amit Deshpande Oct 21 '12 at 06:05

6 Answers6

3

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.

Rohit Jain
  • 209,639
  • 45
  • 409
  • 525
  • Found the cause added it as answer. – Amit Deshpande Oct 21 '12 at 06:18
  • 1
    @AmitD.. Yeah I just got that link also. But as you posted it. So no need to post. :) – Rohit Jain Oct 21 '12 at 06:19
  • I think little room for improvement in your last statement. It's a fact that all the classes in Java extend `Object`. There is no instanceof check against `Object`. – Bhesh Gurung Oct 21 '12 at 06:47
  • "So, the value of int.class is int." This doesn't make any sense at all. `int` is a type, not a value. The value of `int.class` is a `Class` object that represents the type `int`. – newacct Oct 21 '12 at 10:31
3

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;
Amit Deshpande
  • 19,001
  • 4
  • 46
  • 72
0

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:


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.

Community
  • 1
  • 1
Luiggi Mendoza
  • 85,076
  • 16
  • 154
  • 332
0

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;
}
Bhesh Gurung
  • 50,430
  • 22
  • 93
  • 142
0

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.

Arham
  • 2,072
  • 2
  • 18
  • 30
0

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.

Yogendra Singh
  • 33,927
  • 6
  • 63
  • 73