异常
文章来自 shichang // Welcome!
主页
|
About Me
|
归档
|
标签
### 抛出异常 异常抛出后,后面的语句将不会执行 ```java throw new Exception(); ``` 执行过程:使用new在堆上创建异常对象,当前的执行路径被终止,从当前的执行环境中弹出异常对象的引用,异常处理机制接管程序,并寻找一个恰当的地方继续执行程序。一切都是为了保证程序从错误状态恢复。 ### 异常体系 ``` Throwable——>Error——>StackOverflowError | |——>OutOfMemoryError | |——>Exception——>IOException |——>RuntimeException |——>ClassNotFoundException |——>CloneNotSupportedException ``` Error表示编译错误和系统错误 Exception表示程序在运行过程中遇到的错误 ### 两种Error情况 一,我们的StackOverflowError,方法栈溢出时发生,一般是程序中存在无限递归和无限循环。二,我们的OutOfMemoryError,这是虚拟机内存不足的错误,虚拟机有几块区域都可能内存不足,第一种永久代(方法区)溢出,方法区主要加载类的信息,发生方法区溢出一般是程序中的jar和class文件太多。第二种是堆区溢出, ### 异常参数 Exception类的构造器有两种,一种无参,一种允许一个String类型的参数 Throwable类的一些方法: String getMessage() String getLocalizedMessage() 得到异常的详细信息 String toString() void printStackTrance() void printStackTrance(PrintStream) void printStackTrance(java.io.PrintWriter) 输出异常以及调用栈轨迹 StackTraceElement[] Exception.getStackTrace() StackTraceElement[].getMethodName() ### 捕获异常 监控区域:try-catch-finally catch语句块可以有多个,块内为异常处理语句 可以省略catch或是finally即try-catch或者try-finally ### 终止模型和恢复模型 终止模型:java支持终止模型,认为错误非常关键,程序一旦出现异常抛出,便无法再返回异常处继续执行 恢复模型:出现异常时,调用方法修正错误,重新运行出现错误的语句,认为第二次可以运行成功。比如将try块放在while循环中 ### 自定义异常 继承Exception类,重写构造方法,或者增添额外的成员参数 ```java class MyException extends Exception{ public MyException(String msg){ super(msg); } } class MyException2 extends Exception{ int code; public MyException2(String msg, int code){ super(msg); this.code = code; } } ``` ### 异常日志记录 通过java.util.logging工具,显示异常捕获的时间,从方法调用的地方直到异常发生的地方 ```java class MyExceptionLogging{ private static Logger logger = Logger.getLogger("String参数"); static void logException(Exception e){ StringWriter sw = new StringWriter(); e.printStackTrace(new PrintWriter(sw)); logger.severe(sw.toString()); } } ... catch(MyException e){ logException(e); } ``` ### 异常说明 若在方法内部抛出了异常,则必须在方法参数后用**throws**说明异常。不然编译不会通过。可以声明抛出异常,但实际上不抛出。RuntimeException不需要进行异常说明 ```java void test()**throws MyException**{ throw new MyException(); } ``` ### 捕获所有异常 ```java catch(Exception e){} ``` ### 重新抛出异常 捕捉异常的方法嵌套调用。 下面第一种方法,抛出的是原来异常抛出点的调用栈信息 第二种方法调用了fillInStackTrace()方法,这个方法将返回一个新的Throwable对象,将当前的调用栈信息填入原来的异常对象即产生这个新异常对象,原来的异常发生点信息会丢失,调用这个方法的地方将成为新的异常发生处 ```java 1. catch(Exception e){ throw e; } 2. catch(Exception e){ throw (Exception)e.fillINStackTrace(); } ``` ### 异常链 将异常连接起来,当A异常发生时,表明是由于发生了B异常才导致的A异常。 在Throwable中,只有Error,Exception,RuntimeException拥有带*cause*参数的构造器,要将其他异常连接起来,需要使用initCause()方法 ```java MyException myep = new MyException(); myep.initCause(new 其他Exception()); throw myep; 结果: Myexception at ---(name.java:row) at ---(name.java:row) Caused by:其他Exception at ---(name.java:row) ... ``` ### 检查异常和不检查异常 UnCheckedException:Error和RuntimeException,在程序中不必捕获。我们认为只要代码设计合理就不会发生的异常 CheckedException:需要在程序中进行捕获的异常。即使代码设计的合理也可能会存在的异常,比如文件与网络相关 #### 运行时异常runtimeException ArraysIndexOutOfBoundsException 数组索引越界 StackOverFlowException 栈溢出 NullPointerException 空指针 EmptyStackException 空栈 IllegalArgumentException 不合法参数 IndexOutOfBoundsException 索引越界 UnSupportedOperationException 不支持的操作 IllegalStatusException 不合法状态 ArithmeticException 除数为0异常 NoSuchElementException 没有这个元素 ClassCastException 类转换异常 ### 使用finally语句进行清理 try-catch-finally语句块中finally语句块是必须要执行的代码,无论是否抛出了异常,也不管前面是否已经发生了break或者return。 当try-catch-finally语句块加在while循环中时,finally语句块可以保持一个“程序继续循环之前必须要达到”的条件,或者是加一个static的计数器,使循环能达到一定的次数 **finally的一般用途:**把除内存之外的资源恢复到初始状态,比如已经打开的文件或网络连接,屏幕上的图形,某个其他物件的开关 ### 异常丢失 情况1:嵌套捕捉:外层是try-catch,内层是try-finally。在内层try中发生了异常,没有进行catch捕捉,而finally语句中又发生了第二个异常。最终外层catch语句只捕捉到内层finally块产生的异常,内层try块的异常丢失了 情况2:try-finally语句块,try块产生了异常,没有处理,finally语句块中直接return。异常丢失。 情况3:多方法嵌套try-catch语句块互相调用,try中发生了异常,catch语句块中又抛出了新的异常,这样会丢失原始try中发生的异常 ### 异常的限制 情况1:父类与接口有同样的方法但是有不同的异常说明,在子类中重写这个方法时只有不进行异常说明,否则都会报错。(普通方法,非构造方法) 情况2:关于构造方法,子类构造器的异常说明必须完全包含父类构造器的异常说明,可多不可少 情况3:对于普通方法,子类重写的方法不用管父类这个方法的异常说明,完全随意,想抛啥抛啥 补充:1.子类构造器不能捕获父类构造器抛出的异常。2.异常说明不能作为方法重载的区分 ### 构造器的异常处理 尝试使用在try-catch内部嵌套try-catch-finally语句 ```java public class Cleanup{ public static void main(String[]args){ try{ InputFile in = new InputFile("ok.java"); try{ String s = in.getLine(); }catch(Exception e){ e.printStackTrace(System.out); }finally{ in.close(); } }catch(Exception e){ sout("InputFile构建失败"); } } } ``` 若构建成功才执行close()方法,构建失败则直接抛出异常 基本规则就是:在创建需要清理的对象之后(如文件),立马进入一个try-finally语句块 ### 异常匹配 抛出异常时,系统会按照就近原则选择离该异常最近的处理处理程序(对应)。子类异常的对象也可以匹配父类异常的处理程序。如果把父类异常的处理程序放在最throw的最近处,将其子类异常的处理程序放在后面,则后面的子类处理程序将永远得不到运行,系统会叫你删除掉或是移动到前面去 ### 异常处理实践 [mvc异常处理实践](https://cloud.tencent.com/developer/news/257118)
Pre:
HTTP缓存机制
Next:
设计模式-单例模式