0

例外を使用する理由を理解しようとしていました。プログラムがあるとします。

(try/catch を使用せずに)

public class ExceptionExample {

private static String str;

public static void main(String[] args) {
    System.out.println(str.length());
}

例外が発生しました

Exception in thread "main" java.lang.NullPointerException
at com.Hello.ExceptionExample.ExceptionExample.main(ExceptionExample.java:22)

現在、try/catch を使用して、

public class ExceptionExample {

private static String str;

public static void main(String[] args) {
    try {
        System.out.println(str.length());
    } catch(NullPointerException npe) {
        npe.printStackTrace();
    }
}

}

私は例外を得ました、

java.lang.NullPointerException
at com.Hello.ExceptionExample.ExceptionExample.main(ExceptionExample.java:9)

今、私の質問は、

どちらの場合も、同じメッセージが出力されました。では、try/catch を使用する用途は何ですか? と

例外をキャッチした後に何ができるでしょうか。この場合、スタック トレースを出力しました。catch は、トレースを出力するため、または getMessage() または getClass() を使用して例外の詳細を見つけるためだけに使用されますか?

4

8 に答える 8

5

実際、その違いはかなり大きいです。

最初のものを取り、印刷の後に行を追加します。

public class ExceptionExample {

    private static String str;

    public static void main(String[] args) {
        System.out.println(str.length());
        System.out.println("Does this execute?");
    }
}

Does this execute?例外がコードのフローを中断し、キャッチされない場合は停止するため、出力されないことがわかります。

一方で:

public class ExceptionExample {

    private static String str;

    public static void main(String[] args) {
        try {
            System.out.println(str.length());
        } catch(NullPointerException npe) {
            npe.printStackTrace();
        }
        System.out.println("Does this execute?");
    }
}

スタック トレース Does this execute?. 例外をキャッチするということは、「ここでこれを処理して実行を続行する」と言っているようなものだからです。

もう1つの注意点として、catchブロックはエラー回復が発生する場所であるため、エラーが発生しても回復できる場合は、そこに回復コードを配置します。

編集:

エラー回復の例を次に示します。に存在しないファイルがあるとしますC:\nonexistentfile.txt。開いてみて、見つからない場合は、見つからないというメッセージをユーザーに表示します。FileNotFoundExceptionこれは、ここで生成されたものをキャッチすることで実行できます。

// Here, we declare "throws IOException" to say someone else needs to handle it
// In this particular case, IOException will only be thrown if an error occurs while reading the file
public static void printFileToConsole() throws IOException {
    File nonExistent = new File("C:/nonexistentfile.txt");
    Scanner scanner = null;
    try {
        Scanner scanner = new Scanner(nonExistent);
        while (scanner.hasNextLine()) {
            System.out.println(scanner.nextLine());
        }
    } catch (FileNotFoundException ex) {
        // The file wasn't found, show the user a message
        // Note use of "err" instead of "out", this is the error output
        System.err.println("File not found: " + nonExistent);
        // Here, we could recover by creating the file, for example
    } finally {
        if (scanner != null) {
            scanner.close();
        }
    }
}

したがって、ここで注意すべき点がいくつかあります。

  1. FileNotFoundExceptionスタック トレースを出力する代わりに、カスタム エラー メッセージをキャッチして使用します。エラー メッセージは、スタック トレースを出力するよりも明確でユーザー フレンドリーです。GUI アプリケーションでは、コンソールがユーザーに表示されない場合があるため、代わりにユーザーにエラー ダイアログを表示するコードである可能性があります。ファイルが存在しなかったからといって、コードの実行を停止する必要があるわけではありません。
  2. throws IOException.と一緒にキャッチするのではなく、メソッド シグネチャで宣言しFileNotFoundExceptionます。この特定のケースではIOException、ファイルが存在するにもかかわらず読み取りに失敗すると、ここで がスローされます。この方法では、ファイルの読み取り中に発生したエラーの処理は私たちの責任ではないと言っています。これは、回復不能なエラーを宣言する方法の例です (回復不能とは、ここでは回復不能を意味します。 を呼び出したメソッドなど、さらに上のどこかで回復可能である可能性がありますprintFileToConsole)。
  3. ここで誤ってfinallyブロックを紹介してしまったので、その機能について説明します。Scannerが開かれ、ファイルの読み取り中にエラーが発生した場合、Scannerが閉じられることが保証されます。これは多くの理由で重要です。最も顕著なのは、ファイルを閉じないと Java がファイルをロックしたままになるため、アプリケーションを終了しないとファイルを再度開くことができないことです。
于 2012-09-25T18:06:46.857 に答える
3

例外をスローする必要がある場合は 2 つあります。

