第七章 异常
1. “程序中凡是可能出现异常的地方必须进行捕获或抛出”,这句话对吗?
一、异常的种类
java异常可以分成两大类:Exception和RuntimeException(虽然RuntimeException是从Exception继承的)。exception异常代表“无法避免的异常” 如io异常 往往这类异常是由于外部原因造成的,程序本身无法保证他们不发生,所以这类异常必须捕获。如果在函数内部无法处理这个异常必须再次抛出(在函数后面用throws语句),如果什么都不做就出现编译错误。
runtimexception是指“可以避免的异常”,如 null引用异常,这类异常都是由程序内部原因造成的,是可以避免的。对于这类异常可以忽略他们,但一旦发生程序就会异常终止。这类异常对debug非常有帮助,当然,如果需要也可以catch。
另外,有些地方即使不会有exception,但是从商业逻辑上是错误的、非预期的,也可以抛出user exception。例如,用户输入非法,bank account非法透支等等。
二、主要原则
处理意外的一个重要原则,就是要么处理,要么接着抛,决不能吃掉(You either handle it, or throw it. You don’t eat it.)这就是说,当你捕获一个异常之后,必须决定是否立即处理这个异常,或者继续抛出这个异常(或者另一个自定义异常),以便由调用的客户端捕获之。当客户端捕获到以后,又会继续进行类似的判断。
一般来说,GUI端是要处理异常的,比如JSP捕获到异常之后,需要先是给用户一个友好的出错信息,而不要给出系统的出错信息。系统的出错信息一方面不太友好,另一方面提供了太多的系统信息,容易被恶意用户用来攻击系统。
换句话说,所有的异常最终必须有一个终极的处理者,这就是GUI。至于中间的环节,比如在服务器端运行的JavaBean是否要处理捕获到的异常,还是继续抛出所捕获的异常,需要视具体情况处理。
除非你想把异常处理的责任交给调用者,一般不用throws。比如你要读入一些文件,如果你想通知调用者,让调用者决定如何处理这个异常,你就把这个异常throws给调用者;如果你知道应该如何处理这个异常,或者你想把异常马上解决,你可以就地catch她。
这完全取决于你想把异常自己立即处理还是想把处理责任返回给调用者。取决于你的程序的结构和要求。
需要注意的有:
1、如果无法处理某个异常,那就不要捕获它。
2、如果捕获了一个异常,请不要胡乱处理它。
3、尽量在靠近异常被抛出的地方捕获异常。
4、在捕获异常的地方将它记录到日志中,除非您打算将它重新抛出。
5、按照您的异常处理必须多精细来构造您的方法。
6、需要用几种类型的异常就用几种,尤其是对于应用程序异常。
三、异常嵌套和捕获适当的异常
按照Java语言的定义,所谓异常(Exception)指的就是向调用方法(calling method)表示发生非正常情况的习惯方式。下面讨论两种在处理异常时可兹利用的技术:异常嵌套和捕获适当的异常。
异常嵌套
你在试图捕获异常并打算扔出异常时该采取什么措施呢?同时,你希望原始的异常信息可用吗?
要回答以上的问题你不妨尝试一下NestedException类。具体的编程并不难,唯一要做的无非是利用构造器并且重载printStackTrace()以便显示出正确的数据。
此外,你还应当考虑封装Throwable而非Exception类来创建更具有重用性的组件。之后,你可以创建NestedRuntimeException变量封装Throwable但无需对其进行声明。
捕获适当的异常
正确地处理异常并不是一项轻松的任务,这是因为异常的处理有时会导致程序出现其他不明行为。不过,以下三条规则可以帮助你避免错误处理异常所可能遭遇的风险。
规则 #1: 总是捕获扔出异常的类型而不要理睬异常的超类。为了遵守通常的代码习惯,你可以采用Exception类的大写字母作为变量名,如下所示:
catch(FileNotFoundException fnfe)
以及
catch(SQLException sqle)
规则 # 2: 决不让catch块留空。在很多情况下虽然确实编写了try/catch块但在代码的catch部分却什么都没有做。或者,如果采用了日志API(Logging API),那么请编写代码把异常写到日志中。
规则 # 3: 决不扔出Exception基类的实例。开发人员应当总是扔出自己创建的异常类。
扔出异常的API很难处理。在声明方法扔出java.lang.Exception的情况下,所有的问题都会强加在API用户的头上,这样他们就无法以一种专业的编程方式来处理异常。通过为扔出API声明Exception类的子类这一举措,API开发人员就可以减轻用户的负担。
以上提到的两种技术在处理异常时还可能用得更好、更适当。嵌套技术令异常扔到另一异常的内部,而捕获适当的异常令程序调试大大简化。
参考:http://zhidao.baidu.com/link?url=lznhRrppPZb57u8hCsXAa1v2alsC2RYgBYdiZO-w5f-RD4AusiMd67hQYvJS7pBnBzgUk1VS6J6nKo8fg7oOgK
2. 自定义一个异常类,并在程序中主动产生这个异常类对象。
public class yichang { public static void main(String[] args) { System.out.print("Please input an Integer: "); int value = new Scanner(System.in).nextInt(); try{ if(value < 0){ throw new MyException("My Exception comes!"); } }catch (MyException myExp){ System.out.println("MyExcepton caugth!"); } } } class MyException extends Exception{ public MyException(String s){ System.out.println("MyException occurs. The value must be greater than ZERO!"); } }
3. 借助JDK帮助,请列举发生NULLPointerException异常的一些情况。
当应用程序试图在需要对象的地方使用 null 时,抛出该异常。这种情况包括:
调用 null 对象的实例方法。
访问或修改 null 对象的字段。
将 null 作为一个数组,获得其长度。
将 null 作为一个数组,访问或修改其时间片。
将 null 作为 Throwable 值抛出。
4.不执行程序,指出下面程序输出结果;如果将黑体代码去掉,写出输出结果;如果再将斜体代码去掉,写出输出结果。
public class Test { public static void aMethod() throws Exception{ try{ throw new Exception(); } //------------------黑体------------------------------------------------ catch(Exception e){ System.out.println("exception000"); } //---------------------------------------------------------------------- //--------------------斜体----------------------------------------------- finally{ System.out.println("exception111"); } //--------------------------------------------------------------------------- } public void main(String[] args){ try{ aMethod(); } catch(Exception e){ System.out.println("exception"); } System.out.println("finished"); } }
输出: exception000
exception111
finished
去黑体输出:exception111
exception
finished
去斜体输出:exception000
finished
5. 不执行程序,指出下面程序输出结果
public class Test{ public static String output =''; public static void foo(int i){ try{ if(1==1) {throw new Exception();} output += "1"; } catch(Exception e){ output += "2"; return; } finally{output += "3";} output += "4"; } public static void main(String args[]){ foo(0); foo(1); System.out.println(Test.output); } }
输出结果:13423
6.编写一个程序方法,对空指针异常、除数为零异常给出出错的中文提示。当有新异常发生时,扩展该方法中的代码进行统一处理。
public static void main(String[] args) { // 输入计算参数 Integer a = 2; Integer b = 1; try { double cc = b/(double)a; //这样才能计算小数,不会报除0错误 System.out.println("cc:"+cc); } catch (NullPointerException e) { System.out.println("空指针异常"); }catch (ArithmeticException e) { System.out.println("计算异常"); }catch (Exception e) { System.out.println("其他异常"); e.printStackTrace(); } }
7.从屏幕输入10个数,在输入错误的情况下,给出相应提示,并继续输入。在输入完成情况下,找到最大最小数。
import java.util.Scanner;
public class Input { public static void main(String[] args) { int index = 0; int[] array = new int[10]; int max,min; while (true) { if (index == array.length) { break;} Scanner sc = new Scanner(System.in); System.out.print("输入[" + (index + 1) + "]:"); try { array[index] = sc.nextInt(); index++; }
catch (Exception e) {System.out.println("输入错误,重新输入!");} } max = array[0]; min = array[0]; for (int i = 1; i < array.length; i++) { if (array[i] > max) {max = array[i];} if (array[i] < min) {min = array[i];} } System.out.println("max = " + max); System.out.println("min = " + min); } }
posted on 2015-12-04 15:55 hzau2013310200722 阅读(448) 评论(0) 编辑 收藏 举报