Search code examples
javareflectionprimitiveautoboxing

How to commonly address primitives and objects


Here is a utility method I have:

public static Class<?>[] getTypes(Object[] objects){
    Class<?>[] types = new Class<?>[objects.length];

    for (int i = 0; i < objects.length; i++) {
        types[i] = objects[i].getClass();
    }

    return types;
}

And here is a test case that fails:

@Test
public void getTypesTest() {
    Object[] objects = {"String", new StringBuilder(), new Integer(5), 5};

    Class<?>[] classes = ReflectionUtils.getTypes(objects);
    assertTrue(classes[0].equals(String.class));
    assertTrue(classes[1].equals(StringBuilder.class));
    assertTrue(classes[2].equals(Integer.class));
    assertTrue(classes[3].equals(int.class)); // Fails here
}

I realize that when I pass 5 within Object[], this is Boxed to new Integer(5).

How can I get the behavior I am expecting?

Edit

What I am expecting: The assertion that fails in my test will pass. What should I do with the method under test to achieve that?:


Solution

  • You cannot treat a primitive as an object as this is what defines a primitive as different to an object. By having an array of objects, you are ensuring everything in it is an object, not a primitive.


    An int is not an object so you can't put it in an Object[] so the compiler will generate code to auto-box you value of 5. i.e. it calls Integer.valueOf(5) which is more efficient than new Integer(5) but is still an object.

    You can't call .equals() on a primitive so the fact this compiles tells you its not.

    BTW you can use int.class to get the class of int.

    How can I get the behavior I am expecting?

    Can you say exactly what you are expecting in English?


    For those interested, the code for Integer.valueOf(int) in Java 6 and 7

    public static Integer valueOf(int i) {
        assert IntegerCache.high >= 127;
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }