首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

java错误机制、错误栈、错误处理方式、错误链、错误丢失

2014-01-13 
java异常机制、异常栈、异常处理方式、异常链、异常丢失1、java标准异常概述Throwable表示任何可以作为异常被抛

java异常机制、异常栈、异常处理方式、异常链、异常丢失

1、java标准异常概述

Throwable表示任何可以作为异常被抛出的类,有两个子类Error和Exception。从这两个类的源代码中可以看出,这两个类并没有添加新的方法,Throwable提供了所以方法的实现。Error表示编译时和系统错误。Exception是可以被抛出的异常类。RuntimeException继承自Exception(如NullPointerException),表示运行时异常,JVM会自动抛出.

2、自定义异常类

自定义异常类方法:?通过继承Throwable或Exception。异常类的所有实现都是基类Throwable实现的,所以构造自定义异常类完全可以参考Exception和Error类。我们只要添加上自定义异常类的构造方法就可以了

[java]?view plaincopy?
  1. <span?style="font-size:16px;">package?demo.others;??
  2. ??
  3. /**?
  4. ?*?自定义异常类方法?
  5. ?*?1、通过继承Throwable?
  6. ?*?2、通过继承Exception?
  7. ?*??
  8. ?*?@author?Touch?
  9. ?*/??
  10. public?class?MyExceptionDemo?extends?Exception?{??
  11. ??
  12. ????private?static?final?long?serialVersionUID?=?1L;??
  13. ??
  14. ????public?MyExceptionDemo()?{??
  15. ????????super();??
  16. ????}??
  17. ??
  18. ????public?MyExceptionDemo(String?message)?{??
  19. ????????super(message);??
  20. ????}??
  21. ??
  22. ????public?MyExceptionDemo(String?message,?Throwable?cause)?{??
  23. ????????super(message,?cause);??
  24. ????}??
  25. ??
  26. ????public?MyExceptionDemo(Throwable?cause)?{??
  27. ????????super(cause);??
  28. ????}??
  29. }??
  30. </span>??


?

3、异常栈及异常处理方式

可以通过try、catch来捕获异常。捕获到的异常。下面的示例演示了几种常用异常处理方式

[java]?view plaincopy?
  1. <span?style="font-size:16px;">package?demo.others;??
  2. ??
  3. import?mine.util.exception.MyException;??
  4. ??
  5. public?class?ExceptionDemo1?{??
  6. ????public?void?f()?throws?MyException?{??
  7. ????????throw?new?MyException("自定义异常");??
  8. ????}??
  9. ??
  10. ????public?void?g()?throws?MyException?{??
  11. ????????f();??
  12. ????}??
  13. ??
  14. ????public??void?h()?throws?MyException??{??
  15. ????????try?{??
  16. ????????????g();??
  17. ????????}?catch?(MyException?e)?{??
  18. ????????????//1、通过获取栈轨迹中的元素数组来显示异常抛出的轨迹??
  19. ????????????for?(StackTraceElement?ste?:?e.getStackTrace())??
  20. ????????????????System.out.println(ste.getMethodName());??
  21. ????????????//2、直接将异常栈信息输出至标准错误流或标准输出流??
  22. ????????????e.printStackTrace();//输出到标准错误流??
  23. ????????????e.printStackTrace(System.err);??
  24. ????????????e.printStackTrace(System.out);??
  25. ????????????//3、将异常信息输出到文件中??
  26. ????????????//e.printStackTrace(new?PrintStream("file/exception.txt"));??
  27. ????????????//4、重新抛出异常,如果直接抛出那么栈路径是完整的,如果用fillInStackTrace()??
  28. ????????????//那么将会从这个方法(当前是h()方法)作为异常发生的原点。??
  29. ????????????//throw?e;??
  30. ????????????throw?(MyException)e.fillInStackTrace();??
  31. ????????}??
  32. ????}??
  33. ????public?static?void?main(String[]?args)?{??
  34. ????????????try?{??
  35. ????????????????new?ExceptionDemo1().h();??
  36. ????????????}?catch?(MyException?e)?{??
  37. ????????????????//?TODO?Auto-generated?catch?block??
  38. ????????????????e.printStackTrace();??
  39. ????????????}??
  40. ????}??
  41. }??
  42. </span>??

