Victor Wong
Victor Wong

Reputation: 2486

Generic Casting on primitive value causing ClassCastException

I have a method below doing casting on a String according to the given type, assuming the String given must be correct.

private static <T> T parsePrimitive(final Class<T> primitiveType, final String primitiveValue) {
    if (primitiveType.equals(int.class) || primitiveType.equals(Integer.class)) {
        return primitiveType.cast(Integer.parseInt(primitiveValue));
    }
    /*
    ...
    for the rest of the primitive type
    ...
    */
}

However, when I call parsePrimitive(int.class, "10");,

primitiveType.cast(Integer.parseInt(primitiveValue));

This causes ClassCastException, any idea for this?

p.s. In fact, when I use Object as the return type, and no casting in before return, it works fine outside the method, but this is not generic enough I think.

Thanks in advance for any help.

Upvotes: 1

Views: 1750

Answers (2)

ɲeuroburɳ
ɲeuroburɳ

Reputation: 7120

int.class is a VM internal class and not the same thing as Integer.class. Here's a small snippet of code to show the differences between int.class and Integer.class.

import java.lang.reflect.Modifier;
import java.util.Arrays;

public class Main {
    public static void main(String[] args) {
        dump(int.class);
        System.out.println("---");
        dump(Integer.class);
    }

    private static void dump(Class<?> c) {
        System.out.printf(
            "Name: %s%n" +
            "Superclass: %s%n" +
            "Interfaces: %s%n" +
            "Modifiers: %s%n",
            c.getName(),
            c.getSuperclass() == null ? "null" : c.getSuperclass().getName(),
            Arrays.asList(c.getInterfaces()),
            Modifier.toString(c.getModifiers()));
    }
}

Outputs:

Name: int
Superclass: null
Interfaces: []
Modifiers: public abstract final
---
Name: java.lang.Integer
Superclass: java.lang.Number
Interfaces: [interface java.lang.Comparable]
Modifiers: public final

Upvotes: 0

Perception
Perception

Reputation: 80603

You are mixing up autoboxing and casting. The java compiler will generate bytecode to box and unbox your primitives to objects and vice versa, but the same does not apply to types.

  • Boxing/Unboxing = variables
  • Casting = types

In your particular case, int.class and Integer.class are not assignable from each other.

Class<?> intClazz = int.class;
Class<?> integerClazz = Integer.class;
System.out.println(intClazz);
System.out.println(integerClazz);
System.out.println(integerClazz.isAssignableFrom(intClazz));

Output:

int
class java.lang.Integer
false

With the amount of specialized checks you would have to put in your logic I am not sure its worth trying to come up with a generic method for parsing a String into a primitive value.

Upvotes: 3

Related Questions