我已经阅读了有关此内容的所有内容,但我仍然不明白如何使用检查和未检查的例外。我想我仍然无法掌握这个概念。我已经阅读了stackoverflow,说使用未检查而不是检查的例外是更好的,但是Eclipse forces 我使用检查的异常,例如在FileNotFoundException
中要插入尝试/捕获块,这是一个检查的例外)。我想知道,有什么办法可以翻译检查为未选中的检查吗?到底是什么本身。我不明白处理例外是什么。
我在这里有一个示例,我真的很想知道如何处理(?)。这是一个检查的例外,对吗?
public void readFile() {
File foo = new File("./foo.bar");
try {
BufferedReader bufferedReader = new BufferedReader(new FileReader(foo));
} catch (FileNotFoundException e) {
// What should I do here?
}
getDataFromFile(bufferedReader);
}
我已经看到人们在这里做的各种事情。有些人打印出堆栈跟踪,这就是我通常要做的,而且我看不到它的问题。它为我提供了需要调试的信息。有些人忽略了它们,我认为不应该这样做(我看到Jnode OS Booter忽略了例外)。有些人只需在签名中添加throws
声明即可。有些投掷更多的例外情况!(我认为也许这是使用未检查而不是检查的方法?)
此外,如果您添加throws
声明,您将被迫进一步进行尝试/捕获块,如果您有很大的应用程序,那将是不便的。对不起,但我简直毫无头绪。完全地。我正在尝试学习良好而优雅的设计,这正在折磨我。
未选中的例外
是一个例外,因为首先不应该发生的事情,因此无法预料。仅当您的程序具有 bug 时,它才能处理出现的情况。
它是RuntimeException
的子类(是Exception
的子类),通常使用IllegalArgumentException
,NullPointerException
或IllegalStateException
未检查的运行时例外情况表示通常 说话,反映您程序逻辑中的错误,不能是 在运行时合理地恢复。
检查了异常
由于系统的其余部分,可能发生的事情可能发生。它不在您的直接控制之外,但是不一定是一个错误,而是可以遇到的情况。
它是Exception
的子类。
来自:异常
在您的示例中,
不存在的文件是您需要处理的情况,即使在某些条件盛行(磁盘已满)的情况下,即使在生产代码中也可能发生。这使它成为一个例外。
处理例外:
例外旨在提供更好的用户体验。所以 您应该向用户报告错误,并优雅地终止 你不能继续。
如果确实是您预期的情况,那么您可能应该告知用户该问题,并在必要时优雅地终止或继续进行下一件事。
如果这是一个不受限制的例外,那么您能做的最好的就是告诉用户,而不是出现意外错误,因为这不是首先要发生的事情,并且将stacktrace报告回到你。
首先,您的朋友是例外::) - 不,真的。例外是错误处理错误的强大且安全的方法。
基本上,Java中检查和未检查的例外之间的差异是对例外的预期反应:
通常使用检查的例外,将操作的某种"意外"结果传达给呼叫者,后者被认为是要明确处理该特殊状态的。
一个未选中的例外通常是被认为或多或少无法恢复的例外。它用于指示某些假定的故障状态,这些条件被认为使整个操作无效。像NullPointerException
一样,这些例外几乎在所有操作中都具有或多或少的潜在。检查它们将意味着需要由呼叫者进行错误处理。
在您的示例中,您可能会这样去:
public void readFile() {
File foo = new File("./foo.bar");
try {
BufferedReader bufferedReader = new BufferedReader(new FileReader(foo));
getDataFromFile(bufferedReader); // If the file could not be found above, this will never execute!
} catch (IOException e) {
// React, e.g.:
System.out.println("Data could not be read due to an IO error.");
}
}
重新验证例外或包裹另一个例外并不少见。 - 例如,当IOException
罢工时,您可能需要进行一些清理,关闭一些打开的文件或类似的内容,然后将异常AS交给呼叫者,以便他可以以适当的方式处理异常。<<<<<<<<<<<</p>
您实际处理特定异常的方式几乎完全取决于您。根据用户(例如您自己)和运行代码打印的环境,堆叠可能还可以。或者,也许您想在停顿后重试您刚刚做的事情。或者,在给出的示例中,您可以向用户显示一条消息,并要求他重新输入文件名,&amp; c。
后者是可以有效使用不同类别异常的东西:FileNotFoundException
(是IOException
的子类)可以通过用户交互可恢复;裸露的IOException
很可能被认为是无法恢复的,因为它在最坏的情况下甚至表明某种硬件故障。
让我们以示例(修改)本身要解释。
public void readFile() {
BufferedReader bufferedReader = null;
try {
File foo = new File("./foo.bar");
bufferedReader = new BufferedReader(new FileReader(foo));
} catch (FileNotFoundException e) {
// What should I do here?
}
getDataFromFile(bufferedReader);
}
当您获得FileNotFoundException
异常时,您的BufferedReader不会使用文件流进行初始化。在这种情况下,您的下一个语句即getDataFromFile(bufferedReader);
将失败,因为没有读取数据的bufferedReader。
因此,在catch
块中,您可以在两者中执行:
- 提出一个新的自定义异常,然后从程序中返回
- 尝试在再次获取文件句柄时纠正问题(在这种情况下可以使用默认文件),因此
bufferedReader
已正确初始化。
以这种方式,CheckedException
在编写程序本身时对情况有所帮助。他们为您提供有关可能失败的输入,并使您能够预先做出适当的处理决策。
另一方面,在编译时间很难识别未检查的例外,例如NullPointerException
,并且可能没有注意到。如果发生并且没有处理,它们会在运行时间引起问题。
检查的异常是屁股的痛苦。
很抱歉使用这种钝语,但它们是Java最糟糕的设计错误之一!如果您必须处理仍然使用已检查异常的遗留API,例如Eclipse或Java自己的API,我个人要做的就是将它们包裹在我自己的未检查的例外。最好使用自己的标签类是一个好习惯。这可以帮助您识别这些例外是由您的代码引起的,例如在日志文件中或调试时。
我个人对打电话给我的标签类BullshitFree
感到非常满意
try {
// call to legacy API that still uses checked exceptions
} catch(CheckedException exception) {
throw new BullshitFree(exception);
}
确保您的BullshitFree
异常类实际扩展了RuntimeException
,以便未选中它!
在您的代码示例中,有两个选项。如果有一种方法可以从中恢复,例如,创建文件或向用户报告错误,请这样做。如果没有,或者只是您自己使用的一个小脚本,请将其包装在BullshitFree
例外,并花一天的时间学习Ruby或其他设计精良的语言……
您的里程可能会有所不同。