2

I am looking for a simple, concise way to convert a given Number object to an object of a given numeric type.

  • Loss of precision due to narrowing conversions is fine
  • I prefer not to go through strings.

I need something like:

private static Number convert(Number num, Class<? extends Number> targetType)

Is there a way to do it without checking all the combinations of types?

1
  • 1
    Regardless of the implementation, I'd at least rewrite the method signature as public static <N extends Number> N convert(Number number, Class<N> type). This would return exactly the specified number type, which can have advantages in postprocessing. Commented Sep 19, 2010 at 18:04

3 Answers 3

4

I think the clearest way is to use brute force:

private static Number convert(Number num, Class<? extends Number> targetType) {
    Number result = null;
    if (Byte.class.equals(targetType)) {
        result = Byte.valueOf(num.byteValue());
    } else if (Short.class.equals(targetType)) {
        result = Short.valueOf(num.shortValue());
    } else if (...) {
         ...
    } else {
        throw new IllegalArgumentException("targetType is not a Number");
    }
    return result;
}

You might use reflection, but I find that more hackish.

Sign up to request clarification or add additional context in comments.

2 Comments

+1 to avoid reflection. Reflection will slow down the application... I would do it exactly the same.
Nice. I will use this solution. With the static methods of these types there is no need to actually check all type combinations. Thanks!
4

You can use something like:

String simpleName = targetType.getSimpleName().toLowerCase();
if (simpleName.equals("integer")) {
   simpleName = "int";
}
Method m = number.getClass().getMethod(simpleName + "Value");
return (Number) m.invoke(number);

This relies on the fact that Number has methods like longValue(), floatValue(), etc.

As for BigInteger or AtomicInteger - you can use their constructor reflectively, which accepts one argument - the primitive type.

2 Comments

+1. Would need to check that the types AtomicInteger, AtomicLong, BigDecimal, BigInteger, aren't passed in as targetType as they don't have a xxxValue() method on Number.
@Noel M: I don't need to handle these types. However, now I realize that performance IS important. I may consider the verbose solution instead... Anyway, I like the creativity of this solution :)
1

Perhaps converting via BigDecimal would work?

1 Comment

I suspect this requires either converting to String or using reflection, right?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.