5

だから私はtry/finallyブロックを持っています。finallyブロックでいくつかのメソッドを実行する必要があります。ただし、これらのメソッドはそれぞれ例外をスローする可能性があります。ネストされたfinallyブロックなしで、これらすべてのメソッドが呼び出される(または試行される)ことを保証する方法はありますか?

これは私が今していることです、それはかなり醜いです:

protected void verifyTable() throws IOException {
    Configuration configuration = HBaseConfiguration.create();
    HTable hTable = null;                                               

    try {
        hTable = new HTable(configuration, segmentMatchTableName);      

        //...
        //various business logic here
        //...

    } finally {                         
        try {
            try {
                if(hTable!=null) {
                    hTable.close(); //This can throw an IOException
                }               
            } finally {
                try {
                    generalTableHelper.deleteTable(configuration, segmentMatchTableName); //This can throw an IOException
                } finally {
                    try {
                        generalTableHelper.deleteTable(configuration, wordMatchTableName); //This can throw an IOException
                    } finally {
                        generalTableHelper.deleteTable(configuration, haplotypeTableName); //This can throw an IOException      
                    }
                }
            }                               
        } finally {
            HConnectionManager.deleteConnection(configuration, true); //This can throw an IOException   
        }
    }               
}

これを行うためのよりエレガントな方法はありますか?

4

8 に答える 8

2

Java で適切なリソース管理を行うための標準的な (実用的な) 方法は次のとおりです (原則は他の言語にも適用されます)。

Resource resource = acquire(resource);
try {
    use(resource);
} finally {
    resource.release();
}

または、現在のバージョンの Java SE でショートカットを (少し巧妙に) 使用します。

try (Resource resource = acquire(resource)) {
    use(resource);
}

(Joe K が指摘しているように、リソースをラップして、Java 言語が依存している特定のインターフェースを確認できるようにする必要があるかもしれません。)

2 つのリソースがあり、イディオムを 2 回適用するだけです。

Resource resource = acquire(resource);
try {
    SubResource sub = resource.acquire();
    try {
        use(sub);
    } finally {
        sub.release();
    }
} finally {
    resource.release();
}

Java SE 7 では:

try (
    Resource resource = acquire(resource);
    SubResource sub = resource.acquire()
) {
    use(resource, sub);
}

新しい言語機能の本当に大きな利点は、書き出すとリソース処理が頻繁に壊れてしまうことです。

より複雑な例外処理が必要になる場合があります。たとえば、IOException適切なアプリケーションへのスルーなどの低レベルの例外をスローしたくない場合は、RuntimeException. これは、Java の一般的な冗長性により、Execute Around イディオムを使用して除外できます (この優れた質問を参照してください)。Java SE 8 以降では、ランダムに異なるセマンティクスを持つ短い構文もあります。

with(new ResourceSubAction() { public void use(Resource resource, SubResource sub) {
    ... use resource, sub ...
}});
于 2012-09-06T22:14:06.290 に答える
2

これが Java 7 の場合、新しい try-with-resources コンストラクトの使用を検討できます。AutoCloseableテーブルを削除するには、いくつかの基本的なラッパーを作成する必要がある場合があります。

于 2012-09-06T21:55:44.963 に答える
0

java.util.concurrentフレームワークの使用を検討してください。各呼び出しを個別のCallable(名前付きまたは匿名)としてコーディングする場合は、ExecutorService.invokeAllを使用できます。

于 2012-09-06T23:26:14.780 に答える
0

一般的に、これを回避する方法はありません。複数の finally ブロックが必要です。

ただし、それが適切な設計であるかどうかにかかわらず、特定のコードについてはコメントしたくありません。確かにかなり奇妙に見えます。

于 2012-09-06T21:47:47.557 に答える
0

怖くて仕方がない。io リソースを閉じるときも同様のパターンがありました。たとえば、ファイルを閉じるときに IOException がスローされた場合はどうしますか? 通常は、無視する必要がありました。アンチパターンの場合、これは少しだったので、Java 7 で try-with 構文を導入しました。あなたの例では、他に選択肢はないと思います。おそらく、より明確にするために、それぞれを最終的に独自のメソッドに入れます

于 2012-09-06T21:55:26.577 に答える
0

finally ブロックから複数のメソッドを呼び出すには、いずれもスローしないようにする必要があります。これは、finally ブロックからスローされた例外が例外をオーバーライドするか、try/catch からスローされた値を返すためです。

最も一般的な使用例は、ファイルまたはデータベース接続です。この場合、「静かに閉じる」メソッドを記述します (または、Jakarta Commons IO などの既存のライブラリのメソッドを使用します)。クリーンアップする必要があるために既存のメソッドを使用できない場合は、独自のメソッドを記述します (この場合はdeleteTableQuietly())。

JDK-7 を使用している場合は、" try with resource " コンストラクトも使用できます。

于 2012-09-06T21:55:34.667 に答える
0

execute メソッドを使用して抽象クラス Action を作成し、そのクラスから、呼び出したい例外をスローするメソッドごとに 1 つのクラスを派生させ、execute メソッドからこのメソッドを呼び出すことができます。次に、アクションのリストを作成し、リストの要素をループして、try finally ブロックで execute メソッドを呼び出し、例外を無視します。

于 2012-09-06T21:56:14.950 に答える
0
deleteTableSilently(table1);    
deleteTableSilently(table2);    
deleteTableSilently(table3);


deleteTableSilently()
    try
        deleteTable()
    catch whatever
        log.error();
于 2012-09-06T22:27:08.150 に答える