我有以下代码使用hibernate在错误时抛出自定义异常,我也希望在这种情况下关闭会话,因为除非在客户端计算机上收到异常,否则不会捕获异常。
public <T> T get(final Session session, final String queryName) throws RemoteException
{
final Query query = // query using given session ...
try
{
return (T) query.uniqueResult();
}
catch (final HibernateException e)
{
SessionManager.logger.log(Level.SEVERE, "Could not retrieve Data", e);
this.closeSession(session);
throw new RemoteException("Could not retrieve Data");
}
}
现在我有一个帮助方法关闭会话并抛出一个给定的异常:
public void closeSessionAndThrow(final Session session, final RemoteException remoteException)
throws RemoteException
{
this.closeSession(session);
throw remoteException;
}
现在我想我可以使用以下方法简化上面的代码:
public <T> T get(final Session session, final String queryName) throws RemoteException
{
final Query query = // query using given session ...
try
{
return (T) query.uniqueResult();
}
catch (final HibernateException e)
{
SessionManager.logger.log(Level.SEVERE, "Could not retrieve Data", e);
this.closeSessionAndThrow(session, new RemoteException("Could not retrieve Data"));
}
}
现在我需要在捕获后添加return null;
语句。为什么呢?
答案 0 :(得分:4)
将closeSessionAndThrow
的声明更改为返回RemoteException
,然后“抛出”在客户端代码中调用它的返回结果。
public RemoteException closeSessionAndThrow( ... ) // <-- add return type here
throws RemoteException { ... }
public <T> T get( ... ) throws RemoteException
{
try { ... }
catch (final HibernateException e)
{
throw this.closeSessionAndThrow( ... ); // <-- add "throw" here
}
}
这使得编译器认为它将始终抛出从closeSessionAndThrow
返回的任何异常。由于辅助方法本身会抛出异常,因此第二个throw
永远不会发挥作用。虽然您可以从帮助程序返回异常,但是当有人忘记在调用之前添加throw
时会发生错误。
答案 1 :(得分:4)
这是像closeSessionAndThrow
这样的方法的问题。 JLS规则不允许编译器推断出由于该方法无条件地抛出异常,因此它永远无法正常返回。因此,必须编写调用代码,就好像方法可以返回...即使“我们知道”它也不会发生。
你只需要顺其自然。这是一种“不寻常”的控制模式,Java语言不支持你/我们想要的。
(在某些情况下,可以证明该方法总是在某些假设下抛出异常。但是,由于该方法是public
并且在不同的类中,其中一个假设是定义的类并且使用该方法不会彼此独立地进行更改和编译。当然,这不是编译器可以做出的那种假设......而且它部分解释了为什么JLS规则不会尝试覆盖此模式
如果他们要“解决”这个问题,就需要注释,或者更改java语法来声明帮助方法不能返回。)
答案 2 :(得分:1)
虽然closeSessionAndThrow总是抛出远程异常,但编译器不会深入到该方法中找出它,因此编译器只知道它可能抛出一个RemoteException,而不是它会。我可能会做这样的事情:
public RemoteException closeSessionAndThrow(final Session session, final Exception e, String msg)
{
SessionManager.logger.log(Level.SEVERE, msg, e);
this.closeSession(session);
return new RemoteException(msg);
}
public <T> T get(final Session session, final String queryName) throws RemoteException
{
final Query query = // query using given session ...
try
{
return (T) query.uniqueResult();
}
catch (final HibernateException e)
{
throw this.closeSessionAndThrow(session, e, "Could not retrieve Data");
}
}
答案 3 :(得分:0)
由于此方法必须返回某些内容,因此您应该在{/ 1}之后放置
return null;
但仍在this.closeSessionAndThrow(session, new RemoteException("Could not retrieve Data"));
子句中或使用catch
子句。
你为什么需要这样做?因为你的函数必须返回一些东西。并且从它返回:
finally
并且不返回任何内容,这会导致编译器错误。
答案 4 :(得分:-3)
最后添加到try-catch块 终于{ return null; } - 如果执行进入尝试阻止并且结果成功则会返回,因此终于永远不会被执行。 - 如果执行进入 catch 块,最终块将在 catch 之后执行并返回null。安全执行!
答案不正确!