运行结果:

f
g
h
main
mine.util.exception.MyException: 自定义异常
?at demo.others.ExceptionDemo1.f(ExceptionDemo1.java:7)
?at demo.others.ExceptionDemo1.g(ExceptionDemo1.java:11)
?at demo.others.ExceptionDemo1.h(ExceptionDemo1.java:16)
?at demo.others.ExceptionDemo1.main(ExceptionDemo1.java:35)
mine.util.exception.MyException: 自定义异常
?at demo.others.ExceptionDemo1.f(ExceptionDemo1.java:7)
?at demo.others.ExceptionDemo1.g(ExceptionDemo1.java:11)
?at demo.others.ExceptionDemo1.h(ExceptionDemo1.java:16)
?at demo.others.ExceptionDemo1.main(ExceptionDemo1.java:35)
mine.util.exception.MyException: 自定义异常
?at demo.others.ExceptionDemo1.f(ExceptionDemo1.java:7)
?at demo.others.ExceptionDemo1.g(ExceptionDemo1.java:11)
?at demo.others.ExceptionDemo1.h(ExceptionDemo1.java:16)
?at demo.others.ExceptionDemo1.main(ExceptionDemo1.java:35)
mine.util.exception.MyException: 自定义异常
?at demo.others.ExceptionDemo1.h(ExceptionDemo1.java:30)
?at demo.others.ExceptionDemo1.main(ExceptionDemo1.java:35)

分析上面的程序,首先main函数被调用,然后是调用h函数,再g函数、f函数,f函数抛出异常,并在h函数捕获,这时将依次从栈顶到栈底输出异常栈路径。

4、异常链

有时候我们会捕获一个异常后在抛出另一个异常,如下代码所示:

[java]?view plaincopy?
  1. <span?style="font-size:16px;">package?demo.others;??
  2. ??
  3. import?java.io.IOException;??
  4. ??
  5. import?mine.util.exception.MyException;??
  6. ??
  7. public?class?ExceptionDemo2?{??
  8. ????public?void?f()?throws?MyException?{??
  9. ????????throw?new?MyException("自定义异常");??
  10. ????}??
  11. ??
  12. ????public?void?g()?throws?Exception??{??
  13. ????????try?{??
  14. ????????????f();??
  15. ????????}?catch?(MyException?e)?{??
  16. ????????????e.printStackTrace();??
  17. ????????????throw?new?Exception("重新抛出的异常1");??
  18. ????????}??
  19. ????}??
  20. ??
  21. ????public??void?h()?throws?IOException????{??
  22. ????????try?{??
  23. ????????????g();??
  24. ????????}?catch?(Exception?e)?{??
  25. ????????????//?TODO?Auto-generated?catch?block??
  26. ????????????e.printStackTrace();??
  27. ????????????throw?new?IOException("重新抛出异常2");??
  28. ????????}??
  29. ????}??
  30. ????public?static?void?main(String[]?args)?{??
  31. ????????????try?{??
  32. ????????????????new?ExceptionDemo2().h();??
  33. ????????????}?catch?(IOException?e)?{??
  34. ????????????????//?TODO?Auto-generated?catch?block??
  35. ????????????????e.printStackTrace();??
  36. ????????????}??
  37. ????}??
  38. }??
  39. </span>??


运行结果:

mine.util.exception.MyException: 自定义异常
?at demo.others.ExceptionDemo2.f(ExceptionDemo2.java:9)
?at demo.others.ExceptionDemo2.g(ExceptionDemo2.java:14)
?at demo.others.ExceptionDemo2.h(ExceptionDemo2.java:23)
?at demo.others.ExceptionDemo2.main(ExceptionDemo2.java:32)
java.lang.Exception: 重新抛出的异常1
?at demo.others.ExceptionDemo2.g(ExceptionDemo2.java:17)
?at demo.others.ExceptionDemo2.h(ExceptionDemo2.java:23)
?at demo.others.ExceptionDemo2.main(ExceptionDemo2.java:32)
java.io.IOException: 重新抛出异常2
?at demo.others.ExceptionDemo2.h(ExceptionDemo2.java:27)
?at demo.others.ExceptionDemo2.main(ExceptionDemo2.java:32)

