protected static Number stringToNumber ( final String val ) throws NumberFormatException { char initial = val . charAt ( 0 ) ; if ( ( initial >= ' ' && initial <= ' ' ) || initial == ' ' ) { // decimal representation if ( isDecimalNotation ( val ) ) { // quick dirty way to see if we need a BigDecimal instead of a Double // this only handles some cases of overflow or underflow if ( val . length ( ) > 14 ) { return new BigDecimal ( val ) ; } final Double d = Double . valueOf ( val ) ; if ( d . isInfinite ( ) || d . isNaN ( ) ) { // if we can't parse it as a double, go up to BigDecimal // this is probably due to underflow like 4.32e-678 // or overflow like 4.65e5324. The size of the string is small // but can't be held in a Double. return new BigDecimal ( val ) ; } return d ; } // integer representation. // This will narrow any values to the smallest reasonable Object representation // (Integer, Long, or BigInteger) // string version // The compare string length method reduces GC, // but leads to smaller integers being placed in larger wrappers even though not // needed. i.e. 1,000,000,000 -> Long even though it's an Integer // 1,000,000,000,000,000,000 -> BigInteger even though it's a Long //if(val.length()<=9){ // return Integer.valueOf(val); //} //if(val.length()<=18){ // return Long.valueOf(val); //} //return new BigInteger(val); // BigInteger version: We use a similar bitLenth compare as // BigInteger#intValueExact uses. Increases GC, but objects hold // only what they need. i.e. Less runtime overhead if the value is // long lived. Which is the better tradeoff? This is closer to what's // in stringToValue. BigInteger bi = new BigInteger ( val ) ; if ( bi . bitLength ( ) <= 31 ) { return Integer . valueOf ( bi . intValue ( ) ) ; } if ( bi . bitLength ( ) <= 63 ) { return Long . valueOf ( bi . longValue ( ) ) ; } return bi ; } throw new NumberFormatException ( "val [" + val + "] is not a valid number." ) ; }
Converts a string to a number using the narrowest possible type . Possible returns for this function are BigDecimal Double BigInteger Long and Integer . When a Double is returned it should always be a valid Double and not NaN or + - infinity .