2

我有以下代码使用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;在 catch 之后添加一个语句。为什么?

4

5 回答 5

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在调用之前添加时,这会引发错误。

于 2012-06-26T00:28:31.797 回答
4

这是诸如closeSessionAndThrow. JLS 规则不允许编译器推断,因为该方法无条件地抛出异常,所以它永远不会正常返回。因此,调用代码必须像方法可以返回一样编写……即使“我们知道”它不可能发生。

你只需要顺其自然。这是一种“不寻常的”控制模式,Java 语言并不像您/我们希望的那样支持。


(在某些情况下,可以证明该方法在某些假设下总是会抛出异常。但是,由于该方法public位于不同的类中,因此假设之一是定义和使用该方法的类不会相互独立地更改和编译。当然,这不是编译器可以做出的那种假设……它部分解释了为什么 JLS 规则不试图涵盖这种模式。

如果他们要“修复”这个问题,则需要注释之类的东西,或者更改为 java 语法来声明辅助方法无法返回。)

于 2012-06-26T00:38:27.987 回答
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");
    }
}
于 2012-06-26T00:33:59.927 回答
0

由于此方法必须返回某些内容,因此您应该在return null;后面加上

this.closeSessionAndThrow(session, new RemoteException("Could not retrieve Data"));

但仍在catch从句内或使用finally从句。

为什么需要这样做?因为你的函数必须返回一些东西。并且由于它从以下位置返回:

this.closeSessionAndThrow(session, new RemoteException("Could not retrieve Data"));

并且不返回任何内容,这会导致编译器错误。

于 2012-06-26T00:20:02.013 回答
-3

将 finally 添加到 try-catch 块 finally { return null; } - 如果执行进入try块并且结果是成功它会返回,所以finally永远不会被执行。- 如果执行进入catch块,finally块在catch之后执行并返回 null。安全执行!

不正确答案!

于 2012-06-26T00:19:52.763 回答