java编程思想的错误,读《java编程思想》12-通过异常处理错误

1、什么是异常

(1)异常情形(exception condition)是指阻止当前方法或作用域继续执行的问题。普通问题只是在当前环境中能够得到足够的信息,总能处理这个错误。而对于异常情形,就不能继续下去了。因为当前环境下无法获得必要的信息来解决问题,能做的是从当前环境中跳出,并且把问题提交给上一级环境。这就是抛出异常时发出的事情。

如:调用库存接口,返回报文中公共参数code为0是正常,1代表库存不足,这是业务问题,走补货流程(普通问题)。但如果什么都不返回,或者超时就是异常。

(2)发生异常时

a)将会使用new在堆上创建异常对象 (new)

b)当前执行路径被终止,并从当前环境中弹出对异常对象的引用。(throw)

c)由异常处理程序接管,他的任务是从错误状态中恢复,以使程序继续执行或者换一种方式运行。 (catch)

2、 java异常一览

4172022

c346599bbb247c297d3971ce6924fec2.png

4172022

(1)Throwable 是所有异常类的父类。

(2)Error是严重的错误,如:虚拟机错误(内存不足,方法调用出栈)和 链接错误(找不到类)。仅靠程序本身无法恢复和预防,java编译器不会检查他们(属于UncheckedException),程序中也不应该捕获他们(try catch),遇到此类错误,建议让程序停止。

(3)Exception表示程序可以处理的异常,可以捕获且可能恢复。遇到此类异常,应该尽量处理,而不应该随意终止异常。Exception 又分为运行时异常(Runtime Exception) 和 被检查异常(Checked Exception)

a)RuntimeException:java编译器不会检查它,又被称为 Unchecked Exception。如:数组下标越界、空指针异常等,如果出现RuntimeException,代表的是编程错误。

b)被检查异常:这类异常如果没有捕获(try catch)或者抛出(throw),编译器会报错。 这类异常一般是由外部引起,如:文件找不到,Sql错误等。

3、自定义异常

自定义异常可以继承Exception,作为Checked Exception,受到编译器检查。也可以继承RuntimeException,作为Unchecked Exception。不影响现有代码,运行时透明传递。但最上层一定要有异常处理程序统一处理。否则就是程序错误。

4、异常说明

异常说明属于方法声明的一部分,使用throws,标识所有可能会抛出的异常。

void f() throws Exception1, Exception2....

调用有异常说明的方法编译时会被编译器检查,必须捕获(try catch),无论实际抛出没有(throw)。

5、栈轨迹

在异常处理程序(catch)中,调用printStackTrace可以打出栈轨迹。

如:

java.lang.RuntimeException: custom

at chapter12.Test55.f1(Test55.java:9)

at chapter12.Test55.f2(Test55.java:13)

at chapter12.Test55.f3(Test55.java:17)

at chapter12.Test55.main(Test55.java:22)

第一行异常名称RuntimeException, 构造参数是custom

第二行开始是栈轨迹

4172022

7c101cda84805028d9fc883aaafc2e58.png

也可以通过getStackTrance获取栈轨迹数组,栈顶元素为最后一个方法的调用(异常抛出的位置),栈底元素为第一个方法的调用。

由此可以看出栈轨迹其实可以称为 ”调用方法“的栈轨迹。

6、异常链

捕获异常后,当前环境无法处理(恢复),需要再次抛出时,有三种情况:

(1)可以直接抛出已捕获的异常 ,栈轨迹不变。(相当于这里没有捕获)

(2)抛出e.fillTraceException或者一个新的异常(不带cause),栈轨迹被吞掉当前方法以下的调用信息。

如:f2中捕获并如此处理,则f3 和 main 会被吞掉。

(3)想要捕获异常后抛出另外一个异常,并且把原始异常的信息保存下来。这就是为异常链。

我们使用带Throwable类型cause(原因)构造参数抛出异常,这个原因将被当做原始异常。链接起来。

如:

按照方法调用的顺序入栈:main->f3->f2->f1

3339e2bfe19cec7ed48e2e1574df2611.png

4172022

输出为

chapter12.CustomException3: chapter12.CustomException2: chapter12.CustomException1: custom

at chapter12.Test55.f3(Test55.java:24)

at chapter12.Test55.main(Test55.java:30)

Caused by: chapter12.CustomException2: chapter12.CustomException1: custom

at chapter12.Test55.f2(Test55.java:16)

at chapter12.Test55.f3(Test55.java:22)

... 1 more

Caused by: chapter12.CustomException1: custom

at chapter12.Test55.f1(Test55.java:9)

at chapter12.Test55.f2(Test55.java:14)

... 2 more

可以看出

(1)异常链上所有异常按照抛出的顺序逆序显示(和栈轨迹相反),最后一个抛出的为主异常,其他为原因。

(2)冒号后面是前一个异常原因msg的拼接。(如此保证第一个可以看到所有原因的msg)

由此可以看出异常链,可以称为 ”抛出异常“的链路。

7、异常日志输出

(1)printStackTrace() 同时使用System.out输出时,输出顺序会混乱。

那是因为printStackTrace() 默认为printStackTrace(System.err)

因此可以使用printStackTrace(System.out),就可以和System.out顺序输出了。

(2)如果需要将异常信息变为字符串文本获取

StringWriter trace = new StringWriter();

e.printStackTrace(new PrintWriter(trace));

System.out.println(trace.toString());

8、finally

(1)在return前finally 一定会执行。

(2)在finally中return,会使异常丢失。

9、异常的限制

(1)在覆盖方法是,子类只能抛出基类异常说明里已有的异常,或者不抛出。

(2)子类构造器可以抛出任何异常,但是必须包含基类异常说明里已有的异常。

(3)不能基于异常重载方法。

(4)子类没有向上转型,调用方法时,可以不捕获和接口的异常,反之必须捕获。

10、异常匹配

抛出异常时,异常处理系统会按照代码的书写书序找到”最近“的处理程序进行处理,不会再继续查找。

因此同时有父子类型异常时,应该先”小“后”大“。

同理可以使用Exception 捕获所有异常,应该放到处理程序列表的末尾。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值