hi,大家好,今天xin麒来分析一个在业务代码上遇到的问题:
具有返回值的类方法中try… catch…的代码有异常抛出时为什么不需要再在末尾保存return?
一、前提引入:
具体可以看看这个:https://www.bilibili.com/video/BV1Y7411K7zz?p=302
如果想直接看正文的可以跳过这部分哈。
下面的代码中的解释是xin麒在做项目时自己所思所想所推理的纯个人笔记哈。
public int update(String sql,Object ...args){
System.out.println("BaseDao - update in ["+Thread.currentThread().getName() + "]");
Connection conn = JdbcUtils.geConnection();
try {
return queryRunner.update(conn,sql,args);
}catch (SQLException throwables) {
throwables.printStackTrace();
throw new RuntimeException(throwables);
} /*catch (SQLException throwables) {
throwables.printStackTrace();
}finally {
JdbcUtils.closeConnection(conn);
}
return -1;*/
}
/**
*
* @param type
* @param sql
* @param args
* @param <T>
* @return
*/
public <T> T queryForOne(Class<T> type,String sql,Object ...args){
Connection conn = JdbcUtils.geConnection();
try {
return queryRunner.query(conn,sql,new BeanHandler<T>(type),args);
}catch (SQLException throwables) {
throwables.printStackTrace();
throw new RuntimeException(throwables);
} /*catch (SQLException throwables) {
throwables.printStackTrace();
}finally {
JdbcUtils.closeConnection(conn);
}
return null;*/
}
/**
*
* @param type
* @param sql
* @param args
* @param <T>
* @return
*/
public <T> List<T> queryForlist(Class<T> type, String sql, Object ...args){
Connection conn = JdbcUtils.geConnection();
try {
return queryRunner.query(conn,sql,new BeanListHandler<T>(type),args);
}catch (SQLException throwables) {
throwables.printStackTrace();
throw new RuntimeException(throwables);
} /*catch (SQLException throwables) {
throwables.printStackTrace();
}finally {
JdbcUtils.closeConnection(conn);
}
return null;*/
}
/**
*
* @param sql
* @param args
* @return
*/
public Object queryForSingleValue(String sql,Object ...args){
Connection conn = JdbcUtils.geConnection();
try {
return queryRunner.query(conn,sql,new ScalarHandler(),args);
} catch (SQLException throwables) {
throwables.printStackTrace();
throw new RuntimeException(throwables);
}/*catch (SQLException throwables) {
throwables.printStackTrace();
} finally {
JdbcUtils.closeConnection(conn);
}
return null;为什么这里去掉,没有返回值也可以??,
个人理解:本来应该是:try如果没错误,那么根本不会走到return null的结果;
try有错误,那么就return null;
//现在是: try如果没错误,那么根本不会走到return null的结果;
//try如果有错误,那么抛异常,
纯个人深入分析:
本来如果try存在错误,那么希望可以事务回滚,
但是return null或其他都不知道会不会使得事务rollback ;
相反,当 try存在错误时,抛出异常必定可以导致事务回滚,由此从业务角度分析是正想要看到的。
从代码角度:分析这个程序的细节部分(可能这个方法的细节代码很特殊):
try内部是有返回值的,
总逻辑关系:①如果没错误,那么直接返回;
②如果有错误,那么抛异常,所以,try...catch...外的内容就算存在 return 语句也不会执行。
那么try...catch...外的内容就应该毫无作用,在编译、代码设计工程师应该考虑到这一点了,所以
不会让多余useless的coding编译成为字节码文件load到jvm里面吧?所以idea会检查到错误
所以必须去除这个无作用的return语句
*/
}
二、问题简化
从上面的代码,xin麒抽出一个例子:
public Object queryForSingleValue(String sql,Object ...args){
Connection conn = JdbcUtils.geConnection();
try {
return queryRunner.query(conn,sql,new ScalarHandler(),args);
} catch (SQLException throwables) {
throwables.printStackTrace();
throw new RuntimeException(throwables);
}
}
以上的代码的trycatch
代码后面没有返回值,也并没有报错信息
在编辑器是没有提示报错信息的:
代码块①:
产生的疑问1:为什么这里没有返回值也可以??
代码块②:如果把抛出的异常清了,则会有报错提示:
代码块③:于是xin麒添加一个返回值:
代码块④:如果将代码块①和③结合,那么会提示报错信息:
下面查询一下这个xin麒也不是很懂的单词:
对于②个人理解:
- 本来应该是:try如果没错误,那么根本不会走到return null的结果;
try如果有错误,那么就return null;
对于结合代码块①和代码块③、代码块④的分析:
- try如果没错误,那么根本不会走到return null里头去;
try如果有错误,那么抛异常。
这个是基于xin麒项目问题中的业务代码的纯个人分析,因为业务代码xin麒没有细说所以大家可以忽略哈,直接跳过,到下面看代码角度即可:
如果try代码内本来就存在错误,那么肯定是希望可以事务回滚,但是return null或其他操作是不知道能否使得事务rollback的;
相反,当 try存在错误时,抛出异常必定可以导致事务回滚,由此从业务角度分析是正想要看到的。所以没有return null语句是可行的。
总结:
从代码角度的再次分析:这个程序的细节部分(可能这个方法的细节代码很特殊):
-
首先我们知道:try内部是有返回值的,
-
总逻辑关系:①如果没错误,那么直接返回try内部代码的内容,不会执行后面return null的内容;
②如果有错误,那么抛异常。所以,try…catch…外的内容就算存在 return 语句也不会执行。 -
那么try…catch…外的内容就应该毫无作用,设计代码以及代码编辑器之类的的工程师应该考虑到这一点了,所以
不会让多余useless的coding编译成为字节码文件load到jvm
里面再占用一波空间吧?所以如果该返回值的类方法如果在try中有返回值,catch中有异常抛出的情况下,末尾如果有值返回,idea必定会检查到错误。
所以必须去除类方法末尾这个无作用的return语句。
上述均为xin麒个人所演绎推理所得,如果有错误,希望指正!!!