今天下午在写一个数据库操作的工具类时,发现了一个问题,先贴代码吧:
@Override
public User selectUser(String username) {
User user = null;
Connection conn =null;
PreparedStatement ps = null;
ResultSet rs = null;
// 选择用户
try {
conn = JDBCUtil.getConnection();
ps = (PreparedStatement) conn.prepareStatement("Select * from user where username =?;");
ps.setString(1, username);
rs = ps.getResultSet();
while(rs.next()) {
user = new User();
user.setUserName(rs.getString("username"));
user.setPassWord(rs.getString("password"));
user.setBirthday(rs.getDate("birthday"));
user.setEmail(rs.getString("email"));
}
return user;
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
try {
JDBCUtil.replase(conn,ps ,rs);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
就是这段代码,一直报:- This method must return a result of type User
我反复检查代码,我不是加了返回值了吗?为何现在却报无返回值呢?当我在try 板块之外再加上一句return user;则报错即消失。
当时就此问题和同事进行了讨论,在我的印象中,返回值是可以加在 try 板块中的,如今返回值加在了 try 板块里却报错,不能不让我困惑一阵子,同事看了代码后提醒说,如果try板块的代码执行不到return时报错,跳出执行,那这个方法就没有返回值了
我一听,说的有一定道理,但是还不足以解决我的疑惑,于是,思考再三,又参考了几个案例,终于弄清楚了该问题的原理,问题出在catch板块中,大家看到我在catch板块中写的是将异常打印出来,如果try板块中的代码执行不到return报错后就会进入catch板块,此时我执行完 异常打印后,继续往下执行时就会发现该方法没有返回值了,这也就是说,如果我在catch中添加返回值,则报错应该消失了,于是,我在catch板块中添加了返回值 return user;报错果然消失,验证了我的推测。
与此同时,为了验证我的对于异常原理的理解,我在catch板块中不是将异常打印出来,而是将异常抛出去,如下代码:
@Override
public User selectUser(String username) {
User user = null;
Connection conn =null;
PreparedStatement ps = null;
ResultSet rs = null;
// 选择用户
try {
conn = JDBCUtil.getConnection();
ps = (PreparedStatement) conn.prepareStatement("Select * from user where username =?;");
ps.setString(1, username);
rs = ps.getResultSet();
while(rs.next()) {
user = new User();
user.setUserName(rs.getString("username"));
user.setPassWord(rs.getString("password"));
user.setBirthday(rs.getDate("birthday"));
user.setEmail(rs.getString("email"));
}
return user;
} catch (Exception e) {
// TODO Auto-generated catch block
throw new RuntimeException(e);
}finally {
try {
JDBCUtil.replase(conn,ps ,rs);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return user;
}
这时,我们会发现最后一行 返回值处报错:Unreachable code (执行不到的代码)
这又是为啥呢?
这就涉及到异常执行的原理问题了,前者是在catch 中将异常打印,后者则将异常抛出。这两者的区别在于:前者打印异常后在当前方法中继续执行程序。而在catch中抛出异常,则是交给上层去处理,这样会使得selectUser()方法中断,后面的不会执行,添加也执行不到,即方法不再需要返回值,所以在try-catch块外加return就显得没有意义,此时,try-catch 板块之外的返回值需要删除。
至此,这个问题彻解!