异常处理全面解析
checked和unchecked异常
-
checked 异常(检查型异常)在源代码里必须显式地捕获或者抛出,否则编译器会提示你进行相应的操作;而 unchecked 异常(非检查型异常)就是所谓的运行时异常,通常是可以通过编码进行规避的,并不需要显式地捕获或者抛出。
-
NoClassDefFoundError:程序在编译时可以找到所依赖的类,但是在运行时找不到指定的类文件,导致抛出该错误;原因可能是 jar 包缺失或者调用了初始化失败的类。
-
ClassNotFoundException:当动态加载 Class 对象的时候找不到对应的类时抛出该异常;原因可能是要加载的类不存在或者类名写错了。
throw和throws
1)throws关键字用于声明异常,它的作用和try-catch相似;而throw关键字用于显式的抛出异常。
throws ArithmeticException;
2)throws关键字后面跟的是异常的名字;而throw关键字后面跟的是异常的对象。
throw new ArithmeticException("算术异常");
3)throws关键字出现在方法签名上,而throw关键字出现在方法体里。
4)throws关键字在声明异常的时候可以跟多个,用逗号隔开;而throw关键字每次只能抛出一个异常。
- 如果有好几个类似的方法都可能出现异常,如果为每个方法都加上try-catch,就会显得非常繁琐。一个解决办法就是,使用throws关键字,在方法签名上声明可能会抛出的异常,然后在调用该方法的地方使用try-catch进行处理。
public static void main(String args[]){ try { myMethod1(); } catch (ArithmeticException e) { // 算术异常 } catch (NullPointerException e) { // 空指针异常 } } public static void myMethod1() throws ArithmeticException, NullPointerException{ // 方法签名上声明异常 }
try-catch-finally
-
一个
try
块后面可以跟多个catch
块,用来捕获不同类型的异常并做相应的处理,当 try 块中的某一行代码发生异常时,之后的代码就不再执行,而是会跳转到异常对应的 catch 块中执行。 -
如果一个 try 块后面跟了多个与之关联的 catch 块,那么应该把特定的异常放在前面,通用型的异常放在后面,不然编译器会提示错误。
-
finally 块前面必须有 try 块,不要把 finally 块单独拉出来使用。编译器也不允许这样做。
-
finally 块不是必选项,有 try 块的时候不一定要有 finally 块。
-
如果 finally 块中的代码可能会发生异常,也应该使用 try-catch 进行包裹。
-
即便是 try 块中执行了 return、break、continue 这些跳转语句,finally 块也会被执行
-
不执行finally的情况:遇到了死循环;执行了
System. exit()
这行代码。
class MyFinallyReadLineThrow { public void close() throws Exception { throw new Exception("close"); } public void readLine() throws Exception { throw new Exception("readLine"); } } public class Test { public static void main(String[] args) throws Exception { MyFinallyReadLineThrow myThrow = null; try { myThrow = new MyFinallyReadLineThrow(); // readLine的异常信息丢失 myThrow.readLine(); } finally { myThrow.close(); } /* Exception in thread "main" java.lang.Exception: close at test.ExceptionTest.MyFinallyReadLineThrow.close(Test.java:5) at test.ExceptionTest.Test.main(Test.java:21) */ } }
try-with-resources
- 当一个异常被抛出的时候,可能有其他异常因为该异常而被抑制住,从而无法正常抛出。这时可以通过
addSuppressed()
方法把这些被抑制的方法记录下来,然后被抑制的异常就会出现在抛出的异常的堆栈信息中,可以通过getSuppressed()
方法来获取这些异常。这样做的好处是不会丢失任何异常,方便我们进行调试。
package test.ExceptionTest; class MyFinallyReadLineThrow implements AutoCloseable { @Override public void close() throws Exception { throw new Exception("close"); } public void readLine() throws Exception { throw new Exception("readLine"); } } public class Test { public static void main(String[] args) { try (MyFinallyReadLineThrow myThrow = new MyFinallyReadLineThrow()) { myThrow.readLine(); } catch (Exception e) { e.printStackTrace(); } /* java.lang.Exception: readLine at test.ExceptionTest.MyFinallyReadLineThrow.readLine(Test.java:10) at test.ExceptionTest.Test.main(Test.java:18) Suppressed: java.lang.Exception: close at test.ExceptionTest.MyFinallyReadLineThrow.close(Test.java:6) at test.ExceptionTest.Test.main(Test.java:19) */ } }
本文作者:n1ce2cv
本文链接:https://www.cnblogs.com/sprinining/p/18300977
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南