如何避免java中的数字格式异常?

时间:2011-03-31 12:03:44

标签: java numberformatexception

在我的日常Web应用程序开发中,有许多情况我们需要从用户那里获取一些数字输入。

然后将此数字输入传递给应用程序的服务或DAO层。

在某个阶段,因为它是一个数字(整数或浮点数),我们需要将它转换为Integer,如下面的代码片段所示。

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

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

在上面的情况中,我必须检查输入是否为空或是否没有输入(空白),或者有时可能存在非数字输入,例如等等,等等。

处理此类情况的最佳方法是什么?

13 个答案:

答案 0 :(得分:27)

抓住你的异常并进行适当的异常处理:

if (cost !=null && !"".equals(cost) ){
        try {
           Integer intCost = Integer.parseInt(cost);
           List<Book> books = bookService . findBooksCheaperThan(intCost);  
        } catch (NumberFormatException e) {
           System.out.println("This is not a number");
           System.out.println(e.getMessage());
        }
    }

答案 1 :(得分:4)

与往常一样,雅加达下议院至少有部分答案:

NumberUtils.isNumber()

这可用于检查给定String是否为数字。你仍然必须选择做什么,以防你的字符串不是一个数字...

答案 2 :(得分:2)

Java的最新版本中的异常并不足以使其避免变得非常重要。使用人们建议的try / catch块;如果你在这个过程的早期就捕获了异常(即,在用户输入之后),那么你将不会在此过程中遇到问题(因为无论如何它都是正确的类型)。

过去的例外情况比现在贵很多;在知道异常实际导致问题之前不要优化性能(在这里它们不会。)

答案 3 :(得分:1)

一个可能性:捕获异常并在用户前端中显示错误消息。

编辑:在gui中的字段中添加一个监听器,并检查那里的用户输入,使用这个解决方案的例外情况应该非常罕见......

答案 4 :(得分:1)

我建议做两件事:

  • 在将输入传递给Servlet之前验证客户端的输入
  • 捕获异常并在Tobiask提到的用户前端中显示错误消息。这种情况通常不会发生,但永远不要相信您的客户。 ; - )

答案 5 :(得分:1)

Apache Commons Lang(from here)方法的文档:

  

检查String是否为有效的Java编号。

     

有效数字包括标有0x限定符的十六进制,科学记数法和用类型限定符标记的数字(例如123L)。

     

Null并且空字符串将返回false

     

<强>参数:

`str` - the `String` to check
     

<强>返回:

`true` if the string is a correctly formatted number
来自java.org.apache.commons.lang3.math.NumberUtils

isNumber

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;
}

[代码在Apache许可证的第2版下]

答案 6 :(得分:1)

public class Main {
    public static void main(String[] args) {

        String number;

        while(true){

            try{
                number = JOptionPane.showInputDialog(null);

                if( Main.isNumber(number) )
                    break;

            }catch(NumberFormatException e){
                System.out.println(e.getMessage());
            }

        }

        System.out.println("Your number is " + number);

    }

    public static boolean isNumber(Object o){
        boolean isNumber = true;

        for( byte b : o.toString().getBytes() ){
            char c = (char)b;
            if(!Character.isDigit(c))
                isNumber = false;
        }

        return isNumber;
    }

}

答案 7 :(得分:0)

确定字符串是Int还是Float并以更长的格式表示。

<强>整数

 String  cost=Long.MAX_VALUE+"";
  if (isNumeric (cost))    // returns false for non numeric
  {  
      BigInteger bi  = new BigInteger(cost);

  }

public static boolean isNumeric(String str) 
{ 
  NumberFormat formatter = NumberFormat.getInstance(); 
  ParsePosition pos = new ParsePosition(0); 
  formatter.parse(str, pos); 
  return str.length() == pos.getIndex(); 
} 

答案 8 :(得分:0)

使用Scanner类可以避免令人不快的try / catch或regex:

String input = "123";
Scanner sc = new Scanner(input);
if (sc.hasNextInt())
    System.out.println("an int: " + sc.nextInt());
else {
    //handle the bad input
}

答案 9 :(得分:0)

尝试将奖品转换为十进制格式......

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());
            }
        }

}
}

答案 10 :(得分:-1)

我不知道有关以下内容的运行时缺点,但您可以在字符串上运行regexp匹配,以确保它在尝试解析之前是一个数字,因此

cost.matches("-?\\d+\\.?\\d+")

表示浮动

cost.matches("-?\\d+")

表示整数

修改

请注意@Voo关于max int的评论

答案 11 :(得分:-1)

在Java中,遗憾的是你无法避免使用parseInt函数并且只是捕获异常。那么理论上你可以编写自己的解析器来检查它是否是一个数字,但是你根本就不需要parseInt了。

正则表达式方法存在问题,因为没有什么能阻止某人包含数字&gt; INTEGER.MAX_VALUE将通过正则表达式测试但仍然失败。

答案 12 :(得分:-1)

这取决于您的环境。例如,JSF将负担手动检查和转换字符串&lt; - &gt;的负担。来自您的数字,Bean验证是另一种选择。

您可以在您提供的代码段中立即做什么:

  1. 提取方法getAsInt(String param),其中包含:
  2. 使用String.isEmpty()(自Java 6起),
  3. 环绕try / catch
  4. 如果您碰巧写了很多像这样的代码,那么肯定会想到

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

    (这将是基于拦截器的。)

    最后但并非最不重要:保存工作并尝试切换到支持这些常见任务的框架......