Luigi R. Viggiano Luigi R. Viggiano - 5 months ago 13
Java Question

How to convert from String to a primitive type or standard java Wrapper types

I have a

java.lang.reflect.InvocationHandler
and I need to implement the method invoke()

I have a value of type
java.lang.String
from my elaboration and I need to convert this value to the appropriate returnType expected by the method (it can be a primitive like int, boolean, double or wrapper classes like Boolean, Integer, Double, Float, etc).

Example:

public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
String computedValue = compute(...);
return convert(method.getReturnType(), computedValue);
}

private Object convert(Class<?> returnType, String stringValue) {
return ...; // what's the simplest way?
}


I am not expecting to simply implement an automatic conversion between complex objects, but I expect a simple way to convert from String to the standard java types.

I've seen (too) many times stuff like this, but it doesn't seem appropriate to me:

public static Object toObject( Class clazz, String value ) {
if( Boolean.class.isAssignableFrom( clazz ) ) return Boolean.parseBoolean( value );
if( Byte.class.isAssignableFrom( clazz ) ) return Byte.parseByte( value );
if( Short.class.isAssignableFrom( clazz ) ) return Short.parseShort( value );
if( Integer.class.isAssignableFrom( clazz ) ) return Integer.parseInteger( value );
if( Long.class.isAssignableFrom( clazz ) ) return Long.parseLong( value );
if( Float.class.isAssignableFrom( clazz ) ) return Float.parseFloat( value );
if( Double.class.isAssignableFrom( clazz ) ) return Double.parseDouble( value );
return value;
}


and the above is not even the worse one I saw, so far :)

Does anybody have a secret trick here?

Answer

As far as I'm aware, there is no real alternative to the version you presented. You can simplify it a bit (since the wrapper types are all final), but you essentially need to use if or switch or hashing to switch on the class.

My advice is to code it like the above. Ugly code is only a problem per se if you have to look at it. So put it inside a utility method and don't look at it again.


FWIW - this is how I'd simplify the method:

public static Object toObject( Class clazz, String value ) {
    if( Boolean.class == clazz ) return Boolean.parseBoolean( value );
    if( Byte.class == clazz ) return Byte.parseByte( value );
    if( Short.class == clazz ) return Short.parseShort( value );
    if( Integer.class == clazz ) return Integer.parseInt( value );
    if( Long.class == clazz ) return Long.parseLong( value );
    if( Float.class == clazz ) return Float.parseFloat( value );
    if( Double.class == clazz ) return Double.parseDouble( value );
    return value;
}

This is simpler and more efficient. And it is equivalent to the original version because the classes are all final and because the specs state that equality for Class objects is object identity.

I make no claim that this is less ugly ... but "beauty" is not a useful measure of code quality, because it is subjective and because it doesn't tell you whether the code is easy to understand and / or maintain.

UPDATE

To support primitive types as well, add the corresponding classes to the if conditions; e.g.

    if (Boolean.class == clazz || Boolean.TYPE == clazz) {
        return Boolean.parseBoolean(value);
    }

It may now be getting to the point where doing a String switch on the type's name is more efficient, though there are some slightly knotty issues of type identity that need to be thought through. (In theory, you can have multiple types with the same full name that have been loaded by different classloaders. I think you'd need to "play fast and loose" in a classloader to do that with the primitive wrapper classes ... but I think it might still be possible.)

Update

It is not Integer.parseInteger() it is Integer.parseInt()