从结果中我们可以看出,异常栈变小了。也就是说丢失了最原始的异常信息。怎样保存最原始的异常信息呢?Throwable类中有个Throwable? cause属性,表示原始异常。通过接收cause参数的构造器可以把原始异常传递给新异常,或者通过initCause()方法。如下示例:

[java]?view plaincopy?
  1. <span?style="font-size:16px;">package?demo.others;??
  2. ??
  3. import?java.io.IOException;??
  4. ??
  5. import?mine.util.exception.MyException;??
  6. ??
  7. public?class?ExceptionDemo2?{??
  8. ????public?void?f()?throws?MyException?{??
  9. ????????throw?new?MyException("自定义异常");??
  10. ????}??
  11. ??
  12. ????public?void?g()?throws?Exception??{??
  13. ????????try?{??
  14. ????????????f();??
  15. ????????}?catch?(MyException?e)?{??
  16. ????????????e.printStackTrace();??
  17. ????????????throw?new?Exception("重新抛出的异常1",e);??
  18. ????????}??
  19. ????}??
  20. ??
  21. ????public??void?h()?throws?IOException????{??
  22. ????????try?{??
  23. ????????????g();??
  24. ????????}?catch?(Exception?e)?{??
  25. ????????????//?TODO?Auto-generated?catch?block??
  26. ????????????e.printStackTrace();??
  27. ????????????IOException?io=new?IOException("重新抛出异常2");??
  28. ????????????io.initCause(e);??
  29. ????????????throw?io;??
  30. ????????}??
  31. ????}??
  32. ????public?static?void?main(String[]?args)?{??
  33. ????????????try?{??
  34. ????????????????new?ExceptionDemo2().h();??
  35. ????????????}?catch?(IOException?e)?{??
  36. ????????????????//?TODO?Auto-generated?catch?block??
  37. ????????????????e.printStackTrace();??
  38. ????????????}??
  39. ????}??
  40. }??
  41. </span>??


?

结果:

mine.util.exception.MyException: 自定义异常
?at demo.others.ExceptionDemo2.f(ExceptionDemo2.java:9)
?at demo.others.ExceptionDemo2.g(ExceptionDemo2.java:14)
?at demo.others.ExceptionDemo2.h(ExceptionDemo2.java:23)
?at demo.others.ExceptionDemo2.main(ExceptionDemo2.java:34)
java.lang.Exception: 重新抛出的异常1
?at demo.others.ExceptionDemo2.g(ExceptionDemo2.java:17)
?at demo.others.ExceptionDemo2.h(ExceptionDemo2.java:23)
?at demo.others.ExceptionDemo2.main(ExceptionDemo2.java:34)
Caused by: mine.util.exception.MyException: 自定义异常
?at demo.others.ExceptionDemo2.f(ExceptionDemo2.java:9)
?at demo.others.ExceptionDemo2.g(ExceptionDemo2.java:14)
?... 2 more
java.io.IOException: 重新抛出异常2
?at demo.others.ExceptionDemo2.h(ExceptionDemo2.java:27)
?at demo.others.ExceptionDemo2.main(ExceptionDemo2.java:34)
Caused by: java.lang.Exception: 重新抛出的异常1
?at demo.others.ExceptionDemo2.g(ExceptionDemo2.java:17)
?at demo.others.ExceptionDemo2.h(ExceptionDemo2.java:23)
?... 1 more
Caused by: mine.util.exception.MyException: 自定义异常
?at demo.others.ExceptionDemo2.f(ExceptionDemo2.java:9)
?at demo.others.ExceptionDemo2.g(ExceptionDemo2.java:14)
?... 2 more

