web-dev-qa-db-ja.com

予想されるときにNumberFormatExceptionを処理する適切な方法は何ですか?

私はStringintに解析する必要があり、NumberFormatExceptionの処理方法がわからないこの状況に遭遇しています。コンパイラーは、キャッチしなくても文句を言いませんが、この状況を適切に処理していることを確認したいだけです。

_private int getCurrentPieceAsInt() {
    int i = 0;
    try {
        i = Integer.parseInt(this.getCurrentPiece());
    } catch (NumberFormatException e) {
        i = 0;
    }
    return i;
}
_

このようにコードを単純化したいのですが。コンパイラーには問題はありませんが、スレッドはNumberFormatExceptionで終了します。

_private int getCurrentPieceAsInt() {
    int i = 0;
    i = Integer.parseInt(this.getCurrentPiece());
    return i;
}
_

Google CodeProは何らかの方法で例外をログに記録することを望んでおり、これはベストプラクティスであることに同意します。

_private int getCurrentPieceAsInt() {
    int i = 0;
    try {
        i = Integer.parseInt(this.getCurrentPiece());
    } catch (NumberFormatException e) {
        i = 0;
        e.printStackTrace();
    }
    return i;
}
_

現在のピースが数値でないか解析できない場合、このメソッドが_0_を返すようにしたいのですが。 NumberFormatExceptionを明示的にキャッチしない場合、変数iを割り当てませんか?または、Integer.parseInt()が返すデフォルト値はありますか?

一般的なスタイルでは、例外をキャッチした場合、どこかにログを記録する必要があります。ログに記録したくない。この例外がときどきスローされるのは正常な動作ですが、これも私には適していません。ただし、関数が見つからないため、Integer.parseInt()が例外をスローするかどうかがわかります。したがって、私の唯一の行動方針は、それを呼び出して例外をキャッチすることです。

parseIntの-​​ javadoc はあまり役に立ちません。

知りたい具体的な質問は次のとおりです。

  • 呼び出す前にInteger.parseInt()NumberFormatExceptionをスローするかどうかを通知するメソッドはありますか?それが起こることはないので、私はこれをログに記録しても問題ありません。
  • 単に例外をキャッチしない場合、変数は割り当てられませんか?次に、それが数値でない場合に必要な値に初期化し、例外をキャッチしません。
  • 例外を気にしないことを何らかの方法で明示的にマークする方法はありますか?これはAWTEvent.consume()に似たものになると思います。その場合は、Google CodeProがこれを「ログに記録されていない」と見なさないようにするためです。
18
Erick Robertson
  • Integer.parseInt()がそれを呼び出す前にNumberFormatExceptionをスローするかどうかを通知する、呼び出すことができるメソッドはありますか?それが起こることはないので、私はこれをログに記録しても問題ありません。

残念ながら、違います。少なくともコアにはありませんJava API。これを書くのは簡単ですが、以下のコードを変更するだけです。

  • 単に例外をキャッチしない場合、変数は割り当てられませんか?次に、それが数値でない場合に必要な値に初期化し、例外をキャッチしません。

例外をキャッチしない場合、スタックは、それを処理するキャッチブロックに到達するまで巻き戻されるか、完全に巻き戻されてスレッドを停止します。変数は実際には割り当てられませんが、これはまさにあなたが望むものではありません。

  • 例外を気にしないことを何らかの方法で明示的にマークする方法はありますか?これはAWTEvent.consume()に似たものになると思います。その場合は、Google CodeProがこれを「ログに記録されていない」と見なさないようにするためです。

この特定の警告を無視するようにCodeProに指示する方法があるかもしれません。確かにFindBugsやCheckstyleなどのツールを使用すると、特定の場所で警告をオフにすることができます。 (編集:@Andyはこれを行う方法を指摘しました。)

あなたが欲しいのは、@ davebによって言及されたCommons langパッケージのようなものだと思います。そのような関数を書くのはとても簡単です:

int parseWithDefault(String s, int def) {
    try {
        return Integer.parseInt(s);
    }
    catch (NumberFormatException e) {
        // It's OK to ignore "e" here because returning a default value is the documented behaviour on invalid input.
        return def;
    }
}
13
Cameron Skinner

Commons lang には NumberUtils.toInt(String、int) があります。

NumberUtils.toInt("123", 42) ==> 123
NumberUtils.toInt("abc", 42) ==> 42
9
daveb
* Is there a way to mark the exception somehow explicitly that I don't care about it? I'm thinking this would be something similar to AWTEvent.consume(). If so, then I will do this so that Google CodePro doesn't see this as "unlogged".

はい、1行のコードに対してCodePro監査ルールをローカルで無効にできます。

http://code.google.com/javadevtools/codepro/doc/features/audit/locally_disabling_audit_rules.html

とはいえ、必ずしもすべての例外キャッチブロックに診断ログを含める必要はありません。時々、最善の行動はデフォルトコースを取ることです。時にはそれはユーザーと対話することです。場合によります。

