web-dev-qa-db-ja.com

Javaで数値書式例外を回避するにはどうすればよいですか?

私の日々のWebアプリケーション開発では、ユーザーからいくつかの入力を行う必要がある多くのインスタンスがあります。

次に、この番号の入力を、アプリケーションのサービス層またはDAO層に渡します。

その数(整数または浮動小数点数)以降のある段階で、次のコードスニペットに示すように、整数に変換する必要があります。

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

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

ここで上記のケースでは、入力がnullでないか、入力がない(空白)か、または非数値入力の可能性があるかどうかを確認する必要があります。何とか、テストなど。

そのような状況に対処する最善の方法は何ですか?

14
ashishjmeshram

例外をキャッチして、適切な例外処理を行うだけです。

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

いつものように、ジャカルタコモンズには少なくとも答えの一部があります。

NumberUtils.isNumber()

これは、指定された文字列が数値であるかどうかをほとんどチェックするために使用できます。文字列が数字ではない場合の対処方法を選択する必要があります...

4
Guillaume

Javaの最近のバージョンでの例外は、回避を重要にするほど高価ではありません。プロセスで早い段階で(つまり、直後に)ユーザーが入力した)、プロセスの後半で問題が発生することはありません(とにかく正しいタイプになるためです)。

例外は、以前よりもはるかに高価になりました。例外が実際に問題を引き起こしていることがわかるまで、パフォーマンスを最適化しないでください(ここではそうしません)。

2
Joseph Ottinger

2つのことを行うことをお勧めします。

  • サーブレットに渡す前に、クライアント側で入力を検証します
  • tobiaskが述べたように、例外をキャッチし、ユーザーフロントエンド内にエラーメッセージを表示します。このケースは通常は発生しませんが、クライアントを信頼することはありません。 ;-)
1
Puce
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;
    }

}
1
user3162218

1つの可能性:例外をキャッチし、ユーザーフロントエンド内にエラーメッセージを表示します。

編集:GUI内のフィールドにリスナーを追加し、そこのユーザー入力も確認してください。このソリューションでは、例外ケースは非常にまれです...

1
Tobias

Apache Commons Langのメソッドに関するドキュメント( from here ):

文字列が有効なJava number。

有効な数字には、0x修飾子でマークされた16進数、科学表記法、および型修飾子でマークされた数字(例:123L)が含まれます。

Nullおよび空の文字列はfalseを返します。

パラメータ:

`str` - the `String` to check

戻り値:

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

[コードはApacheライセンスのバージョン2の下にあります]

1
A T

Prizeを10進形式に変換してみてください...

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

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

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
}
0
nairbv