Java 常用类解析:java异常机制,异常栈,异常处理方式,异常链,异常丢失详解

网友投稿 288 2023-06-03


Java 常用类解析:java异常机制,异常栈,异常处理方式,异常链,异常丢失详解

1、java标准异常概述

Throwable表示任何可以作为异常被抛出的类,有两个子类Error和Exception。从这两个类的源代码中可以看出,这两个类并没有添加新的方法,Throwable提供了所以方法的实现。Error表示编译时和系统错误。Exception是可以被抛出的异常类。RuntimeException继承自Exception(如NullPointerException),表示运行时异常,JVM会自动抛出.

2、自定义异常类

自定义异常类方法: 通过继承Throwable或Exception。异常类的所有实现都是基类Throwable实现的,所以构造自定义异常类完全可以参考Exception和Error类。我们只要添加上自定义异常类的构造方法就可以了

package demo.others;

/**

* 自定义异常类方法

* 1、通过继承Throwable

* 2、通过继承Exception

*

* @author Touch

*/

public class MyExceptionDemo extends Exception {

private static final long serialVersionUID = 1L;

public MyExceptionDemo() {

super();

}

public MyExceptionDemo(String message) {

super(message);

}

public MyExceptionDemo(String message, Throwable cause) {

super(message, cause);

}

public MyExceptionDemo(Throwable cause) {

super(cause);

}

}

3、异常栈及异常处理方式

可以通过try、catch来捕获异常。捕获到的异常。下面的示例演示了几种常用异常处理方式

package demo.others;

import mine.util.exception.MyException;

