Tuesday, March 1, 2011

Creating (boxed) primitive instance when the class is known

I need a method that returns an instance of the supplied class type. Let's assume that the supplied types are limited to such that an "empty" instance of them can be created. For instance, supplying String.class would return an empty String, supplying an Integer.class would return an Integer whose initial value is zero, and so on. But how do I create (boxed) primitive types on the fly? Like this?

public Object newInstance(Class<?> type) {
    if (!type.isPrimitive()) {
        return type.newInstance(); // plus appropriate exception handling
    } else {
        // Now what?
        if (type.equals(Integer.class) || type.equals(int.class)) {
            return new Integer(0);
        }
        if (type.equals(Long.class) // etc.... 
    }
}

Is the only solution to iterate through all the possible primitive types, or is there a more straightforward solution? Note that both

int.class.newInstance()

and

Integer.class.newInstance()

throw an InstantiationException (because they don't have nullary constructors).

From stackoverflow
  • I suspect the simplest way is to have a map:

    private final static Map<Class<?>, Object> defaultValues = 
        new HashMap<Class<?>, Object>();
    static
    {
        defaultValues.put(String.class, "");
        defaultValues.put(Integer.class, 0);
        defaultValues.put(int.class, 0);
        defaultValues.put(Long.class, 0L);
        defaultValues.put(long.class, 0L);
        defaultValues.put(Character.class, '\0');
        defaultValues.put(char.class, '\0');
        // etc
    }
    

    Fortunately all these types are immutable, so it's okay to return a reference to the same object on each call for the same type.

    Jon Skeet : @Joonas: Have another look now :)
    Joonas Pulakka : Thanks! That might work :)
    Tom Hawtin - tackline : I think I'd go for an ?: chain. `type==long.class ? (Long)0L :`, etc.
    Jon Skeet : @Tom: Any particular reason? Performance? Readability? Once the map is constructed, the method code is basically just the lookup, so that's nice and readable. I'm generally fine with chained conditionals, but in this case I'm not sure I see an advantage. Not much *disadvantage* either, mind you.
    CPerkins : @Jon: how would you want to change your solution if the OP needed to include mutable classes, like StringBuilder?
    Jon Skeet : @CPerkins: At that point I'd probably change strategy, possibly to something like Tom's suggestion. My answer was aimed at the exact question asked :)
    Joonas Pulakka : I guess the rest of the classes (other than primitive) can be created with the newInstance() method as long as they have a nullary constructor. So I just need to check whether the supplied class type is primitive or not, and then return an instance created with Jon's map system or with newInstance().
    Joonas Pulakka : Err, except that for instance Integers are not primitive, so I must check against all wrapper classes too!

0 comments:

Post a Comment