异常处理
2019-05-22 06:33:14来源:博客园 阅读 ()
当程序运行出现意外情况时,系统会自动生成一个Exception对象来通知程序。
Exception(异常)、Error(错误)都继承自Throwable。
1 try{ 2 //可能出错的代码 3 } 4 catch(XxxException e){ 5 System.out.println(e.getMessage()); //处理异常的代码 6 } 7 finally { 8 //必须要关闭的资源 9 }
try是必须的,catch、finally可选,但必须出现其中之一。
try、catch代码块的{ }均不能省略,即使只有一行代码也不能省略{ }。
try中声明的变量是局部变量,只在try代码块中有效。
1 try{ 2 //...... 3 } 4 catch(NullPointerException e){ 5 System.out.println(e.getMessage()); 6 } 7 catch(Exception e){ 8 System.out.println(e.getMessage()); 9 }
可以同时用多个catch捕获多个异常,但必须小异常在前,大异常在后(子类异常在前,父类异常在后)。
1 try{ 2 //...... 3 } 4 catch(NullPointerException|IndexOutOfBoundsException e){ 5 //System.out.println(e.getMessage()); 6 }
可在一个catch中捕获多种异常,但这些异常必须是不同类型的,就是说不能有交集。异常类用 | 分开即可。
catch代码块中常用的异常处理方式:
1 System.out.println(e.getMessage()); //输出该异常的描述信息 2 System.out.println(e.getStackTrace()); //输出该异常的跟踪栈信息
3 e.printStackTrace(); //直接输出异常跟踪栈的信息,本身就是一个输出方法,不必写sout
GC只负责heap中对象的回收,程序中打开的物理资源,比如数据库连接、网络连接、磁盘文件等,都必须手动关闭。一般在finally中显式回收物理资源,以确保物理资源一定会被回收。
不管try代码块是否出现异常,不管被执行的是哪个catch代码块,甚至在try、catch中执行了return语句,finally代码块都一定会被执行,除非在try或者catch中调用了退出JVM的方法。
Java9自动关闭资源的try语句:
1 try( 2 //在()中写要打开的资源 3 FileOutputStream fos=new FileOutputStream("a.txt"); 4 ) { 5 //在try的{ }中使用打开的资源,当try{ }中的语句执行完毕时,会自动关闭()中打开的资源 6 fos.write("ok".getBytes()); 7 8 } 9 catch(Exception e){ 10 e.getMessage(); 11 }
我们也可以不使用try、catch处理异常,而直接把异常抛给上一级调用者:
1 public void getReault() throws Exception{ //在定义方法是不指定异常处理方式,而是使用throws把异常抛出给上一级调用者,由上一级调用者处理 2 //...... 3 }
上一级调用者可以使用try、catch来处理,也可以throws抛给自己的上一级调用者。
如果main()也使用throws抛出异常,main()抛出的异常会被JVM捕获,由JVM处理,JVM默认的处理方式是:打印异常的跟踪栈信息,终止程序运行。
可以抛出多个异常,用逗号隔开即可。
当程序出现异常时,系统会自动抛出异常,我们也可以手动抛出异常:
1 int a,b; 2 //..... 3 try{ 4 if(b==0) 5 throw new Exception("除数不能为0!"); //抛出异常时,会终止try{ }中throw后面代码块的执行,直接跳到对应的catch执行 6 System.out.println("a/b="+a/b); 7 }catch (Exception e){ 8 System.out.println(e.getMessage()); //捕获并处理我们自己抛出的异常 9 }
10 //后面的代码仍会继续执行
比如下棋时,先检测该点是否已有子,若已有子,自己抛出一个异常,在catch中捕获这个异常,输出提示“该点已有子,不能再落子”,接着继续执行catch代码块后面的代码(结束本次循环,等待用户输入落子点坐标)。
不管是系统自动抛出的异常,还是我们手动throw抛出的异常,处理方式都一样:终止try{ }中其余部分代码的执行,跳到对应的catch块执行后继续执行catch块后面的代码。
由于前面的结果有问题,catch后面正常的代码块往往也会出现问题,程序往往会抛出异常,一级级抛到JVM,打印跟踪栈信息,终止程序。比如try中做一个除法,try后面要使用商,执行try的时候除数为0,抛出异常,转到对应catch执行,然后继续执行catch后面的代码块,但商有问题,正常代码块的执行也会出现异常。
也可以这样:
1 public static void main(String[] args) throws Exception { //抛给上一级调用者 2 int a,b; 3 //...... 4 if(b==0) //不使用try、catch 5 throw new Exception("除数不能为0!"); //可以不在try中抛出异常,这样就可以不用catch处理我们抛出的异常,而是直接抛给上一级调用者,由上一级调用者处理 6 System.out.println("a/b="a/b); 7 }
throw抛出的是一个异常类的实例,而不是异常类,所以要new一个异常类的实例。(参数为异常类的message)
在大型企业级应用中,常常结合使用try、throw,catch做一部分处理,再把这个异常抛给上一级调用者,上一级调用者再做一些处理。
1 public static void main(String[] args) throws Exception { //抛给上一级调用者 2 //..... 3 try{ 4 //..... 5 } 6 catch (Exception e){ 7 //当前catch块做一些处理,比如在日志中记录异常 8 //..... 9 10 //然后再把这个异常抛给上一级调用者,由上一级调用者继续处理,需要在本方法的函数头用throws声明一下。当前方法则继续执行catch代码块后面部分 11 throw new Exception("....."); 12 } 13 //..... 14 }
我们也可以自定义异常,自定义异常必须继承Exception基类。可以直接继承,也可以继承Exception的子类(间接继承)。
异常转译:
通常我们不把底层的原始异常直接传给用户,而是先捕获异常,再抛出一个新异常,新异常包含用户提示信息,由上一级调用者处理。
1 public static void main(String[] args) throws XxxException { //需要在此处声明,抛给上一级调用者 2 //..... 3 try{ 4 //..... 5 } 6 catch (XxxException e){ 7 //把原始异常记录下来,留给管理员查看 8 //..... 9 10 //抛出新异常,由上一级调用者处理。转译原始异常的信息,提示信息用户友好。 11 throw new XxxException("您的xxx不合法"); 12 } 13 //..... 14 }
捕获一个异常,然后接着抛出一个异常,并把原始的异常信息保存下来,这是典型的链式处理(23种设计模式之一:职责链模式,也称为异常链)。
异常跟踪栈:
异常对象的printStackTrace(),可打印异常的跟踪栈信息,开发者可据此找到异常的源头,跟踪异常一路触发的过程。
程序运行时,经常会发生一系列的方法调用,形成方法调用栈。异常的传播方向和方法调用的方向相反,总是由最内部被调用的方法传播到最外部的方法调用( 一般是main(),或者Thread类的run()——多线程情况)。
调试时,我们经常在catch中只输出/打印异常的原始信息,这方便调试,但发布程序时要避免输出异常的原始信息,而是要转换为对异常的适当处理。
不要忽略异常,要对异常做一些有用的处理,而不仅仅是在catch中打印异常信息、或者catch块直接为空。
不要在try中放置大量的代码,因为try中代码越多,出错的可能性越大,代码太多,出错后不好分析异常原因。
可以把大块的try分割为多个可能出现异常的小块的try,分别捕获并处理:
1 try{ 2 3 } 4 catch (XxxException e){ 5 6 } 7 try{ 8 9 } 10 catch (XxxException e){ 11 12 } 13 try{ 14 15 } 16 catch (XxxException e){ 17 18 }
原文链接:https://www.cnblogs.com/chy18883701161/p/10897634.html
如有疑问请与原作者联系
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
下一篇:hash系列集合的性能优化
- 国外程序员整理的Java资源大全(全部是干货) 2020-06-12
- 通过与C++程序对比,彻底搞清楚JAVA的对象拷贝 2020-06-11
- 5月到6月程序员到底经历了和什么,工资狂跌***元,你是否也 2020-06-10
- 国外程序员整理的Java资源大全(全部是干货) 2020-06-09
- Java笔记:数组,异常,泛型 2020-06-08
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash