目录
一、什么是异常?
异常指的是程序运行过程中,发生的不正常的情况,如果程序发生异常后未处理,那么JVM会终止。
二、Java异常体系
Throwable是所有Java程序中错误和异常的超类
-
Error错误:指严重的问题,无法处理,一旦发生,jvm只能终止。
-
Exception异常:一般性问题,发生后可以通过异常处理,保证JVM继续运行。
-
受检异常-编译期异常:必须处理才能运行程序
-
非受检异常-运行时异常:可以选择处理或不处理
RuntimeException类及其子类表示的异常。
-
三、异常的抛出机制
当异常发生时,JVM会在异常的发生处,自动创建对应的异常类对象并抛出,向方法的调用处逐层抛出,最终抛给JVM,JVM会打印输出异常的堆栈追踪信息及异常对象中的信息到控制台,并终止JVM。
异常的抛出方式:
-
JVM自动创建异常对象并抛出
-
使用关键字throw手动抛出异常对象
throw new Exception("异常发生了");
四、异常的处理机制
针对运行时异常,要尽量通过修正提高代码的严谨度,避免运行时异常的发生。针对编译期异常,必须处理才能运行程序。处理方式有2种:
-
try...catch捕获异常 当异常对象被抛出后,在抛给JVM之前将其捕获,就可以保证JVM继续运行。 try{ //可能发生异常的代码 }catch(要捕获的异常类型1|异常类型2 变量){ //异常捕获后的处理逻辑 }catch(要捕获的异常类型 变量){ //异常捕获后的处理逻辑 }finally{ //最终会执行的代码:通常用于释放资源。 }
-
使用throws关键字声明异常,由方法的调用者处理。
public void readFile() throws FileNotFoundExcetion{//表示此方法可能发生FileNotFoundExcetion异常。 }
五、自定义异常
-
为什么需要自定义异常类:
异常表示程序运行中出现的不正常的情况,我们说了Java中不同的异常类,分别表示着某一种具体的异常情况,我们在使用也是尽量使用Java这些异常类型。但在大型系统的开发中总是有些不正常的情况是Java没有定义好的类不好表示的,此时我们可以根据自己业务的异常情况来自定义异常类。例如年龄负数问题,考试成绩负数问题等等,我们都可以通过自定义异常类来表示。
-
异常类如何定义:
保持一个合理的异常体系是很重要的,一般自定义一个异常比如UserException作为“根异常”,然后在此基础上再派生出不同的异常类型,自定义的“根异常”需要从一个合适的现有异常中派生出来,通常建议派生自
java.lang.RuntimeException
。"根异常":
public class UserException extends RuntimeException { }
其他异常从”根异常“派生出来:
public class UserExistedException extends UserException { } public class UserNotFoundException extends UserException { } ...
自定义的“根异常”通常提供多个构造方法,直接调用父类的即可:
//用户异常类 public class UserException extends RuntimeException { public UserException() { } public UserException(String message) { super(message); } public UserException(String message, Throwable cause) { super(message, cause); } public UserException(Throwable cause) { super(cause); } }
派生出的异常,提供简单两个构造方法,够用即可:
//用户已经存在异常类 public class UserExistedException extends UserException { public UserExistedException() { } public UserExistedException(String message) { super(message); } }
六、异常关键字和注意事项总结
-
异常处理中的5个关键字
-
异常处理注意事项
-
编译期异常必须处理,要么捕获处理,要么声明在方法上,让调用者处理。
-
运行时异常被抛出可以不处理。即不捕获也不声明抛出。
-
try语句范围要尽量小的包围在可能出现异常的一行或几行代码上,不要把大量无异常的代码一起包起来,虽然这样很省事。
-
catch语句捕获的异常类型要尽量小,尽量精准,好针对性的做处理。
-
如果finally有return语句,永远返回finally中的结果,但要避免该情况.
-
如果父类方法抛出了多个异常,子类重写父类方法时不能抛出更大异常,可以抛出和父类相同的异常或者是父类异常的子类或者不抛出异常。
-
父类方法没有抛出异常,子类重写父类该方法时也不可抛出异常。
-