public class ExceptionDemo1 {

public void f() throws MyException {

throw new MyException("自定义异常");

}

public void g() throws MyException {

f();

}

public void h() throws MyException {

try {

g();

} catch (MyException e) {

//1、通过获取栈轨迹中的元素数组来显示异常抛出的轨迹

for (StackTraceElement ste : e.getStackTrace())

System.out.println(ste.getMethodName());

//2、直接将异常栈信息输出至标准错误流或标准输出流

e.printStackTrace();//输出到标准错误流

e.printStackTrace(System.err);

e.printStackTrace(System.out);

//3、将异常信息输出到文件中

//e.printStackTrace(new PrintStream("file/exception.txt"));

//4、重新抛出异常,如果直接抛出那么栈路径是完整的,如果用fillInStackTrace()

//那么将会从这个方法(当前是h()方法)作为异常发生的原点。

//throw e;

throw (MyException)e.fillInStackTrace();

}

}

public static void main(String[] args) {

try {

new ExceptionDemo1().h();

} catch (MyException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

}

运行结果:

f

g

h

main

mine.util.exception.MyException: 自定义异常

at demo.others.ExceptionDemo1.f(ExceptionDemo1.Java:7)

at demo.others.ExceptionDemo1.g(ExceptionDemo1.Java:11)

at demo.others.ExceptionDemo1.h(ExceptionDemo1.java:16)

at demo.others.ExceptionDemo1.main(ExceptionDemo1.java:35)

mine.util.exception.MyException: 自定义异常

at demo.others.ExceptionDemo1.f(ExceptionDemo1.java:7)

at demo.others.ExceptionDemo1.g(ExceptionDemo1.java:11)

at demo.others.ExceptionDemo1.h(ExceptionDemo1.java:16)

at demo.others.ExceptionDemo1.main(ExceptionDemo1.java:35)

mine.util.exception.MyException: 自定义异常

at demo.others.ExceptionDemo1.f(ExceptionDemo1.java:7)

at demo.others.ExceptionDemo1.g(ExceptionDemo1.java:11)

at demo.others.ExceptionDemo1.h(ExceptionDemo1.java:16)

at demo.others.ExceptionDemo1.main(ExceptionDemo1.java:35)

mine.util.exception.MyException: 自定义异常

at demo.others.ExceptionDemo1.h(ExceptionDemo1.java:30)

at demo.others.ExceptionDemo1.main(ExceptionDemo1.java:35)

分析上面的程序,首先main函数被调用,然后是调用h函数,再g函数、f函数,f函数抛出异常,并在h函数捕获,这时将依次从栈顶到栈底输出异常栈路径。

4、异常链

有时候我们会捕获一个异常后在抛出另一个异常,如下代码所示:

package demo.others;

import java.io.IOException;

import mine.util.exception.MyException;

public class ExceptionDemo2 {

public void f() throws MyException {

throw new MyException("自定义异常");

}

public void g() throws Exception {

try {

f();

} catch (MyException e) {

e.printStackTrace();

throw new Exception("重新抛出的异常1");

}

}

public void h() throws IOEhttp://xception {

try {

g();

} catch (Exception e) {

// TODO Auto-generated catch block

e.printStackTrace();

throw new IOException("重新抛出异常2");

}

}

public static void main(String[] args) {

try {

new ExceptionDemo2().h();

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

}

运行结果:

mine.util.exception.MyException: 自定义异常

at demo.others.ExceptionDemo2.f(ExceptionDemo2.java:9)

at demo.others.ExceptionDemo2.g(ExceptionDemo2.java:14)

at demo.others.ExceptionDemo2.h(ExceptionDemo2.java:23)

at demo.others.ExceptionDemo2.main(ExceptionDemo2.java:32)

java.lang.Exception: 重新抛出的异常1

at demo.others.ExceptionDemo2.g(ExceptionDemo2.java:17)

at demo.others.ExceptionDemo2.h(ExceptionDemo2.java:23)

at demo.others.ExceptionDemo2.main(ExceptionDemo2.java:32)

java.io.IOException: 重新抛出异常2

at demo.others.ExceptionDemo2.h(ExceptionDemo2.java:27)

at demo.others.ExceptionDemo2.main(ExceptionDemo2.java:32)

从结果中我们可以看出,异常栈变小了。也就是说丢失了最原始的异常信息。怎样保存最原始的异常信息呢?Throwable类中有个Throwable  cause属性,表示原始异常。通过接收cause参数的构造器可以把原始异常传递给新异常,或者通过initCause()方法。如下示例:

package demo.others;

import java.io.IOException;

import mine.util.exception.MyException;

public class ExceptionDemo2 {

public void f() throws MyException {

throw new MyException("自定义异常");

}

public void g() throws Exception {

try {

f();

} catch (MyException e) {

e.printStackTrace();

throw new Exception("重新抛出的异常1",e);

}

}

public void h() throws IOException {

try {

g();

} catch (Exception e) {

// TODO Auto-generated catch block

e.printStackTrace();

IOException io=new IOException("重新抛出异常2");

io.initCause(e);

throw io;

}

}

public static void main(String[] args) {

try {

new ExceptionDemo2().h();

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

}

结果:

mine.util.exception.MyException: 自定义异常

at demo.others.ExceptionDemo2.f(ExceptionDemo2.java:9)

at demo.others.ExceptionDemo2.g(ExceptionDemo2.java:14)

at demo.others.ExceptionDemo2.h(ExceptionDemo2.java:23)

at demo.others.ExceptionDemo2.main(ExceptionDemo2.java:34)

java.lang.Exception: 重新抛出的异常1

at demo.others.ExceptionDemo2.g(ExceptionDemo2.java:17)

at demo.others.ExceptionDemo2.h(ExceptionDemo2.java:23)

at demo.others.ExceptionDemo2.main(ExceptionDemo2.java:34)

Caused by: mine.util.exception.MyException: 自定义异常

at demo.others.ExceptionDemo2.f(ExceptionDemo2.java:9)

at demo.others.ExceptionDemo2.g(ExceptionDemo2.java:14)

... 2 more

java.io.IOException: 重新抛出异常2

at demo.others.ExceptionDemo2.h(ExceptionDemo2.java:27)

at demo.others.ExceptionDemo2.main(ExceptionDemo2.java:34)

Caused by: java.lang.Exception: 重新抛出的异常1

at demo.others.ExceptionDemo2.g(ExceptionDemo2.java:17)

at demo.others.ExceptionDemo2.h(ExceptionDemo2.java:23)

... 1 more

Caused by: mine.util.exception.MyException: 自定义异常

at demo.others.ExceptionDemo2.f(ExceptionDemo2.java:9)

at demo.others.ExceptionDemo2.g(ExceptionDemo2.java:14)

... 2 more

从结果中看出当获取到“重新抛出异常2的时候,同时可以输出原始异常“重新抛出的异常1“和原始异常”自定义异常,这就是异常链。

5、finally的使用

finally子句总是执行的,通常用来做一些清理工作,如关闭文件,关闭连接等

下面举几个finally的例子:

// 读取指定路径文本文件

public static String read(String filePath) {

StringBuilder str = new StringBuilder();

BufferedReader in = null;

try {

in = new BufferedReader(new FileReader(filePath));

String s;

try {

while ((s = in.readLine()) != null)

str.append(s + '\n');

} finally {

in.close();

}

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

return str.toString();

}

分析:如果调用in = new BufferedReader(new FileReader(filePath));时发生异常,这时是一个文件路径不存在的异常,也就是说并没有打开文件,这时将会直接跳到catch块,而不会执行try...finally块(并不是finally子句)里面的语句in.close();此时不需要关闭文件。

再看一个例子,会导致异常的丢失

package demo.others;

import mine.util.exception.MyException;

public class ExceptionDemo3 {

public void f() throws MyException {

throw new MyException("异常1");

}

public void g() throws MyException {

throw new MyException("异常2");

}

public static void main(String[] args) {

try {

ExceptionDemo3 ex = new ExceptionDemo3();

try {

ex.f();

} finally {

ex.g();//此时捕获g方法抛出的异常,f方法抛出的异常丢失了

}

} catch (MyException e) {

System.out.println(e);

}

}

}

结果:mine.util.exception.MyException: 异常2

此时异常1就丢失了

或者这样写:

package demo.others;

import mine.util.exception.MyException;

public class ExceptionDemo3 {

public void g() throws MyException {

throw new MyException("异常2");

}

public static void main(String[] args) {

ExceptionDemo3 ex = new ExceptionDemo3();

try {

ex.g();

} finally {

//直接return会丢失所以抛出的异常

return;

}

}

}

6、异常的限制

(1)当覆盖方法时,只能抛出在基类方法的异常说明里列出的那些异常,有些基类的方法声明抛出异常其实并没有抛出异常,这是因为可能在其子类的覆盖方法中会抛出异常

(2)构造器可以抛出任何异常而不必理会基类构造器所抛出的异常,派生类构造器异常说明必须包含基类构造器异常说明,因为构造派生类对象时会调用基类构造器。此外,派生类构造器不能捕获基类构造器抛出的异常。

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Vue + Webpack + Vue
下一篇:微信小程序 仿猫眼实现实例代码
相关文章

 发表评论

暂时没有评论,来抢沙发吧~