Thinking in Java 整理笔记:通过异常处理错误
Posted Chouney
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Thinking in Java 整理笔记:通过异常处理错误相关的知识,希望对你有一定的参考价值。
1.异常情形:是指阻止当前方法或作用域继续执行的问题。2.抛出异常后的流程: a.同Java中其他对象的创建一样,将使用new在堆上创建异常对象 。 b.当前的执行路径(不能继续下去了)被终止,并且从当前环境中弹出对异常对象的引用。 c.异常处理机制接管程序,并开始寻找一个恰当的地方来继续执行程序。这个恰当的地方就是 异常处理程序。
3.异常最重要的方面之一就是如果发生问题,他们将不允许程序沿着其正常的路径继续走下去。
4.创建异常对象也伴随着存储空间的分配和构造器的调用。所有标准异常类都有两个构造器:一个是默认构造器;另一个是接受字符串的参数 如: throw new NullPointerException("t = null")
5.能够跑出任意类型的Throwable对象,它是异常类型的根类(Exception即从此类继承)
6.异常处理理论上有两种基本: a. Java支持终止模型(它是Java和C++所支持的模型 ):将假设错误非常关键,以至于程序无法返回到异常发生的地方继续执行; b.另一种成为恢复模型:异常处理程序的工作是修正错误,然后重新尝试调用出问题的方法,并认为第二次能成功。对于恢复模型,通常希望异常被处理之后能继续执行程序 若想要用java实现类似恢复的行为,那么在遇见错误时就不能抛出异常,而是调用方法来修正该错误。
7.创建自定义的异常类,必须从已有的异常类继承。 例如:class SimpleException extends Exception ... public void f() throws SimpleException ps:对于异常来说最重要的部分就是类名。
8.System.err将错误发送给标准错误流; .printStackTrace()默认输出到标准错误流;.printStackTrace(System.out)输出到控制台
9.可以使用java.util.logging工具将输出记录到日志中
10.Throwable的getMessage()方法可以产生更详细的信息,对于异常类来说getMessage()方法有点类似于toString()方法
11.异常说明,使用了附加的关键字trhrows,后面借一个所有潜在异常类型的列表。 PS:可以声明方法将抛出异常,实际上却不抛出。编译器相信了这个声明,并强制此方法的用户像真的抛出异常那样使用这个方法。(为异常先占个位子,以后就可以抛出这种异常而不用修改已有的代码。在定义抽象基类和接口时这种能力很重要)
12.Exception是与编程有关的所有异常类的基类,所以它不会含有大多的具体信息,不过可以调用它从其基类Throwable继承的方法: String getMessage()// String getLocalizedMessage() 用来获取详细信息,或用本地语言表示的详细信息 String toString() 返回对Throwable的简单描述,以及其他详细信息 printStackTrace() printStackTrace(PrintStream)
printStackTrace(java.io.PrintWriter)
输出调用栈轨迹,显示了异常的方法调用序列。输出到不同的流中 Throwable FillInStackTrace() 用于在Throwable对象的内部记录栈帧的当前状态。这在程序重新抛出错误或异常时很有用
13.栈轨迹:printStackTrace()所提供的信息可以通过getStackTrace()方法来直接访问,这个方法将返回一个由栈轨迹中的元素所构成的数组,其中每一个元素都表示栈中的一帧(如元素0是栈顶元素,并且是调用序列中的最后一个方法调用)
14.重新抛出异常,如: catch (Exception e) throw e; 重抛异常会把异常抛给上一级环境中的异常处理程序,同一个try块的后续catch字句将被忽略 PS: 如果只是把当前异常对象重新抛出,那么printStackTrace()方法显示的将是原来异常抛出点的调用栈信息。 要想更新这个信息,则可以调用上述12的fillInStackTrace()方法,返回一个Throwable对象。 PS2:在捕获异常之后抛出另一种异常,得到的效果类似于使用FillInStackTrace() PS3:永远不必为清理前一个异常对象而担心,他们都是用new在堆上创建的对象,所以垃圾回收器会自动把它们清理掉
15.若要在捕获一个异常后抛出另一个异常并且希望把原始异常信息保存下来,这被称为 异常链。方法: 现在所有Throwable的子类在构造器中都可以接受一个cause对象作为参数。用来表示原是一场,这样可以通过把原始异常传递给新的异常。 但是,在Throwable的子类,只有三种基本的异常类提供了带cause参数的构造器。(Error(用于Java虚拟机报告系统错误)、Exception以及RuntimeException) 若是其他类型的异常连接起来,应该使用initCause()方法而不是构造器 例如: catch (Exception e) Outter o = new Outter(); o.initCause(e); throw o;
16.Java标准异常:Throwable对象可分为两种类型:Error用来表示编译时和系统错误(一般不用关心);Exception是可以被抛出的基本类型,在Java类库、用户方法以及运行时故障中都可能抛出Exception型异常,这个需要关注。
17.RuntimeException 不受检查异常 特例 : 属于运行时异常的类型有很多,它们会自动被Java虚拟机抛出,所以不必在异常说明中把它们列出来。这些异常都是从RuntimeException类继承而来。他们也被称为(不受检查异常),这种异常属于错误,将被自动捕获,不用亲自动手。 原因:RuntimeException代表的是编程错误(空指针,边界错误等)
18.finally用来做什么: 特性:无论try块中的异常是否抛出,它们都能得到执行。 finally经常用来把除内存之外的资源恢复到初始状态,如文件,连接,图形。 PS:return 返回作用域的上一级:如: try f(); return ; catch (Exception e) e.printStackTrace();
19.Java异常丢失:Java异常实现也有瑕疵:前一个异常还没处理就抛出下一个异常(即finally语句中可能会有异常出现而导致前一个异常丢失)
20 .异常的限制 : a .当覆盖方法的时候,只能抛出在基类方法的异常说明里列出的那些异常: 如: 父类: public void event() throws AException throw new AException(); 子类: public void event() throws AException 或者 public void event()
这样保证调用派生类对象若有异常时,基类一定存在该异常。(核心思想:一个出现在基类方法的异常说明中的异常,不一定会出现在派生类方法的异常说明里,即在继承和覆盖的过程中,异常说明的接口不是变大而是变小了) b.虽然异常限制对构造器不起作用,但是因为基类构造器必须以这样或那样的方式被调用,所以派生类构造器必须包含基类构造器的异常说明。 如: 父类: public Outter() throws AException 子类: public test() throws DbException,AException c.派生类构造器不能捕获基类构造器抛出的异常 d.道理如a,基类方法若没有异常说明,派生类覆盖方法也不能有异常说明: 如: 父类: public void event() 子类: //!public void event() throws AException //! 报错。
21.在构造阶段(如文件,连接等)可能会抛出异常,其清理基本规则是在创建需要清理的对象之后,立即进入一个try-finally语句块
22.”强静态类型语言(也就是编译时就做类型检查的语言)
23.异常处理程序可能因为面对大程序而变得无法管理(因为面对”被检查的异常“有时不知道采取什么措施提供处理程序),特别是”被检查的异常“所造成的问题。
24.main()作为一个方法也可以由异常说明,通过把它传递到控制台,就不用在main()中写try-catch语句了
25.在面对”被检查的异常“时不知道如何采取措施提供处理程序时可以直接把其包装进RuntimeException里面
26.异常使用指南: 应该在下列情况下使用异常: 1)在恰当的级别处理问题 2)解决问题并且重新调用产生异常的方法 3)进行少许修补,然后绕过异常发生的地方继续执行 4)用别的数据进行计算,以代替方法预计会返回的值 5)把当前运行环境下能做的事情尽量做完,然后把相同的异常 重新抛到更高层 6) 把当前运行环境下能做的事情尽量做完,然后把不同的异常抛到更高层 7)终止程序 8)进行简化 9)让类库和程序更安全
以上是关于Thinking in Java 整理笔记:通过异常处理错误的主要内容,如果未能解决你的问题,请参考以下文章