`

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

    博客分类:
  • 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)构造器可以抛出任何异常而不必理会基类构造器所抛出的异常,派生类构造器异常说明必须包含基类构造器异常说明,因为构造派生类对象时会调用基类构造器。此外,派生类构造器不能捕获基类构造器抛出的异常。

分享到:
评论

相关推荐

    Java 常用类解析:java异常机制,异常栈,异常处理方式,异常链,异常丢失详解

    Java 异常机制详解 Java 异常机制是 Java 语言中的一种错误处理机制...Java 异常机制是一个复杂的机制,它提供了多种异常处理方式和机制。开发者需要了解 Java 异常机制的原理和使用方法,以便更好地编写 Java 程序。

    java 异常处理

    1. **异常处理的机制**:Java异常处理的核心在于“抛出”和“捕获”两个概念。当程序运行时遇到异常(通常是逻辑错误或系统错误),会创建一个异常对象并抛出。此时,运行时系统会尝试寻找相应的捕获块来处理这个...

    Java 异常1

    运行时异常和受检查异常的主要区别在于处理方式和编译要求。运行时异常是程序设计错误,通常建议立即终止程序,因为这些错误意味着程序状态已经破坏,继续执行可能导致更严重的问题。受检查异常则是期望程序员能够...

    程序崩溃自动重启以及将未捕获到的异常写退出栈

    当程序由于未捕获的异常而崩溃时,通常会丢失当前的堆栈信息,这使得定位问题变得困难。为了解决这个问题,我们可以编写一个全局的异常处理器,该处理器在异常发生时捕获异常,并在控制台上打印详细的堆栈跟踪信息。...

    Java常见异常总结

    为了帮助开发者更好地理解和处理这些异常,本文将深入探讨一系列常见的Java异常,涵盖从基本的`ArithmeticException`到复杂的`TypeInitializationException`,以及一些特定于类型或操作的异常。通过理解每种异常的...

    JAVA程序员最常遇见的10个异常

    在Java编程中,异常处理是十分重要的一个环节,它能够帮助开发者及时发现并解决程序运行时出现的问题。本文将详细介绍Java程序员经常遇到的10种常见异常,并对其进行深入分析。 #### 1. `java.lang....

    java错误大全,详细解释

    Java编程语言在开发过程中,程序员经常会遇到各种类型的错误。这些错误可以分为编译错误、运行时错误和逻辑错误。...此外,深入学习和理解Java异常处理机制,对理解和处理开源框架中的异常也至关重要。

    java做的记事本

    8. **异常处理**:为了确保程序的稳定性和健壮性,Java的异常处理机制(try-catch-finally)必不可少。在处理文件操作或网络通信时,异常处理尤为重要。 9. **调试与测试**:开发过程中,单元测试和集成测试是必不...

    JAVA面试题2019

    7. **异常处理**:Java中的异常分类(运行时异常和检查异常)及其处理机制。 8. **线程同步**:`synchronized` 关键字的实现原理和锁优化策略。 9. **volatile关键字**:保证可见性和禁止指令重排的作用。 10. **...

    java调用C++ webservice

    - 错误处理是关键,需要处理网络、SOAP解析、服务端异常等可能的问题。 - 注意不同平台之间的编码差异,确保数据传输过程中不丢失或错误。 6. **示例代码**: - 假设已生成了名为`WebServiceClientStub.java`的...

    CoreJava笔记.doc

    - Java中的异常处理机制主要包括`try`、`catch`、`finally`等关键字。 **8.2 捕获异常** - 使用`try...catch`语句捕获异常。 - 可以指定多个`catch`块来处理不同类型的异常。 **8.3 处理异常** - 处理异常通常是...

    java学生信息管理系统

    2. 异常处理:良好的异常处理机制能有效避免程序因错误崩溃,提升系统的稳定性。 3. 用户体验:优化界面设计,使操作流程更加直观,提高用户的使用满意度。 五、未来拓展与升级 1. 权限管理:添加用户角色和权限...

    java_性能调优.pdf

    在Java中,try/catch块用于捕获和处理异常,减少程序因异常终止而造成的资源泄漏或数据丢失。正确使用异常处理是编写健壮代码的重要部分,但也不应该滥用,因为过度捕获异常可能会掩盖真正的错误。 在JDBC部分,...

    完整的java面试题

    针对“完整的java面试题”这个主题,我们可以深入探讨Java的核心概念、语法特性、内存管理、多线程、集合框架、异常处理、IO流、网络编程、反射机制、JVM优化等多个方面。 1. **核心概念与语法** - **类与对象**:...

    java Tcp协议验证

    Java的Socket API虽然没有直接暴露这些窗口机制,但可以通过异常处理(如`SocketException`)来捕获网络问题并采取重传策略。 TCP校验和是确保数据完整性的手段之一。它对整个TCP头和数据部分进行计算,以检测传输...

    简易QQ聊天系统java版

    8. **错误处理与异常捕获**:任何网络程序都应具备良好的错误处理机制。Java的try-catch-finally语句块用于捕获和处理可能出现的异常,保证程序的稳定运行。 9. **设计模式**:为了实现可扩展性和模块化,设计模式...

    java网络聊天工具

    6. **异常处理**:网络通信中,错误和异常是常见的,因此需要良好的异常处理机制来确保程序的健壮性。例如,处理连接丢失、数据传输错误等情况。 7. **多线程编程**:为了提高性能和用户体验,服务端和客户端都可能...

    常问的java 面试题(适合秋招春招)

    2. **Java异常处理**: - **`throws`**:在方法签名上使用`throws`关键字声明方法可能抛出的异常,这样调用者必须处理这些异常或者在调用方法时也声明抛出相同的异常。 - **`try-catch`**:通过`try`块捕获可能...

    基于java聊天室(gui)

    TCP(传输控制协议)是互联网协议栈中最关键的协议之一,它确保了数据在网络中的可靠传输,通过建立连接、分段数据、确认接收以及重传丢失的数据来实现这一目标。IP(网际协议)则负责将数据包从源主机发送到目标...

    java源码Java聊天室程序(java)

    3. **异常处理**:在网络编程中,异常处理尤为重要。程序需要能够妥善处理各种可能出现的问题,如连接中断、数据包丢失等。 4. **用户界面设计**:对于前端部分,需要利用Swing或JavaFX等工具库来设计美观且易于使用...

Global site tag (gtag.js) - Google Analytics