人生这趟旅程,总有人上车,也有人下车。
今文章会说一说 Java 异常分类,以及 Java 异常捕获处理一些方式,不足之处请多包含。
作为初学者,在编程 Java 时应该也遇到过一些异常,有的在未启动程序就已经出现红色波浪线进行了错误提示,有的又会在启动时就报错,有的错误包含 Exception 字段,有的包含 Error字段。首先,先介绍一些异常的分类,让大脑中有一些基本了解。
1.异常分类
所有异常有一个父类-----Throwable类,该类下分为 Error 和 Exception两个大类,再就是两个大类下的一些分类,重点了解Exception 类下有一个分类为 RuntimeException 类。
1.1 检查型异常(Checked Exception)
简单地说就是,在编译代码时编译器检查出的异常。该类异常必须被处理才能正确编译和启动服务程序。
该类异常为 Exception类下除了 RuntimeException类以外的其他异常类,常见的检查型异常有 FileNotFoundException(未发现文件异常),IOException(IO流异常),ClassNotFoundException(未发现类异常)。
1.2 非检查型异常(Unchecked Exception)
该类型异常,一般可以通过编译,但是在程序处理过程中出现,一般属于代码逻辑和处理中的错误。当然,Error 异常类也属于非检查异常,该类异常属于系统内部错误,一般在程序中较少出现。
此类型常见异常为:NullException(空指针异常),IndexOutOfBoundsException(索引越界异常),ClassCastException(类强转异常),ArithmeticException(异常的运算条件)。
异常分类简易树形图:
2.处理错误
对于 Java 后端工作者来说,编程常分为①Controller层(或Manage层),②Service 层,③Dao层。对③来说,一般用于数据库数据传输处理层。对②来说,一般用于程序设计编程细节处理。对①来说,一般用于控制某个功能接口的流程控制。反过来说,①控制流程,②控制实现细节,③负责数据处理。
在代码中出现检查型异常时,最常用的处理:方法一,在方法首部声明异常;方法二,try捕获异常并处理。
2.1 声明异常
在②实现细节过程中,是异常出现高发区,在该区域对异常声明处理是重点。声明如下,通过 throws将异常声明在方法首部:
2.1.1 声明单个检查型异常
private static void doHanle() throws FileNotFoundException {//在方法首部单个声明
FileOutputStream fileOutputStream = new FileOutputStream("文件路径");
}
2.1.2 声明多个检查型异常
private static void doHanle() throws FileNotFoundException,EOFException {//在方法首部多个声明格式
FileOutputStream fileOutputStream = new FileOutputStream("文件路径");
......
}
观察上面标题会发现,都是声明检查型异常,在声明异常时需要注意,非检查型异常无需使用异常声明方式,即Error 和 RuntimeException无需声明。因为检查型异常在编译阶段必须处理,而非检查型,对其无法直接控制。
2.2 捕获异常
2.2.1 抛异常
在某些时候,需要主动抛出一些自定义异常信息,需要使用什么方式呢?如下,使用 throw 抛出某异常对象。
public class ExceptionHandleDemo {
public static void main(String[] args) {
try {
doHanle();
} catch (EOFException e) {
e.printStackTrace();
}
}
private static void doHanle() throws EOFException {
throw new EOFException("主动抛出异常");
// java.io.EOFException: 主动抛出异常
// at study.ExceptionHandleDemo.doHanle(ExceptionHandleDemo.java:18)
// at study.ExceptionHandleDemo.main(ExceptionHandleDemo.java:11)
}
}
2.2.2 try…catch
如上,当抛出某异常时,常用 try…catch 方法捕获并处理,分解开即为,①try{代码} ②catch(异常对象){异常处理}。①部分捕获,②部分处理。
只有当 try 捕获到异常,才会进入 catch 处理。如果不使用 try…catch进行处理,还可以继续通过 throws 往上抛出异常,使用 throws 方式抛异常,意味着该异常必须在某个环节被处理才能继续传递。
当捕获多个异常时会出现:
try {
doHanle();
} catch (EOFException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
这种情况可进行合并:
try {
doHanle();
} catch (Exception e) {
e.printStackTrace();
}
2.2.3 try…catch…finally
除了try…catch异常捕获处理结构还有一种 try…catch…finally结构,此处 finally 代表着总会执行的处理,不论 try 部分有没有捕获异常,finally 部分都会执行。
try {
doHanle();
} catch (Exception e) {
e.printStackTrace();
}finally {
System.out.println("最终且一定被执行处理部分");
}
为什么会需要有 finally 部分呢?因为当 try 包含的部分捕获到异常,那么异常之后的代码将不会再被执行,但是某些使用场景又有必须最后处理的事项,那么 finally 的存在就显得有了意义。
此处有一个例子,关于try…catch…finally结构中有 return 情况下,输出结果是什么?
//场景:当 fianlly 有 return 时候,最终输出的都是 fianlly 的 return 值。
public static void main(String[] args) {
int num = doVoid();
System.out.println("输出结果为:"+num);// 输出结果为:3
}
private static int doVoid() {
try {
//省略代码....
return 1;
} catch (Exception e) {
e.printStackTrace();
return 2;
} finally {
return 3;
}
}