尝试/捕捉内部或外部function
关于使用try catch(最佳实践),我有一个非常基本的问题。 我有一个像这样的简单函数(DAO)
public void addVehicle(Vehicle vehicle) { em.getTransaction().begin(); em.persist(vehicle); em.getTransaction().commit(); }
并在Web服务中使用DAOfunction:
@WebMethod(operationName = "addVehicle") public void addVehicle(Vehicle vehicle) { try { vehicleDAO.addVehicle(vehicle); System.out.print("Vehicle added"); } } catch (Exception e) { e.printStackTrace(); } }
或者更好地使用DAO函数中的try
/ catch
如下所示:
public void addVehicle(Vehicle vehicle) { try { em.getTransaction().begin(); em.persist(vehicle); em.getTransaction().commit(); } catch (Exception e) { e.printStackTrace(); } }
对此没有完美的规则。
如果在需要时尽早捕获exception,代码通常会更清晰,更简单,但应尽可能晚。
你应该考虑在Exception
发生时谁必须采取行动,这决定了你是否在方法(addVehicle)中catch
它,或者如果你throw
它以致调用者必须catch
它。
例如:
public void addVehicle(Vehicle vehicle) throws SQLException{ em.getTransaction().begin(); em.persist(vehicle); em.getTransaction().commit(); }
在这个例子中,调用者必须捕获。
此外,只有在少数情况下,您应该捕获Exception
或RunTimeException
,更好地捕获特定的Exception,如IOException
而不是Exception
。
在你的代码中的某个地方,你需要一个“最后一道防线”才能catch (Exception ex).
这是处理不应发生的错误所必需的。
您应该只捕获您想要处理的exception。 您可以包含一个最顶层的exception处理程序,将任何未处理的exception转换为对最终用户有用的东西。
而不是e.printStackTrace();
,尝试返回正确的exception消息。
在此处了解有关exception处理的更多信息
以下是有关exception处理的更多讨论 。
AFAIK最佳实践将是这样的:
public void addVehicle(Vehicle vehicle) { em.getTransaction().begin(); try { em.persist(vehicle); em.getTransaction().commit(); } catch (Exception e) { if (em.getTransaction().isActive()) { try { em.getTransaction().rollback(); } catch (Exception e) { // Log rollback failure or something } } throw new RuntimeException(e); } }
使用两者,唯一的原因是使用catch RuntimeException
甚至是Throwable
。 因为这种exception通常是由底层框架引发的。 如果要在再次重新抛出之前进行某些操作(例如日志记录,打印堆栈跟踪等),则应该捕获这种exception。 如果你不这样做,你可能会失去例外的原因。
@Transactional public void addVehicle(Vehicle vehicle) { try { //do whatever with session } catch (RuntimeException e) { e.printStackTrace(); throw new Exception(e); } }
在决定在何处处理特定类型的exception时,最好的经验法则是停止查看代码的微观细节,退后一步,了解程序的逻辑并考虑以下事项:
- 您的程序当前操作无法恢复的exception是什么? 如果是,那么将exception放在该操作的最顶层是有意义的,以确保它不会继续。
- 如果你的程序可以解决那个特定的exception(也许是在放弃之前尝试其他的东西),那么从每一层嵌套函数开始(从最高层开始),每次都问问自己: 如果在执行某些代码行期间发生exception在这个函数中,这个函数继续有意义吗? 只要答案是“是”,就进入更深层次。 一旦答案是“否”,很可能这是放置该exception的处理程序的最佳位置。
- 除了上一个之外,你可以决定你的程序的替代“攻击计划”是什么,以防exception被引发。 然后,转到会引发该exception的代码行并问自己: 这个函数是否有足够的上下文信息来执行我想到的解决方法? 只要答案为“否”,请转到调用者函数。 一旦答案变为“是”,请考虑将exception处理程序放在那里。
话虽这么说,你应该只捕获合理的专门exception并保持catch(Exception ex)
构造只作为最后一个手段,只在顶层,并且只在所有其他可能的catch
块之后,保留它只用于你真正无法遇到的各种exception在撰写本文时预测。 (我知道你说这不是这个例子的重点,但是既然我们就是这样,我认为应该提到这个答案更完整。)