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;で、キャッチの後にステートメントを追加する必要があります。なんで?

4

5 に答える 5

4

これは、のようなメソッドの問題closeSessionAndThrowです。JLSルールで、メソッドが無条件に例外をスローするため、正常に戻ることはできないとコンパイラーが推測することはできません。したがって、呼び出し元のコードは、メソッドが戻ることができるかのように記述する必要があります...「わかっている」場合でも発生することはありません。

あなたは単に流れに従わなければなりません。これは、Java言語がサポートしていない「異常な」制御パターンです。


(特定の状況下では、特定の仮定の下でメソッドが常に例外をスローすることを証明できます。ただし、メソッドはpublic別のクラスにあるため、メソッドを定義して使用するクラスはそうではないという仮定の1つがあります。もちろん、それはコンパイラが行うことができる種類の仮定ではありません...そしてそれはJLSルールがこのパターンをカバーしようとしない理由を部分的に説明しています。

この問題を「修正」する場合は、アノテーションのようなものが必要になるか、ヘルパーメソッドが戻れないことを宣言するためにJava構文に変更する必要があります。)

于 2012-06-26T00:38:27.987 に答える
4

の宣言closeSessionAndThrowをreturnに変更し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。ヘルパーメソッドはその例外自体をスローするため、この2番目のメソッドが機能するthrowことはありません。throwヘルパーから例外を返すことはできますが、誰かが呼び出しの前に追加するのを忘れると、エラーが発生します。

于 2012-06-26T00:28:31.797 に答える
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ます。

なぜあなたはこれをする必要がありますか?関数は何かを返さなければならないからです。そして1つ以来それはから戻ります:

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

何も返さないため、コンパイラエラーが発生します。

于 2012-06-26T00:20:02.013 に答える
-3

最後にtry-catchブロックに追加します{returnnull; }-実行がtryブロックに入り、結果が成功した場合、それは返されるため、finallyは実行されません。-実行がcatchブロックに入ると、finallyブロックはcatchの後に実行され、nullを返します。安全な実行!

正解ではありません!

于 2012-06-26T00:19:52.763 に答える