我在理解Java中的异常checked和unchecked异常方面遇到了一些问题.
checked异常应该在编译期间寻找异常.在不同来源中提供的示例引用数据库连接,文件处理作为其中一些,而unchecked异常应该在程序员的部分寻找错误,例如超出数组范围的索引等.不应该反过来吗?我的意思是,数据库连接是在运行时完成的,对吧?文件处理也是如此.在编译期间没有打开文件句柄,为什么在编译期间会查找可能的错误?另一方面,在程序中已完成索引超出其范围的数组,可在编译期间检查(如果用户在运行时提供异常索引,则可以将其作为运行时)问题).我在这里错过了什么?
2其次,如何才能RunTimeException,本身是unchecked,子类Exception,这是checked?这意味着什么?
我在Herbert Schildt的书中找到了一个例子来解释checked异常的用法:
class ThrowsDemo {
public static char prompt(String str)
throws java.io.IOException {
System.out.print(str + ": ");
return (char) System.in.read();
}
public static void main(String args[]) {
char ch;
try {
ch = prompt("Enter a letter");
}
catch(java.io.IOException exc) {
System.out.println("I/O exception occurred.");
ch = 'X';
}
System.out.println("You pressed " + ch);
}
}
Run Code Online (Sandbox Code Playgroud)
这throws条款是否必要?为什么我不能正常做这样的try-catch声明(抱歉我不知道如何模拟IO Exception,所以不能自己检查!):
class ThrowsDemo {
public static char prompt(String str) {
System.out.print(str + ": ");
return (char) System.in.read();
}
public static void main(String args[]) {
char ch;
try {
ch = prompt("Enter a letter");
}
catch(java.io.IOException exc) {
System.out.println("I/O exception occurred.");
ch = 'X';
}
System.out.println("You pressed " + ch);
}
}
Run Code Online (Sandbox Code Playgroud)
Lui*_*ano 27
CheckedException需要由调用者处理,Unchecked异常不需要.
因此,在设计应用程序时,您应该记住您正在管理的特殊情况.
例如,如果您设计一个检查某些用户输入有效性的验证方法,那么您就知道调用者必须检查验证异常并以一种漂亮的方式向用户显示错误.这应该是一个经过检查的例外.
或者,对于那些可以恢复的异常情况:假设您有一个负载均衡器,并且您希望通知呼叫者其中一个"n"服务器已关闭,因此呼叫者必须将事件恢复重新路由到另一个服务器; 这应该是一个经过检查的异常,因为调用者(客户端)尝试恢复错误是至关重要的,并且不要让错误破坏程序流.
相反,有许多条件不应该发生,和/或应该打破程序.例如,编程错误(如除零,空指针异常),API的错误使用(IllegalStateException,OperationNotSupportedException),硬件崩溃,或者只是一些不可恢复的小情况(与服务器的连接丢失),或世界末日:-); 在这些情况下,正常处理是让异常到达代码的最外部块,向用户显示发生了不可预测的错误,并且应用程序无法继续执行任何操作.这是一个致命的情况,所以你唯一能做的就是将它打印到日志或在用户界面中显示给用户.在这些情况下,捕获异常是错误的,因为在捕获异常后,您需要手动停止程序以避免进一步损坏; 所以最好让某种例外"击中粉丝":)
出于这些原因,在JRE中还存在一些未经检查的异常:OutOfMemoryError(不可恢复),NullPointerException(这是需要修复的错误),ArrayIndexOutOfBoundsException(另一个错误示例),依此类推.
我个人认为也应该取消选中SQLException,因为它表示程序中的错误或数据库的连接问题.但是有很多例子你会得到异常,你真的没有任何关于如何管理的线索(RemoteException).
处理异常的最佳方法是:如果您可以恢复或管理异常,请处理它.否则让异常传出; 别人需要处理.如果您是最后一个"其他人"并且您不知道如何处理异常,只需显示它(在UI中记录或显示).
throws子句中声明未经检查的异常; 但你必须声明已检查的例外情况;RuntimeException并且Error,他们所有的子类(的IllegalArgumentException,StackOverflowError等等),是unckecked例外; RuntimeException与其他Throwable子类不同,未经检查的事实是设计的;更一般地,认为在JVM错误或程序员错误的情况下抛出未经检查的异常.一个着名的例外是NullPointerException,通常缩写为NPE,它是子类RuntimeException,因此未经检查.
未经检查的异常与已检查异常之间的另一个非常重要的区别是,在try-catch块中,如果要捕获未经检查的异常,则必须明确地捕获它们.
最后一点:如果你有异常类E1和E2和E2延伸E1,然后捕捉和/或投掷E1也捕捉/抛出E2.这代表已检查和未检查的异常.这对catch块有一个暗示:如果你区分捕获E2和E1,你必须首先捕获E2.
例如:
// IllegalArgumentException is unchecked, no need to declare it
public void illegal()
{
throw new IllegalArgumentException("meh");
}
// IOException is a checked exception, it must be declared
public void ioerror()
throws IOException
{
throw new IOException("meh");
}
// Sample code using illegal(): if you want to catch IllegalArgumentException,
// you must do so explicitly. Not catching it is not considered an error
public void f()
{
try {
illegal();
} catch (IllegalArgumentException e) { // Explicit catch!
doSomething();
}
}
Run Code Online (Sandbox Code Playgroud)
我希望这会让事情更清楚......
不是.所有异常都在运行时发生.已检查的异常是强制调用者处理它们或声明它们的异常.它们通常用于发出可恢复错误的信号,这些错误不是由程序员错误(如文件不存在或网络连接问题)引起的.运行时异常通常用于表示不可恢复的错误.它们不会强制调用者处理或声明它们.其中许多确实发出编程错误信号(如NullPointerException).
因为这就是JLS如何定义未经检查的异常:一个异常是或扩展RuntimeException,它本身扩展了Exception.使用单个继承根允许在单个catch子句中处理每个可能的异常.
关于你的例子:是的,throws子句是必需的,因为IOException是一个经过检查的异常,并且方法中的代码很容易抛出一个.