  • クラスの不適切な使用 (つまり、プログラミング エラー) に起因するエラーを検出すると、チェックされていない例外のインスタンス、つまりのサブクラスをスローします。RuntimeException
  • プログラミング エラー以外の原因によるエラー (無効なデータ、ネットワーク接続の欠落など) を検出すると、Exceptionサブクラス化されていないのインスタンスをスローします。RuntimeException

第 1 種の例外ではなく、第 2 種の例外をキャッチする必要があります。さらに、プログラムに例外的な状況を修正する一連のアクションがある場合は、例外をキャッチする必要があります。たとえば、接続の切断を検出した場合、プログラムはユーザーにネットワークに再接続して操作を再試行するように提案できます。コードが例外を適切に処理できない状況では、それを処理できるレイヤーに伝搬させます。

于 2012-09-25T18:05:18.240 に答える
1

データベースに接続していて、レコードの読み取り中に例外がスローされたとします。この特定のケースでは、Finally ブロックで接続を閉じることができます。ここでメモリリークを回避しました。私が言いたかったのは、例外がスローされても、キャッチして処理することでタスクを実行できるということです。

于 2012-09-25T18:06:50.107 に答える
1

あなたが与えた例では、あなたは正しいです、利益はありません。

次のいずれかの場合にのみ例外をキャッチする必要があります

  • あなたはそれについて何かをすることができます (報告、情報の追加、状況の修正)、または
  • チェックされた例外があなたを強制するので、あなたはしなければなりません

例外の通常の「処理」は、選択したログ ファイルに状況を記録し、関連するコンテキスト依存情報を追加して、フローを続行させることです。コンテキスト情報を追加すると、問題の解決に大きく役立ちます。したがって、あなたの例では、

public static void main(String[] args) {
    try {
        System.out.println(str.length());
    } catch(NullPointerException npe) {
        System.err.println(
           "Tried looking up str.length from internal str variable,"
               +" but we got an exception with message: "
               + npe.getMessage());
        npe.printStackTrace(System.err);
    }
}

そのようなメッセージを見ると、誰かがそのメッセージに基づいて、何がうまくいかなかったのか、それを修正するために何をすればよいのかさえわかるでしょう。

于 2012-09-25T18:07:24.013 に答える
1

try/catch は、アプリケーションのクラッシュを防ぎます。正確には、意図しない条件が満たされた場合でも実行は停止しません。「危険な」コードを try ブロックでラップし、catch ブロックでその例外を処理できます。ハンドリングとは、その状態を何とかして実行に移すという意味です。try/catch を使用しないと、エラーが発生した行で実行が停止し、それ以降のコードは実行されません。

あなたの場合、「これは私が期待したものではありませんでした。とにかく、先に進みましょう!」と出力できたはずです。

于 2012-09-25T18:05:47.737 に答える
0

例外を使用している場合は、しないでください

 catch(NullPointerException npe) {
    npe.printStackTrace();
}

単に

  catch(NullPointerException npe) {
        //error handling code
    }

エラー印刷を削除する必要があります。とにかく、特定の例外だけでなく、一般的な例外をキャッチします。

于 2012-09-25T18:03:31.413 に答える
0

2 つの例外を見ると、実際には異なっています。最初のものは 22 行目を参照し、2 つ目は 9 行目を参照しています。try/catch を追加すると最初の例外がキャッチされたように聞こえますが、別のコード行も例外をスローしました。

したがって、表示されていないコードの一部で行われた場合を除き、新しい文字列を作成したり、文字列に値を設定したりしていないため、例外がスローされています。

try/catch ブロックを追加すると、ほとんどまたはまったく制御できないオブジェクトで非常に役立ちます。そのため、これらのオブジェクトが予想外のもの (null など) である場合、問題を適切に処理できます。

文字列は通常、最初にインスタンス化するものであるため、通常、try/catch の使用について心配する必要はありません。

お役に立てれば。

于 2012-09-25T18:08:44.390 に答える
0

元の質問 Che に答えるには、「いつ例外を使用するのですか?」

Java の場合 - もうお気づきだと思いますが、Java には、try / catch を必要とする特定のメソッドがあります。これらのメソッドは例外を「スロー」し、それを意図しています。それを回避する方法はありません。

例えば、

FileUtils.readFileToString(new File("myfile.txt"));

try/catch を追加するまでコンパイルできません。

一方、例外から得られるものがあるため、例外は非常に便利です。

Java リフレクションを例にとると...

try { Class.forName("MyClass").getConstructor().newInstance(); }
catch ( ClassNotFoundException x ) { // oh it doesnt exist.. do something else with it.

だからあなたの質問に完全に答えるために -

Try/Catch は控えめに使用してください。通常、アプリケーションでエラーが発生する可能性があるため、「眉をひそめる」ものです。逆に、メソッドで必要な場合に使用してください。

于 2012-09-25T18:12:00.940 に答える