Java 基础篇之异常
异常
异常层次
- error:java 运行时系统的内部错误和资源耗尽错误。应用程序不应该抛出这种类型的对象。如果出现了这样的内部错误,除了通告给用户,并尽力使程序安全地终止之外,再也无能为力了。
- exception
- runtimeexception:由程序错误导致的异常
- 其他异常:程序本身没有问题,但由类似 io 错误导致的异常
checked 异常 & runtime 异常
checked 异常:不是 runtimeexception 类及其子类的异常实例
runtime 异常:所有 runtimeexception 类及其子类的异常实例
java 认为 checked 异常都是可以被处理修复的异常,所以程序必须显示处理 checked 异常,如果程序没有处理 checked 异常,编译时会出错。checked 异常体现了 java 的设计理念,没有完善错误处理的代码根本不会被执行。
对 checked 异常处理方式:
当前方法明确知道如何处理该异常,应该使用 try-catch 处理该异常
当前方法不知道如何处理该异常,应在定义该方法时声明抛出该异常
对 runtime 异常的处理方式:
- runtime 异常无需显式声明抛出,如果程序需要捕获 runtime 异常,也可以使用 try-catch 块
throws 声明抛出异常
如果当前方法不知道如何处理这种类型的异常,该异常应该由上一级调用者处理,如果上一级调用者也不知道如何处理,再抛出直至交由 jvm 处理。
throws 声明抛出只能在方法声明中使用,可以声明抛出多个异常类。一旦使用 throws 语句声明抛出该异常,程序就无需使用 try-catch 来捕获异常了。
示例:下面程序声明不处理 ioexception 异常,而是将该异常交由 jvm 处理
import java.io.fileinputstream; import java.io.ioexception; public class throwstest { public void main(string[] args) throws ioexception { fileinputstream fis = new fileinputstream("a.txt"); } }
如果某段代码中调用了一个带 throws 声明的方法,该方法声明抛出了 checked 异常,则表明该方法希望它的调用者来处理该异常。那么调用者在调用该方法时,要么将其放入 try 块中并显示捕获该异常,要么放在另一个带 throws 声明抛出的方法中。
示例代码如下:
import java.io.fileinputstream; import java.io.ioexception; public class throwstest2 { public static void test() throws ioexception { /* 因为 fileinputstream 的构造器声明抛出 ioexception 异常 所以调用 test() 方法 的代码要么处于 try-catch 块中 要么处于另一个带 throws 声明抛出的方法中 */ fileinputstream fis = new fileinputstream("a.txt"); } public static void main(string[] args) throws exception { /* 因为 test() 方法声明抛出 ioexception 异常 所以调用该方法的代码要么处于 try-catch 块中 要么处于另一个带 throws 声明抛出的方法中 */ test(); } }
主动抛出异常 throw
如果 throw 语句抛出的异常是 checked 异常,则该 throw 语句要么处于 try 块里,显式捕获该异常,要么放在一个带 throws 声明抛出的方法中;如果 throw 语句抛出的是 runtime 异常,则无需放在 try 块里,也无需放在带 throws 声明抛出的方法中,既可以显式的用 try-catch 来捕获并处理异常,也可以完全不理会该异常,把该异常交给该方法调用者处理。
import java.io.ioexception; public class throwtest3 { public static void throwchecked(int a) throws exception { if (a > 0) { // 自行抛出 exception 异常 // 该代码必须处于 try 块里,或处于带 throws 声明的方法中 throw new exception("a的值大于0,不符合要求"); } } public static void throwruntime(int a) { if (a > 0) { // 自行抛出 runtimeexception 异常 // 既可以捕获该异常,也可以完全不理会该异常,把异常交给方法调用者处理 throw new runtimeexception("a的值大于0,不符合要求"); } } public static void main(string[] args) { try { // 调用声明抛出 checked 异常的方法,要么显式在 try-catch 中捕获该异常,要么在 main 方法中再次声明抛出 throwchecked(3); } catch (exception e) { system.out.print(e.getmessage()); } // 调用声明抛出 runtime 异常的方法既可以显式捕获该异常,也可以不理会该异常 throwruntime(3); } }
自定义异常类
public class auctionexception extends exception { // 无参构造器 public auctionexception() {} // 带一个字符串参数的构造器 public auctionexception(string msg) { super(msg); } }
异常链
将原始信息隐藏起来,仅向上提供必要的异常提示信息的处理方式,可以保证底层异常不会扩散到表现层,避免向上暴露太多的细节,符合面向对象的封装原则。
public calsal() throws salexception { try { // 实现结算工资的业务逻辑 ... } catch (sqlexception sqle) { // 将原始异常记录下来,留给管理员 ... // 下面异常中的 message 就是给用户的提示 throw new salexception("访问数据库异常“); } catch (exception e) { // 将原始异常记录下来,留给管理员 ... // 下面异常中的 message 就是给用户的提示 throw new salexception("系统出现未知异常“); } }
欢迎关注我的公众号