我试图理解为什么要使用例外。 假设我有一个程序,
(不使用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()查找异常详细信息?
答案 0 :(得分: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?
。这是因为捕获异常就像是说:“我们将在此处理并继续执行。”
另外一句话,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();
}
}
}
所以这里有几点需要注意:
FileNotFoundException
并使用自定义错误消息而不是打印堆栈跟踪。我们的错误消息比打印堆栈跟踪更清晰,更友好。在GUI应用程序中,控制台甚至可能对用户不可见,因此这可能是向用户显示错误对话框的代码。仅仅因为文件不存在并不意味着我们必须停止执行我们的代码。throws IOException
,而不是将其与FileNotFoundException
一起删除。在这种特殊情况下,如果我们无法读取文件,即使它存在,IOException
也将被抛出。对于这种方法,我们说处理文件时遇到的错误不是我们的责任。这是一个如何声明不可恢复的错误的例子(通过不可恢复的,我的意思是在这里不可恢复,它可以在某个地方进一步恢复,例如在调用printFileToConsole
的方法中)。finally
块,所以我将解释它的作用。它保证如果Scanner
被打开并且在我们阅读文件时发生错误,则Scanner
将被关闭。这很重要,原因很多,特别是如果你不关闭它,Java仍然会锁定文件,因此你不能在不退出应用程序的情况下再次打开文件。答案 1 :(得分:3)
有两种情况应该抛出异常:
RuntimeException
Exception
的子RuntimeException
的实例您应该捕获第二种异常,而不是第一种异常。此外,如果您的计划有一系列纠正特殊情况的行动,您应该抓住例外情况;例如,如果您检测到连接丢失,您的程序可以让用户重新连接到网络并重试该操作。在您的代码无法充分处理异常的情况下,让它传播到可以处理异常的层。
答案 2 :(得分:1)
try / catch将阻止您的应用程序崩溃或准确 - 如果满足无意的条件,执行将不会停止。您可以将“风险”代码包装在try块中,在catch块中可以处理该异常。通过处理,这意味着对该条件做一些事情并继续执行。 没有try / catch,执行在错误生成线处停止,之后的任何代码都不会被执行。
在你的情况下,你可以打印出“这不是我想象的,不管怎样,让我们继续吧!”
答案 3 :(得分:1)
假设您已连接到数据库但在读取记录时会抛出一些异常。现在在这种特殊情况下,您可以在Finally块中关闭连接。你刚才避免了内存泄漏。 我的意思是,即使通过捕获和处理异常引发异常,您也可以执行任务。
答案 4 :(得分: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);
}
}
当看到这样的消息时,有人会根据消息知道出了什么问题,甚至可能会做些什么来修复它。
答案 5 :(得分:0)
如果您使用的是例外,请不要
catch(NullPointerException npe) {
npe.printStackTrace();
}
简单地
catch(NullPointerException npe) {
//error handling code
}
您需要删除错误打印。无论如何,除了特定的例外情况之外,还要抓住一般例外。
答案 6 :(得分:0)
如果你看两个例外,它们实际上是不同的。第一个是指第22行,而第二个是指第9行。听起来像添加try / catch捕获了第一个异常,但另一行代码也引发了异常。
因此,抛出异常是因为您从未创建过新的String,或者为字符串设置了值,除非它是在未显示的部分代码中完成的。
添加try / catch块对于几乎无法控制的对象非常有用,因此如果这些对象不是预期的(例如null),则可以正确处理该问题。
字符串通常是您首先要实例化的东西,因此您通常不必担心使用try / catch。
希望这有帮助。
答案 7 :(得分:0)
回答你原来的问题Che,“何时使用例外?”
在Java中 - 我相信你已经发现了... Java中有一些需要try / catch的方法。这些方法“抛出”异常,并且意味着。没有办法解决它。
例如,
FileUtils.readFileToString(new File("myfile.txt"));
在添加try / catch之前,不允许编译。
另一方面,异常非常有用,因为你可以从中得到什么。
以Java Reflection为例......
try { Class.forName("MyClass").getConstructor().newInstance(); }
catch ( ClassNotFoundException x ) { // oh it doesnt exist.. do something else with it.
完全回答你的问题 -
谨慎使用Try / Catch,因为它通常会“不赞成”应用程序中的EXPECT错误。相反,在您的方法需要时使用它们。