从结果中看出当获取到“重新抛出异常2的时候,同时可以输出原始异常“重新抛出的异常1“和原始异常”自定义异常,这就是异常链。

5、finally的使用

finally子句总是执行的,通常用来做一些清理工作,如关闭文件,关闭连接等

下面举几个finally的例子:

[java]?view plaincopy?
  1. <span?style="font-size:16px;">//?读取指定路径文本文件??
  2. ????public?static?String?read(String?filePath)?{??
  3. ????????StringBuilder?str?=?new?StringBuilder();??
  4. ????????BufferedReader?in?=?null;??
  5. ????????try?{??
  6. ????????????in?=?new?BufferedReader(new?FileReader(filePath));??
  7. ????????????String?s;??
  8. ????????????try?{??
  9. ????????????????while?((s?=?in.readLine())?!=?null)??
  10. ????????????????????str.append(s?+?'\n');??
  11. ????????????}?finally?{??
  12. ????????????????in.close();??
  13. ????????????}??
  14. ????????}?catch?(IOException?e)?{??
  15. ????????????//?TODO?Auto-generated?catch?block??
  16. ????????????e.printStackTrace();??
  17. ????????}??
  18. ????????return?str.toString();??
  19. ????}</span>??

分析:如果调用in = new BufferedReader(new FileReader(filePath));时发生异常,这时是一个文件路径不存在的异常,也就是说并没有打开文件,这时将会直接跳到catch块,而不会执行try...finally块(并不是finally子句)里面的语句in.close();此时不需要关闭文件。

再看一个例子,会导致异常的丢失

[java]?view plaincopy?
  1. <span?style="font-size:16px;">package?demo.others;??
  2. ??
  3. import?mine.util.exception.MyException;??
  4. ??
  5. public?class?ExceptionDemo3?{??
  6. ????public?void?f()?throws?MyException?{??
  7. ????????throw?new?MyException("异常1");??
  8. ????}??
  9. ??
  10. ????public?void?g()?throws?MyException?{??
  11. ????????throw?new?MyException("异常2");??
  12. ????}??
  13. ??
  14. ????public?static?void?main(String[]?args)?{??
  15. ??
  16. ????????try?{??
  17. ????????????ExceptionDemo3?ex?=?new?ExceptionDemo3();??
  18. ????????????try?{??
  19. ????????????????ex.f();??
  20. ????????????}?finally?{??
  21. ????????????????ex.g();//此时捕获g方法抛出的异常,f方法抛出的异常丢失了??
  22. ????????????}??
  23. ????????}?catch?(MyException?e)?{??
  24. ????????????System.out.println(e);??
  25. ????????}??
  26. ??
  27. ????}??
  28. }??
  29. </span>??

结果:mine.util.exception.MyException: 异常2

此时异常1就丢失了
或者这样写:

[java]?view plaincopy?
  1. <span?style="font-size:16px;">package?demo.others;??
  2. ??
  3. import?mine.util.exception.MyException;??
  4. ??
  5. public?class?ExceptionDemo3?{??
  6. ??
  7. ????public?void?g()?throws?MyException?{??
  8. ????????throw?new?MyException("异常2");??
  9. ????}??
  10. ??
  11. ????public?static?void?main(String[]?args)?{??
  12. ????????ExceptionDemo3?ex?=?new?ExceptionDemo3();??
  13. ????????try?{??
  14. ????????????ex.g();??
  15. ????????}?finally?{??
  16. ????????????//直接return会丢失所以抛出的异常??
  17. ????????????return;??
  18. ????????}??
  19. ??
  20. ????}??
  21. }??
  22. </span>??

6、异常的限制

(1)当覆盖方法时,只能抛出在基类方法的异常说明里列出的那些异常,有些基类的方法声明抛出异常其实并没有抛出异常,这是因为可能在其子类的覆盖方法中会抛出异常

(2)构造器可以抛出任何异常而不必理会基类构造器所抛出的异常,派生类构造器异常说明必须包含基类构造器异常说明,因为构造派生类对象时会调用基类构造器。此外,派生类构造器不能捕获基类构造器抛出的异常。

热点排行