我什么时候应该在java中使用异常

Ama*_*ath 0 java exception-handling exception

我试图理解为什么要使用异常.假设我有一个程序,

(不使用try/catch)

public class ExceptionExample {

private static String str;

public static void main(String[] args) {
    System.out.println(str.length());
}
Run Code Online (Sandbox Code Playgroud)

我有例外

Exception in thread "main" java.lang.NullPointerException
at com.Hello.ExceptionExample.ExceptionExample.main(ExceptionExample.java:22)
Run Code Online (Sandbox Code Playgroud)

现在使用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();
    }
}
Run Code Online (Sandbox Code Playgroud)

}

我得到了例外,

java.lang.NullPointerException
at com.Hello.ExceptionExample.ExceptionExample.main(ExceptionExample.java:9)
Run Code Online (Sandbox Code Playgroud)

现在我的问题是,

在这两种情况下,我都打印了相同的信息.那么使用try/catch有什么用呢?和

捕获异常后我们可以做些什么,在这种情况下我打印了堆栈跟踪.catch是否仅用于打印跟踪或使用getMessage()或getClass()查找异常详细信息?

Bri*_*ian 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?");
    }
}
Run Code Online (Sandbox Code Playgroud)

您将看到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?");
    }
}
Run Code Online (Sandbox Code Playgroud)

将打印堆栈跟踪 Does this execute?.这是因为捕获异常就像是说:"我们将在这里处理并继续执行."

另外一句话,该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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

所以这里有一些注意事项:

  1. 我们捕获FileNotFoundException并使用自定义错误消息而不是打印堆栈跟踪.我们的错误消息比打印堆栈跟踪更清晰,更友好.在GUI应用程序中,控制台甚至可能对用户不可见,因此这可能是向用户显示错误对话框的代码.仅仅因为文件不存在并不意味着我们必须停止执行我们的代码.
  2. 我们throws IOException在方法签名中声明,而不是将其与FileNotFoundException.在这种特殊情况下,IOException如果我们无法读取文件,即使它存在,也会抛出此处.对于这种方法,我们说处理文件时遇到的错误不是我们的责任.这是一个如何声明一个不可恢复的错误的例子(通过不可恢复的,我的意思是在这里不可恢复,它可以在某个地方进一步恢复,例如在调用的方法中printFileToConsole).
  3. 我不小心在finally这里介绍了这个块,所以我会解释它的作用.它保证如果Scanner打开并且在我们读取文件时发生错误,Scanner则将关闭.这很重要,原因很多,最明显的是如果你不关闭它,Java仍然会锁定文件,因此你不能在不退出应用程序的情况下再次打开文件.