java异常
一、简介
Java异常是Java提供的一种识别及响应错误的一致性机制。
Java异常机制可以使程序中异常处理代码和正常业务代码分离,保证程序代码更加优雅,并提高程序健壮性。在有效使用异常的情况下,异常能清晰的回答what, where, why这3个问题:异常类型回答了“什么”被抛出,异常堆栈跟踪回答了“在哪“抛出,异常信息回答了“为什么“会抛出。
(一)关键字
关键字 | 作用 | 备注 |
---|---|---|
try | 用于监听。将要被监听的代码(可能抛出异常的代码)放在try语句块之内,当try语句块内发生异常时,异常就被抛出。 | |
catch | 用于捕获异常。catch用来捕获try语句块中发生的异常。 | |
finally | finally语句块总是会被执行。它主要用于回收在try块里打开的物力资源(如数据库连接、网络连接和磁盘文件)。只有finally块,执行完成之后,才会回来执行try或者catch块中的return或者throw语句,如果finally中使用了return或者throw等终止方法的语句,则就不会跳回执行,直接停止。 | |
throw | 用于抛出异常。 | |
throws | 用在方法签名中,用于声明该方法可能抛出的异常。 |
(二)java基础异常分类
说明:
在Java中,所有异常类的父类是Throwable类,Error类是error类型异常的父类,Exception类是exception类型异常的父类,RuntimeException类是所有运行时异常的父类,RuntimeException以外的并且继承Exception的类是非运行时异常。
典型的RuntimeException包括NullPointerException、IndexOutOfBoundsException、IllegalArgumentException等。
典型的非RuntimeException包括IOException、SQLException等。
(三)如何进行异常处理
基本代码块:
try {
File file = new File("d:/c.txt");
if (!file.exists()) {
file.createNewFile();
}
} catch (IOException e) {
System.out.println("如果发现异常我们该怎么办的操作");
} finally {
System.out.println("无论如何都要执行的代码块");
}
二、继承时异常关系
下面是三点原则:
1)父类的方法没有声明异常,子类在重写该方法的时候不能声明异常;
2)如果父类的方法声明一个异常exception1,则子类在重写该方法的时候声明的异常不能是exception1的父类;
3)如果父类的方法声明的异常类型只有非运行时异常(运行时异常),则子类在重写该方法的时候声明的异常也只能有非运行时异常(运行时异常),不能含有运行时异常(非运行时异常)
三、异常处理和设计的几个注意
建议 | 说明 |
---|---|
只在必要使用异常的地方才使用异常,不要用异常去控制程序的流程 | |
切忌使用空catch块 | 在捕获了异常之后什么都不做,相当于忽略了这个异常。千万不要使用空的catch块,空的catch块意味着你在程序中隐藏了错误和异常,并且很可能导致程序出现不可控的执行结果。如果你非常肯定捕获到的异常不会以任何方式对程序造成影响,最好用Log日志将该异常进行记录,以便日后方便更新和维护。 |
检查异常和非检查异常的选择 | 一旦你决定抛出异常,你就要决定抛出什么异常。这里面的主要问题就是抛出检查异常还是非检查异常。 检查异常导致了太多的try…catch代码,可能有很多检查异常对开发人员来说是无法合理地进行处理的,比如SQLException,而开发人员却不得不去进行try…catch,这样就会导致经常出现这样一种情况:逻辑代码只有很少的几行,而进行异常捕获和处理的代码却有很多行。这样不仅导致逻辑代码阅读起来晦涩难懂,而且降低了程序的性能。我个人建议尽量避免检查异常的使用,如果确实该异常情况的出现很普遍,需要提醒调用者注意处理的话,就使用检查异常;否则使用非检查异常。 因此,在一般情况下,我觉得尽量将检查异常转变为非检查异常交给上层处理。 |
注意catch块的顺序 | 被破获的异常也有大小,先捕获大的异常小的就捕获不了了。 |
不要将提供给用户看的信息放在异常信息里 | 尽量,有的公司框架还是直接弹出异常给用户,他们也能接受 |
避免多次在日志信息中记录同一个异常 | 只在异常最开始发生的地方进行日志信息记录。很多情况下异常都是层层向上跑出的,如果在每次向上抛出的时候,都Log到日志系统中,则会导致无从查找异常发生的根源 |
异常处理尽量放在高层进行 | 尽量将异常统一抛给上层调用者,由上层调用者统一之时如何进行处理。如果在每个出现异常的地方都直接进行处理,会导致程序异常处理流程混乱,不利于后期维护和异常错误排查。由上层统一进行处理会使得整个程序的流程清晰易懂。 |
在finally中释放资源 | 如果有使用文件读取、网络操作以及数据库操作等,记得在finally中释放资源。这样不仅会使得程序占用更少的资源,也会避免不必要的由于资源未释放而发生的异常情况。 |
四、自定义异常
继承对应的父类就可以实现自定义异常,然后根据需求重新构造方法等属性。
1.所有异常都必须是Throwable的子类。
2.如果希望写一个检查异常类,则需要继承Exception类。
3.如果希望写一个运行时异常类,则需要继承RuntimeException类。
public class CommonException extends RuntimeException {
public CommonException(String msg) {
super(msg);
}
}
public void testCommonException() {
throw new CommonException("错误");
}