回忆之前我们对异常的使用,我们用异常改变了方法执行流程
public class TestTry {
public static void main(String[] args) {
System.out.println(1);
test(0.0);
System.out.println(3);
}
public static void test(double p) {
if(p <= 0.0) {
// 异常也是一个对象, 包含的是错误描述
throw new IllegalArgumentException("本金必须大于 0"); // 1 处
}
System.out.println(2);
}
}
输出
1
Exception in thread "main" java.lang.IllegalArgumentException: 本金必须大于 0
at com.itheima.module3.TestTry.test(TestTry.java:13)
at com.itheima.module3.TestTry.main(TestTry.java:7)
这个例子中,执行到 1 处出现了异常,后续的输出 2、3 的代码都不会执行了
但如果希望,一个方法出现异常后,不要影响其它方法继续运行,可以用下面的语法来处理
public class TestTry {
public static void main(String[] args) {
System.out.println(1);
try {
test(0.0);
} catch (IllegalArgumentException e) {
System.out.println(e);
}
System.out.println(3);
}
public static void test(double p) {
if (p <= 0.0) {
throw new IllegalArgumentException("本金必须大于 0");
}
System.out.println(2);
}
}
输出
1
java.lang.IllegalArgumentException: 本金必须大于 0
3
执行流程为
如果把 catch 的异常类型改为 NullPointerException
如果不加 try - catch 块,异常对象也会继续从 main 方法抛给 jvm,jvm 收到异常终止程序执行
如果把 catch 的异常类型改为 Exception
问题:为何之前我们控制器中出现的异常不用 try - catch 处理?
我们当然也能自己 catch 异常,但可悲的是,你就算 catch 住异常又能干什么呢?还得考虑自己如何把异常信息转换为响应,还不如不 catch,交给 Spring 去处理
异常按语法可以分成两类
分别举一个例子:throw 一个运行时异常,没有额外语法,此异常抛给上一层方法来处理
public static void test(double p) {
if (p <= 0.0) {
throw new IllegalArgumentException("本金必须大于 0");
}
System.out.println(2);
}
如果 throw 一个编译异常
public static void test(double p) {
if (p <= 0.0) {
throw new Exception("本金必须大于 0"); // 语法报错了!
}
System.out.println(2);
}
public static void test(double p) throws Exception {
if (p <= 0.0) {
throw new Exception("本金必须大于 0");
}
System.out.println(2);
}
但编译时异常的烦人之处在于,当编译时异常抛给上一层方法后,上一层方法也被迫做出类似的选择
如果无论是否出现异常,都一定要执行的代码,可以用 finally 语法
try {
} catch (Exception e) {
} finally {
}
其中 catch 不是必须的,可以 try 与 finally 一起用
那这个 finally 的使用场景是什么呢?
以后我们的代码常常需要与一些外部资源打交道,外部资源有文件、数据库等等。这些外部资源使用时都有个注意事项,就是用完后得把资源及时释放关闭,资源都是有限的,如果用完不关,最终会导致资源耗尽,程序也无法继续运行了。将来这边代表资源的对象一般都会提供一个名为 close 的方法,用来释放资源。显然在 finally 中调用资源的 close 方法最为科学
public class TestFinally {
public static void main(String[] args) {
Resource r = new Resource();
try {
System.out.println("使用资源");
int i = 1 / 0;
} catch (Exception e) {
System.out.println(e);
} finally {
r.close();
}
}
}
class Resource implements Closeable {
@Override
public void close() {
System.out.println("释放资源");
}
}
如果资源实现了 Closeable 接口,那么可以用 try-with-resource 语法来省略 finally
public class TestFinally {
public static void main(String[] args) {
// try - with - resource
try (Resource r = new Resource()) {
System.out.println("使用资源");
int i = 1 / 0;
} catch (Exception e) {
System.out.println(e);
}
}
}
class Resource implements Closeable {
@Override
public void close() {
System.out.println("释放资源");
}
}