1.结论
调用某个方法时,能否catch住异常,取决于调用的该方法在执行过程中是否有对应的异常抛出来.
2.示例
2.1自定义异常类MyException
package cn.yang37.zother.myexception;
/**
* @Description:
* @Class: MyException
* @Author: Yiang37
* @Date: 2020/11/26 21:22
* @Version: 1.0
*/
public class MyException extends RuntimeException{
//自定义异常通常实现这两个构造方法
public MyException() {
}
public MyException(String message) {
super(message);
}
}
2.2测试类ExceptionTest
单单只去用try-catch捕获,并不一定真的就靠谱,两段代码的区别仅仅在于doSome()方法内部(42行)的处理不同.
....
//两段代码的main方法是一样的,都是尝试执行 invokeDoSome()方法,出现异常后不进行后续操作
public static void main(String[] args) {
try {
//假设invokeDoSome()是帮助我向数据库插入一条记录;
invokeDoSome(1);
} catch (Exception e) {
System.out.println("若有该行,证明主方法能捕获到异常,捕获到异常:"+e.getMessage());
System.out.println("出现异常后,我知道不再进行业务逻辑...");
return;
}
System.out.println("我认为invokeDoSome帮我向数据库插入了一条记录,代码继续运行,于是我开始进行下一步逻辑...");
}
....
2.2.1测试类:内部catch后不抛出异常
package cn.yang37.zother.myexception;
/**
* @Description:
* @Class: ExceptionTest
* @Author: Yiang37
* @Date: 2020/11/26 21:27
* @Version: 1.0
*/
public class ExceptionTest {
//1.主方法
public static void main(String[] args) {
try {
//假设invokeDoSome()是帮助我向数据库插入一条记录;
invokeDoSome(1);
} catch (Exception e) {
System.out.println("若有该行,证明主方法能捕获到异常,捕获到异常:"+e.getMessage());
System.out.println("出现异常后,我知道不再进行业务逻辑...");
return;
}
System.out.println("我认为invokeDoSome帮我向数据库插入了一条记录,代码继续运行,于是我开始进行下一步逻辑...");
}
//2.invokeDoSome方法 调用了doSome方法
public static String invokeDoSome(int num){
return doSome(num);
}
//3.doSome方法
public static String doSome(int num) {
System.out.println("doSome开始执行");
/*假设我们不知道他内部的处理逻辑 只知道某种情况会抛出异常*/
try {.....}
catch (Exception e) {
//catch不抛出 打印信息并返回执行错误
System.out.println(e.getMessage());
return "error";
}
return "success";
}
}
执行结果
doSome开始执行
doSome()执行出错
我认为invokeDoSome帮我向数据库插入了一条记录,代码继续运行,于是我开始进行下一步逻辑...
2.2.2测试类:内部catch后抛出异常
package cn.yang37.zother.myexception;
/**
* @Description:
* @Class: ExceptionTest
* @Author: Yiang37
* @Date: 2020/11/26 21:27
* @Version: 1.0
*/
public class ExceptionTest {
//1.主方法
public static void main(String[] args) {
try {
//假设invokeDoSome()是帮助我向数据库插入一条记录;
invokeDoSome(1);
} catch (Exception e) {
System.out.println("若有该行,证明主方法能捕获到异常,捕获到异常:"+e.getMessage());
System.out.println("出现异常后,我知道不再进行业务逻辑...");
return;
}
System.out.println("我认为invokeDoSome帮我向数据库插入了一条记录,代码继续运行,于是我开始进行下一步逻辑...");
}
//2.invokeDoSome方法 调用了doSome方法
public static String invokeDoSome(int num){
return doSome(num);
}
//3.doSome方法
public static String doSome(int num) {
System.out.println("doSome开始执行");
/*假设我们不知道他内部的处理逻辑 只知道某种情况会抛出异常*/
try {.....}
catch (Exception e) {
//catch后抛出 打印信息 抛出异常
System.out.println(e.getMessage());
throw new MyException("由doSome()抛出的MyException");
}
return "success";
}
}
执行结果
doSome开始执行
doSome()执行出错
若有该行,证明主方法能捕获到异常,捕获到异常:由doSome()抛出的MyException
出现异常后,我知道不再进行业务逻辑...
3.结果说明
A 同样是调用doSome()的过程中doSome()执行出现了错误,只是由于前者的doSome()方法未抛出异常,就导致main()方法运行的结果不一样.
B 深层代码不抛出异常时,直接catch是无法捕捉的.
来对比下
- 不抛出异常
doSome开始执行
doSome()执行出错
我认为invokeDoSome帮我向数据库插入了一条记录,代码继续运行,于是我开始进行下一步逻辑...
- 抛出异常
doSome开始执行
doSome()执行出错
若有该行,证明主方法能捕获到异常,捕获到异常:由doSome()抛出的MyException
出现异常后,我知道不再进行业务逻辑...
在前一种情况里面,我们以为执行出错时能在catch进行处理,开始下一步的代码编写...然而doSome()已经出现了错误.
如果我们调用的是一个内部未抛出异常的方法,以为直接用最厉害的catch(Exception e)能抓住一切,其实是危险的写法.
4.原因分析
4.1为何内部的doSome()不去抛出异常让我们知道?
今天有点晚了,以后再完善...
4.2当内部不抛出异常而只给出返回值(前者)时,如何确保安全?
此时修改主方法的代码
public static void main(String[] args) {
try {
//尝试调用一个不知道情况的doSome()方法
String res = invokeDoSome(1);
if ("error".equals(res)){
throw new Exception("invokeDoSome的插入表操作是失败的!");
}
} catch (Exception e) {
System.out.println("若有该行,证明主方法能捕获到异常,捕获到异常:"+e.getMessage());
System.out.println("出现异常后,我知道不再进行业务逻辑...");
return;
}
System.out.println("我认为invokeDoSome帮我向数据库插入了一条记录,代码继续运行,于是我开始进行下一步逻辑...");
}
执行结果
doSome开始执行
doSome()执行出错
若有该行,证明主方法能捕获到异常,捕获到异常:invokeDoSome的插入表操作是失败的!
出现异常后,我知道不再进行业务逻辑...
5.附源码用于调试
package cn.yang37.zother.myexception;
/**
* @Description:
* @Class: ExceptionTest
* @Author: Yiang37
* @Date: 2020/11/26 21:27
* @Version: 1.0
*/
public class ExceptionTest {
public static void main(String[] args) {
try {
//尝试调用一个不知道情况的doSome()方法
String res = invokeDoSome(1);
if ("error".equals(res)){
throw new Exception("invokeDoSome的插入表操作是失败的!");
}
} catch (Exception e) {
System.out.println("若有该行,证明主方法能捕获到异常,捕获到异常:"+e.getMessage());
System.out.println("出现异常后,我知道不再进行业务逻辑...");
return;
}
System.out.println("我认为invokeDoSome帮我向数据库插入了一条记录,代码继续运行,于是我开始进行下一步逻辑...");
}
//doSome()会抛出一个自定义的异常
public static String doSome(int num) {
System.out.println("doSome开始执行");
/*假设我们不知道他内部的处理逻辑 只知道某种情况会抛出异常*/
try {
if (num % 2 != 0){
throw new MyException("doSome()执行出错");
}
//它某种情况下抛出了一个异常
}
catch (Exception e) {
System.out.println(e.getMessage());
return "error";
// throw new MyException("由doSome()抛出的MyException");
}
return "success";
}
public static String invokeDoSome(int num){
return doSome(num);
}
}