Is there a better practice to convert any input number string (int, double, etc) to it's respective Wrapper object/primitive type in java?

Using valueOf() or parseXXX() methods it can achieved. but I should be knowing the underlying string format before selecting the appropriate type.

What I am doing is parsing number string to long, using the NumberUtils from commons-lang.jar as follows:

long longValue= (long) NumberUtils.toLong(numberString);

but the problem is If the numberString has a double value, then it fails to parse to number and will return 0.0 as parsed value. Only the following statement works fine for double values :

Long longValue = (long) NumberUtils.toDouble(numberString);

Is there a generic way of doing this? also I don't care about the digits after the decimal.

Thanks for reading.

Update

This looks elegant solution to me, suggested by @Thomas :

NumberFormat numberFormat = NumberFormat.getNumberInstance(); long longValue = numberFormat.parse(targetFieldValue).longValue();

as the parse() method returns Long or Double wrapper object, It can be checked and assigned accordingly for generic use. Only catch here is that the parse() could throw ParseException, so need to be handled according to the requirement.

I've used this to solve my problem, but curious to know about any other solutions!!

2

There are 2 answers

3
mystarrocks On
import static org.apache.commons.lang3.math.NumberUtils.isDigits;
import static org.apache.commons.lang3.math.NumberUtils.toDouble;
import static org.apache.commons.lang3.math.NumberUtils.toLong;    

public static void main(String[] args) {
  String numberString = "-23.56";
  long longNumber = (isDigits(numberString) ? toLong(numberString) : (long) toDouble(numberString));
  System.out.println(longNumber);
}

The cast here assumes that you are happy with truncating the decimal, regardless of the sign (the presence of - in the string would mean isDigits returns false). If not, do the appropriate rounding.

If you fear the string might contain alphabets, use the createLong variant that would throw a NumberFormatException instead of defaulting to 0.

0
Bálint Kriván On

I've needed a more sophisticated approach, since I wanted "1.0" serialized as a double, not as an int so I implemented my own solution and I leave it for the future:

public Number deserialize(CharSequence text) {
    Preconditions.checkArgument(Objects.requireNonNull(text).length() > 0);

    switch (text.charAt(text.length() - 1)) {
        case 'L':
            return Long.parseLong(text.subSequence(0, text.length() - 1).toString());
        case 'f':
            return Float.parseFloat(text.toString());
        default:
            Number number = Ints.tryParse(text.toString());
            if (number == null) {
                number = Doubles.tryParse(text.toString());
            }
            if (number == null) {
                throw new IllegalArgumentException("Unsupported number: " + text);
            }
            return number;
    }
}

The format follows the way as in Java, so integers without 'L' at the end will be converted to Integers otherwise Longs. Decimal numbers will be converted into Doubles unless they end with 'f' in that case they will be converted to Floats. The following tests are passing:

    EXPECT.that(deserialize("1")).isEqualTo(1);
    EXPECT.that(deserialize("5L")).isEqualTo(5L);
    EXPECT.that(deserialize("2.0")).isEqualTo(2.0);
    EXPECT.that(deserialize("4.0f")).isEqualTo(4.0f);