How to avoid Number Format Exception in java? [dup

2019-01-17 16:41发布

This question already has an answer here:

In my day to day web application development there are many instances where we need to take some number inputs from the user.

Then pass on this number input to may be service or DAO layer of the application.

At some stage since its a number (integer or float), we need to convert it into Integer as shown in the following code snippet.

String cost = request.getParameter("cost");

if (cost !=null && !"".equals(cost) ){
    Integer intCost = Integer.parseInt(cost);
    List<Book> books = bookService . findBooksCheaperThan(intCost);  
}

Here in the above case I have to check if the input is not null or if there is no input (blank) or sometimes there is a possibility of a non number inputs e.g. blah, test etc.

What is the best possible way of handling such situations?

13条回答
ゆ 、 Hurt°
2楼-- · 2019-01-17 17:25

As always, the Jakarta Commons have at least part of the answer :

NumberUtils.isNumber()

This can be used to check most whether a given String is a number. You still have to choose what to do in case your String isnt a number ...

查看更多
Explosion°爆炸
3楼-- · 2019-01-17 17:26

That depends on your environment. JSF for example would take the burden of manually checking and converting Strings <-> Numbers from you, Bean Validation is another option.

What you can do immediately in the snippet you provide:

  1. Extract method getAsInt(String param), in it:
  2. Use String.isEmpty() (Since Java 6),
  3. surround with try / catch

What you should definitely think about if you happen to write a lot of code like this:

public void myBusinessMethod(@ValidNumber String numberInput) {
// ...    
}

(This would be interceptor-based).

Last but not least: Save the work and try to switch to a framework which gives you support for these common tasks...

查看更多
太酷不给撩
4楼-- · 2019-01-17 17:29

Try to convert Prize into decimal format...

import java.math.BigDecimal;
import java.math.RoundingMode;

public class Bigdecimal {
    public static boolean isEmpty (String st) {
        return st == null || st.length() < 1; 
    }
    public static BigDecimal bigDecimalFormat(String Preis){        
        //MathContext   mi = new MathContext(2);
        BigDecimal bd = new BigDecimal(0.00);

                         bd = new BigDecimal(Preis);


            return bd.setScale(2, RoundingMode.HALF_UP);

        }
    public static void main(String[] args) {
        String cost = "12.12";
        if (!isEmpty(cost) ){
            try {
               BigDecimal intCost = bigDecimalFormat(cost);
               System.out.println(intCost);
               List<Book> books = bookService.findBooksCheaperThan(intCost);  
            } catch (NumberFormatException e) {
               System.out.println("This is not a number");
               System.out.println(e.getMessage());
            }
        }

}
}
查看更多
贼婆χ
5楼-- · 2019-01-17 17:31

You can avoid the unpleasant looking try/catch or regex by using the Scanner class:

String input = "123";
Scanner sc = new Scanner(input);
if (sc.hasNextInt())
    System.out.println("an int: " + sc.nextInt());
else {
    //handle the bad input
}
查看更多
别忘想泡老子
6楼-- · 2019-01-17 17:33

one posibility: catch the exception and show an error message within the user frontend.

edit: add an listener to the field within the gui and check the user inputs there too, with this solution the exception case should be very rare...

查看更多
SAY GOODBYE
7楼-- · 2019-01-17 17:34

Documentation for the method from the Apache Commons Lang (from here):

Checks whether the String a valid Java number.

Valid numbers include hexadecimal marked with the 0x qualifier, scientific notation and numbers marked with a type qualifier (e.g. 123L).

Null and empty String will return false.

Parameters:

`str` - the `String` to check

Returns:

`true` if the string is a correctly formatted number

isNumber from java.org.apache.commons.lang3.math.NumberUtils:

public static boolean isNumber(final String str) {
    if (StringUtils.isEmpty(str)) {
        return false;
    }
    final char[] chars = str.toCharArray();
    int sz = chars.length;
    boolean hasExp = false;
    boolean hasDecPoint = false;
    boolean allowSigns = false;
    boolean foundDigit = false;
    // deal with any possible sign up front
    final int start = (chars[0] == '-') ? 1 : 0;
    if (sz > start + 1 && chars[start] == '0' && chars[start + 1] == 'x') {
        int i = start + 2;
        if (i == sz) {
            return false; // str == "0x"
        }
        // checking hex (it can't be anything else)
        for (; i < chars.length; i++) {
            if ((chars[i] < '0' || chars[i] > '9')
                && (chars[i] < 'a' || chars[i] > 'f')
                && (chars[i] < 'A' || chars[i] > 'F')) {
                return false;
            }
        }
        return true;
    }
    sz--; // don't want to loop to the last char, check it afterwords
          // for type qualifiers
    int i = start;
    // loop to the next to last char or to the last char if we need another digit to
    // make a valid number (e.g. chars[0..5] = "1234E")
    while (i < sz || (i < sz + 1 && allowSigns && !foundDigit)) {
        if (chars[i] >= '0' && chars[i] <= '9') {
            foundDigit = true;
            allowSigns = false;

        } else if (chars[i] == '.') {
            if (hasDecPoint || hasExp) {
                // two decimal points or dec in exponent   
                return false;
            }
            hasDecPoint = true;
        } else if (chars[i] == 'e' || chars[i] == 'E') {
            // we've already taken care of hex.
            if (hasExp) {
                // two E's
                return false;
            }
            if (!foundDigit) {
                return false;
            }
            hasExp = true;
            allowSigns = true;
        } else if (chars[i] == '+' || chars[i] == '-') {
            if (!allowSigns) {
                return false;
            }
            allowSigns = false;
            foundDigit = false; // we need a digit after the E
        } else {
            return false;
        }
        i++;
    }
    if (i < chars.length) {
        if (chars[i] >= '0' && chars[i] <= '9') {
            // no type qualifier, OK
            return true;
        }
        if (chars[i] == 'e' || chars[i] == 'E') {
            // can't have an E at the last byte
            return false;
        }
        if (chars[i] == '.') {
            if (hasDecPoint || hasExp) {
                // two decimal points or dec in exponent
                return false;
            }
            // single trailing decimal point after non-exponent is ok
            return foundDigit;
        }
        if (!allowSigns
            && (chars[i] == 'd'
                || chars[i] == 'D'
                || chars[i] == 'f'
                || chars[i] == 'F')) {
            return foundDigit;
        }
        if (chars[i] == 'l'
            || chars[i] == 'L') {
            // not allowing L with an exponent or decimal point
            return foundDigit && !hasExp && !hasDecPoint;
        }
        // last character is illegal
        return false;
    }
    // allowSigns is true iff the val ends in 'E'
    // found digit it to make sure weird stuff like '.' and '1E-' doesn't pass
    return !allowSigns && foundDigit;
}

[code is under version 2 of the Apache License]

查看更多
登录 后发表回答