thinking in java笔记 12 异常

***基本概念
    使用异常的好处是,它往往能够降低错误处理代码的复杂度。如果不使用异常,就必须检查特定的错误,在程序的很多地方进行处理。而使用异常则不必在方法调用处进行检查,因为异常机制能够捕获这个错误,并且只需在一个地方处理。而且能把执行过程代码和错误处理代码相分离。

*** Checked vs UnChecked 异常
除了Error与RuntimeException,其他剩下的异常都是你需要关心的,而这些异常类统称为Checked Exception,至于Error与RuntimeException则被统称为Unchecked Exception.

***基本异常
    当抛出异常后,java会使用new在堆上创建异常对象。然后当前的执行路径被终止,并且从当前环境中弹出对异常对象的引用,此时,异常处理机制接管程序,并开始寻找一个恰当的地方来继续执行程序,这个恰当的地方就是异常处理程序,它的任务是将程序从错误状态中恢复,以使得程序要么换一种方式运行,要么继续运行下去。
    异常使得我们可以将每件事都当做一个事务来考虑,异常可以看护着这些事务的底线。
    异常最重要的方面之一是如果发生问题,我们将不允许程序沿着其正常的路径继续走下去。

***异常说明
    应把方法可能会抛出的异常告知使用此方法的客户端程序员。使用 throws  关键字
     void B() throws NewException{
throw new NewException();
}


***异常日志
    自定义异常类中,可以自动记录日志信息;
class LoggingException extends Exception {
private static Logger logger = Logger.getLogger("LoggingException");

public LoggingException() {
StringWriter trace = new StringWriter();
printStackTrace(new PrintWriter(trace));
logger.severe(trace.toString());
}
}
    
     更多的时候不是自定义异常类,而是捕获别人的异常,记录日志的方法如下:
public class LoggingExceptions2 {
private static Logger logger = Logger.getLogger("LoggingExceptions2");

static void logException(Exception e) {
StringWriter trace = new StringWriter();
e.printStackTrace(new PrintWriter(trace));
logger.severe(trace.toString());
}

public static void main(String[] args) {
try {
throw new NullPointerException();
} catch (NullPointerException e) {
logException(e);
}
}
}



***重新抛出异常
    如果只是把当前异常对象重新抛出,那么printStackTrace()显示的将是原来异常抛出点的调用栈信息,而非重新抛出点的信息。想要更新此信息,可以采用 throw (Exception)e.fillInStackTrace();

***异常链
    在捕获一个异常后抛出另一个异常,并把原始异常的信息保存下来,称为异常链。Throwable的子类中,三种基本的异常类提供了带cause参数的构造器(Error Exception RuntimeException),其他类型的异常,应该使用initCause()方法。

***Java标准异常
    Throwable对象分为两种类型:Error表示编译时和系统错误。Exception是可以被抛出的基本类型。

***RuntimeException
    运行时异常(包含RuntimeException及其子类)(不受检查异常)会自动被java虚拟机抛出,所以不必在异常说明中列出。这种异常属于错误,将被自动捕获。如果RuntimeException没有被捕获而直达main(),那么在程序退出前将调用异常的printStackTrace()方法。    
    RuntimeException代表的是编程错误:
    1 无法预料的错误,比如在控制范围之外传递进来的null引用。
    2 应该在代码中进行检查的错误。

***finally
    用处:把除内存之外的资源恢复到初始状态,如打开的文件或网络连接,在屏幕上画的图形,外部世界的开关等。
    异常丢失:
      异常不应该被忽略。但它可以轻易地忽略。在try中抛出的异常未被catch之前,在finally中再抛出异常则会覆盖前一个异常,造成前一个异常的丢失。 从finally中return也会造成异常丢失(在finally中使用return方法会silence所有抛出的exception)。

***异常限制
    在继承结构中,子类的构造函数必须包含父类构造函数的异常声明。派生类的构造器不能捕获基类构造器抛出的异常。
    子类覆盖的方法的异常声明必须是父类的异常声明的子集(或父类异常声明的派生类异常)。对象的可替换性得到了保证。

***构造器
    异常发生时,需要确保正确清理所有东西。但在构造器内部,可能会出现异常,而此时初始化动作尚未执行完毕,因此无法在构造器内部进行清理操作。
    清理的惯用方法是在创建需要清理的对象之后,立即进入一个try-finally块,即使构造器不会抛出异常,也应该使用。如:
     public class Cleanup {
public static void main(String[] args) {
try {
InputFile in = new InputFile("Cleanup.java");
try {
String s;
int i = 1;
while ((s = in.getLine()) != null )
; // Perform line-by-line processing here...
} catch (Exception e) {
System. out .println("Caught Exception in main");
e.printStackTrace(System. out );
} finally {
in.dispose();
}
} catch (Exception e) {
System. out .println("InputFile construction failed");
}
}
}


原文地址:https://www.cnblogs.com/myparamita/p/2203976.html