Thinking In Java 学习笔记 12.通过异常处理错误

异常 Exception
Exception是所有与编程有关的异常类的基类
抛出异常,当前情况解决不了的问题,传给上一级
标准异常类有默认构造器和接受String参数的构造器。
异常类型根类是Throwable,通过throw抛出异常
在方法内设置一个特殊的块用来捕获异常,即try块,使程序能继续运行
异常处理程序 catch子句紧跟try,只有匹配的catch子句才会执行。
终止模型,异常被抛出,程序终止
日志 logger
回复模型,不常用

异常声明 例如 void f() throws Exception1,Exception2{ }
调用栈轨迹 printStackTrace
捕获所有异常 catch( Exception e ) 一般用在程序列表末尾
e.printStackTrace();显示原抛出点信息,调用fillInStackTrace()方法填入当前调用栈信息,再printStackTrace()
异常链,捕获一个异常后抛出一个异常,并保存原始异常信息,Throwable的子类(三个基本异常类)提供带cause参数的构造器。Error、Exception、RuntimeException。
预编译异常和常用异常
运行时异常 继承自 RuntimeException 不受检查异常,这种异常属于错误。
只能在代码中忽略RuntimeException 。其他异常处理都是强制实施的。
RuntimeException代表编程错误,包括无法预料的错误和应该在代码中检查的错误。
无论异常是否被抛出,finally子句总能被执行。
在finally中抛出异常或在finally中return,可能会造成异常丢失。
异常跟错误的区分
  在 Java 中,所有的异常都有一个共同的祖先 Throwable(可抛出)。
  Throwable 有两个重要的子类:Exception(异常)和 Error(错误),二者都是 Java 异常处理的重要子类,各自都包含大量子类。 
  ①.Exception(异常)是应用程序中可能的可预测、可恢复问题。一般大多数异常表示中度到轻度的问题。异常一般是在特定环境下产生的,通常出现在代码的特定方法和操作中。
    Exception 类有一个重要的子类 RuntimeException。RuntimeException 类及其子类表示“JVM 常用操作”引发的错误。例如,若试图使用空值对象引用、除数为零或数组越界,则分别引发运行时异常(NullPointerException、ArithmeticException)和 ArrayIndexOutOfBoundException。
②.Error(错误)表示运行应用程序中较严重问题。大多数错误与代码编写者执行的操作无关,而表示代码运行时 JVM(Java 虚拟机)出现的问题。例如,当 JVM 不再有继续执行操作所需的内存资源时,将出现OutOfMemoryError。 
检查异常 和 未检查异常 的划分

Java中的异常分为两大类:
  1.Checked Exception(非Runtime Exception)
  2.Unchecked Exception(Runtime Exception)
运行时异常
 RuntimeException类是Exception类的子类,它叫做运行时异常,Java中的所有运行时异常都会直接或者间接地继承自RuntimeException类。
  Java中凡是继承自Exception,而不继承自RuntimeException类的异常都是非运行时异常。
  一个try后面可以跟多个catch,但不管多少个,最多只会有一个catch块被执行。
对于非运行时异常(checked exception),必须要对其进行处理,否则无法通过编译。
  处理方式有两种:
  1.使用try..catch..finally进行捕获;
  2.在产生异常的方法声明后面写上throws 某一个Exception类型,如throws Exception,将异常抛出到外面一层去。
对于运行时异常(runtime exception),可以对其进行处理,也可以不处理。推荐不对运行时异常进行处理。
扩展:错误和异常的区别(Error vs Exception) 
  1).java.lang.Error: Throwable的子类,用于标记严重错误。合理的应用程序不应该去try/catch这种错误。绝大多数的错误都是非正常的,就根本不该出现的。
     java.lang.Exception: Throwable的子类,用于指示一种合理的程序想去catch的条件。即它仅仅是一种程序运行条件,而非严重错误,并且鼓励用户程序去catch它。
  2).Error和RuntimeException 及其子类都是未检查的异常(unchecked exceptions),而所有其他的Exception类都是检查了的异常(checked exceptions).
    checked exceptions: 通常是从一个可以恢复的程序中抛出来的,并且最好能够从这种异常中使用程序恢复。比如FileNotFoundException, ParseException等。检查了的异常发生在编译阶段,必须要使用try…catch(或者throws)否则编译不通过。
    unchecked exceptions: 通常是如果一切正常的话本不该发生的异常,但是的确发生了。发生在运行期,具有不确定性,主要是由于程序的逻辑问题所引起的。比如ArrayIndexOutOfBoundException, ClassCastException等。从语言本身的角度讲,程序不该去catch这类异常,虽然能够从诸如RuntimeException这样的异常中catch并恢复,但是并不鼓励终端程序员这么做,因为完全没要必要。因为这类错误本身就是bug,应该被修复,出现此类错误时程序就应该立即停止执行。 因此,面对Errors和unchecked exceptions应该让程序自动终止执行,程序员不该做诸如try/catch这样的事情,而是应该查明原因,修改代码逻辑。
    RuntimeException:RuntimeException体系包括错误的类型转换、数组越界访问和试图访问空指针等等。
处理RuntimeException的原则是:如果出现 RuntimeException,那么一定是程序员的错误。例如,可以通过检查数组下标和数组边界来避免数组越界访问异常。其他(IOException等等)checked异常一般是外部错误,例如试图从文件尾后读取数据等,这并不是程序本身的错误,而是在应用环境中出现的外部错误。
重新抛出异常、finally的使用,return跟finally关系
重新抛出异常,捕获e后再 throw e;会再次抛给上一级,同一个try块的后续catch将被忽略。
The finally Block
The finally block always executes when the try block exits. This ensures that the finally block is executed even if an unexpected exception occurs. But finally is useful for more than just exception handling — it allows the programmer to avoid having cleanup code accidentally bypassed by a return,continue, or break. Putting cleanup code in a finally block is always a good practice, even when no exceptions are anticipated.

finally 语句块应该是在控制转移语句之前执行,在执行 subroutine(也就是 finally 语句块)之前,try 或者 catch 语句块会保留其返回值到本地变量表(Local Variable Table)中。待 subroutine 执行完毕之后,再恢复保留的返回值到操作数栈中,然后通过 return 或者 throw 语句将其返回给该方法的调用者(invoker)


方法名字只由方法名和参数类型组成。
一个在基类方法异常说明中出现的异常,在子类异常说明中不一定出现。
子类中只能出现父类声明的异常或其子类异常。
基类处理程序catch 可以捕获子类异常。
将被检查的异常包装进RuntimeException
catch(Exception1 e){
throw new RuntimeException(e);
}

猜你喜欢

转载自blog.csdn.net/jjj1299894209/article/details/80894709