Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 221
Luigi R. Viggiano Avatar asked Dec 19 '12 00:12

Luigi R. Viggiano


People also ask

How do you convert a string to primitive?

For converting a primitive type value to a string in Java, use the valueOf() method.

How do you convert a wrapper to primitive?

Converting an object of a wrapper type (Integer) to its corresponding primitive (int) value is called unboxing. The Java compiler applies unboxing when an object of a wrapper class is: Passed as a parameter to a method that expects a value of the corresponding primitive type.

How do you convert a string to a wrapper class?

We can use the Integer. parseInt() to get the corresponding primitive int value of a string or use Integer. valueOf() to get the corresponding value of Integer wrapper class. If the string is not an integer, NumberFormatException will be thrown.

Which method of the wrapper class is used to convert a string into primitive?

1. valueOf() method: We can use the valueOf() method to create a Wrapper object for a given primitive or String.


3 Answers

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.

Arguably, we should be using the <wrapper>.valueOf(String) methods which return the wrapper objects directly.

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

like image 78
Stephen C Avatar answered Oct 20 '22 04:10

Stephen C


I think I found something

import java.beans.PropertyEditor;
import java.beans.PropertyEditorManager;

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

private Object convert(Class<?> targetType, String text) {
    PropertyEditor editor = PropertyEditorManager.findEditor(targetType);
    editor.setAsText(text);
    return editor.getValue();
}

I think that those 3 lines of code are better than the multiple ifs, and I avoided to add external library dependencies, since java.beans package is inside the Java standard libraries (javadocs: PropertyEditorManager).

I find it quite acceptable; my only perplexity is that PropertyEditor is contained in java.beans package and I would have preferred something available in java.util or java.lang.reflect package, since this code has nothing to do with java.beans actually.

The code above has also the advantage that you can register additional PropertyEditor instances to translate complex objects, btw. That's not a bad thing to have though.

I think it's better than a list of ifs, in beauty, but also in quality.

like image 31
Luigi R. Viggiano Avatar answered Oct 20 '22 05:10

Luigi R. Viggiano


Probably org.apache.commons.beanutils.ConvertUtils can help?

import org.apache.commons.beanutils.ConvertUtils;
// ...
final Object v = ConvertUtils.convert("42", Integer.class);
like image 44
Borv Avatar answered Oct 20 '22 04:10

Borv