前言
本文参考:
- 黑马程序员
- BiliBili遇见狂神说:https://space.bilibili.com/95256449/channel/index
异常
概念
异常,顾名思义,出毛病了,在Java代码中也代表着这段代码出毛病了
异常其实并没有什么可怕的,放轻松,按照对应的情况进行处理即可
分类
简而言之就是这样的一张图 Throwable是顶头Boss,然后分为了异常
Exception
和错误Error
其中异常我还列举了一些非常常见的异常。 我们一般称呼异常,一般说的都是Exception
Error
Error是不能处理的,好比人的绝症,一旦得上就要等死。
Exception
Exception是可以处理的,我们通常说的异常就是这个,可以处理的异常。
Exception分类中有两种比较重要的子类:
- RuntimeException:一般由于程序员的代码逻辑错误出现的异常,是运行时异常,平时处理的最多的错误。
- IOException:只要发生IO操作就会出现IO异常,非常正常。
受检查异常和不受检查异常
- 受检查异常:编译器能够检查出来,要求必须处理
- 不受检查异常:编译器一般检查不出来,不要求处理
不受检查异常包括
Error
和RuntimeException
,前者编译器处理不了,后者是程序员该管的事 不受检查异常不是说不应该处理,而是不应该编译器处理受检查异常一般在写代码的时候,编译器就给检测出来了,比如IO异常,不处理编译不通过
异常处理机制
异常处理就两个词:抛出,捕获
抛出
简而言之就是甩锅,把异常甩给上一级,让上一级去处理,自己不去管了。
捕获
简而言之就是处理,这个叫真正的处理,不甩锅了。
抛出和捕获的五个关键字
Java中处理异常全靠这五个关键字:
try
catch
finally
throw
throws
五个关键字分为两组:
try - catch - finally
throw - throws
throw 和 throws
thorw用在方法里,作用是抛出一个异常对象,这个异常对象要么捕获要么标识,必须去处理。 throws用在类上,作用是标识异常,提醒调用者去处理异常
try 和 catch 和 finally
try-catch-finally是一套组合拳 try用于发现可能出现的异常, catch提出对应的异常出现的策略 finally是最后的收尾,不管程序如何,最后一定会执行finally代码块,我们常常用于关闭资源,比如IO 注意了,就算是try或者catch代码块中有return,也得先把数据存下,然后等finally执行完之后再返回
package com.howling;
public class Throw {
public static void main(String[] args) {
try {
exception();
} catch (Exception e) {
System.out.println("异常处理策略");//异常处理策略
} finally {
System.out.println("程序一定会执行");//一定会执行
}
}
public static void exception() throws RuntimeException,Exception{
throwException();
}
public static void throwException(){
throw new RuntimeException();
}
}
catch的注意事项:如果有多个异常:
- 可以分别进行处理:分别处理
- 一次捕获,一次处理:处理这些异常的父类
final finally finalize三者的区别
答案是没什么关联。前两者应该没有什么问题,但是finalize说一下:
finalize()是在java.lang.Object里定义的,也就是说每一个对象都有这么个方法。
这个方法在gc启动,该对象被回收的时候被调用。
finally必须要执行
假如finally也有返回结果
public static int test() {
try {
int i = 1/0;
return 1;
} catch (Exception e) {
e.printStackTrace();
} finally {
return 2; //返回2
}
}
一些常用的方法
Throwable中定义了比较有用的方法
getMessage()
:获取异常的描述信息printStackTrace()
:打印异常,利于追踪
package com.howling;
public class Throw {
public static void main(String[] args) {
try {
exception();
} catch (Exception e) {
System.out.println(e.getMessage());//null
e.printStackTrace();//java.lang.RuntimeException
}
}
public static void exception() throws RuntimeException,Exception{
throwException();
}
public static void throwException(){
throw new RuntimeException();
}
}
自定义异常
只需两步:
- 新建类
- 继承异常
package com.howling;
public class CustomizeException extends Exception{
public CustomizeException() {
}
public CustomizeException(String message) {
super(message);
}
public CustomizeException(String message, Throwable cause) {
super(message, cause);
}
public CustomizeException(Throwable cause) {
super(cause);
}
public CustomizeException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}
可以看到有很多构造器的重载,但是一般来说前两个就够用了
package com.howling;
public class Throw {
public static void main(String[] args) {
try {
throwException();
} catch (CustomizeException e) {
e.printStackTrace();//com.howling.CustomizeException: 自定义异常
}
}
public static void exception() throws RuntimeException,Exception{
throwException();
}
public static void throwException() throws CustomizeException {
throw new CustomizeException("自定义异常");
}
}