3
Andy Thomas

現在および将来使用するための独自の便利なメソッドを作成します。

public static int parseInt(final /*@Nullable*/ String s, final int valueIfInvalid) {
    try {
        if (s == null) {
            return valueIfInvalid;
        } else {
            return Integer.parseInt(s);
        }
    } catch (final NumberFormatException ex) {
        return valueIfInvalid;
    }
}

Integer.parseInt()がそれを呼び出す前にNumberFormatExceptionをスローするかどうかを通知する、呼び出すことができるメソッドはありますか?それが起こることはないので、私はこれをログに記録しても問題ありません。

私が知っていることではありません。あった場合は、値を2回解析することになることに注意してください(一度検証すると、1回解析します)。あなたは例外を避けたいと思っていますが、この場合、これは例外をキャッチしていますJavaの標準的なイディオムであり、それは別のものを提供しません(少なくとも私が知っていることです)。

単に例外をキャッチしない場合、変数は割り当てられませんか?次に、それが数値でない場合に必要な値に初期化し、例外をキャッチしません。

(それが何もしない場合でも)例外をキャッチする必要があります。そうしないと、ブロックをエスケープしてスタックをスローします。

例外を気にしないことを何らかの方法で明示的にマークする方法はありますか?これはAWTEvent.consume()に似たものになると思います。その場合は、Google CodeProがこれを「ログに記録されていない」と見なさないようにするためです。

知りません。上記の便利な方法を使用します(すべてのプロジェクトで使用できる一般的なユーティリティの小さなコレクションに似たものがあります)。

本当に正常な状態であれば、ログに記録しません。私はGoogle CodeProに慣れていませんが、警告を抑制する方法があるといいのですが。ある種の@SuppressWarnings( "xxx")アノテーション/キーワード。


編集:以下のコメントでこれらのコメントを指摘したかった

このアプローチはまだ例外を処理しません。例外をキャッチしてそれに対して何もしないのは悪い形です。これが私がより良い解決策を探している理由です

...例外(状況)処理中示されたvalueIfInvalidを返す。 "bad form"あなたが参照している空のcatchブロックを盲目的にそして思いがけずに書くという悪い習慣そして、ケースを真に検討して対処するために戻ることはありません。 例外状況が考慮され、正しいことを行う状況の場合(正しいことは何も行わない場合でも)、あなた ' veが例外を「処理」しました

1
Bert F

あなたがしているようにあなたは例外をキャッチする必要があります。面倒ですが、最善の方法です。

文字列が有効なintでない場合に0を返すJava APIメソッドはありません。

文字列がintでない場合、例外がスローされるため、実行中に例外をキャッチしない限り、int変数は設定されません。

0
Marcus Leon

最初のコードブロックは正しいです。 iは、例外が発生したときに暗黙的に0に変換されないため、その例外をキャッチする必要があります。 i内でcatchを0に設定することは正しいです。単にi = 0;return 0;。この場合、例外処理を回避することはできません。

明確にするために、これを使用できます:

private int getCurrentPieceAsInt() {
    int i = 0;
    try {
        i = Integer.parseInt(this.getCurrentPiece());
    } catch (NumberFormatException e) {
        // log that an exception occured if it's needed
        return 0;
    }
    return i;
}
0
darioo

ゲッターからそれを処理する方法が明確でない場合は、それをキャッチして、代わりに呼び出し側に処理させる必要があります。それがどのように扱われるべきか知っているなら、あなたはそれをするべきです。この場合、ログを記録する必要がないか、非常に役立ちます。

例外のログ方法は、例外の処理方法がわからず、ログを読む人にそれを任せている場合に、より役立ちます。

0
Peter Lawrey

他の人が述べたように、組み込みコアはありませんJava APIメソッドを呼び出して整数を検証できますが、Characterクラスを使用して入力を検証できます- without例外処理を使用します。例:

package com.example.parseint;

public class ValidateIntExample {
    public static boolean isInteger(String s) {
        if (s == null) {
            return false;
        }

        s = s.trim();

        if (s.length() == 0) {
            return false;
        }

        int start = 0;
        if (s.charAt(0) == '-') { // handle negative numbers
            if (s.length() == 1) {
                return false;
            }
            else {
                start = 1;
            }
        }

        for (int i = start; i < s.length(); i++) {
            if (! Character.isDigit(s.charAt(i))) {
                return false;
            }
        }

        return true;
    }
}

実際、parseInt自体は内部でCharacter.isDigitを使用しており、JREソースコードで確認できます。 (申し訳ありませんが、ここにparseIntメソッドを含めましたが、ライセンス条項に基づいて許可されているかどうかはわかりません。)Eclipseを使用していて、JREソースコードがプロジェクトで、コードのメソッドInteger.parseIntを右クリックして、[宣言を開く]をクリックできます。

0
rob