3

概要

私はクローズ可能な型を持っています。CloseableClassこれは、コンストラクター、メソッド、さらには内部で IOError をスローできますclose。私は try-with-resources を使用し、構築中のエラーを使用中のエラーとは異なる方法で処理したいと考えています (使用にはクリーンアップが含まれます)。さらに良いことに、保守可能なコードを書きたいと思っています。


クローズ可能なクラス インスタンスを構築し、それを try-with-resources ステートメントで使用したいとします。IOExceptionコンストラクターと、try-with-resources の本体で使用されるメソッドの両方をスローできます。

import java.io.Closeable;
import java.io.IOException;
import java.util.Random;

public class CloseableClass implements Closeable {
    public CloseableClass() throws IOException {
        if (new Random().nextBoolean()) {
            throw new IOException();
        }
    }

    public void internetStuff() throws IOException {
        if (new Random().nextBoolean()) {
            throw new IOException();
        }
    }

    public void close() throws IOException {
        if (new Random().nextBoolean()) {
            throw new IOException();
        }
    }

    public static void main(String[] args) {
        try (CloseableClass closeable = new CloseableClass()) {
            closeable.internetStuff();
        }
        catch (IOException e) {
            System.out.println("Bad error!");
        }
    }
}

コンストラクターと本体でスローされたエラーを別々に処理したいとします。それを行うためのサポートされている方法はありますか? Python では、次のようにします。

try:
    closeable = CloseableClass()
except IOException:
    print("Constructor error")
    return

try:
    with closeable:
        closeable.internet_stuff()
except IOException:
    print("Body error")

ただし、Java では、オブジェクトに 2 番目の名前を割り当てないとできません。

CloseableClass closeable_;

try {
    closeable_ = new CloseableClass();
}
catch (IOException e) {            
    System.out.println("Constructor error!");
    return;
}

try (CloseableClass closeable = closeable_) {
    closeable.internetStuff();
}
catch (IOException e) {
    System.out.println("Body error!");
}

これは主に の使用による「保守不可能なコード」であると言われましたがcloseable_、私はそうは思いません。それをエミュレートするというさらに悪い問題があるため、try-finally の使用は避けたいと思います。

CloseableClass closeable;

try {
    closeable = new CloseableClass();
}
catch (IOException e) {            
    System.out.println("Constructor error!");
    return;
}

try {
    closeable.internetStuff();
}
catch (IOException e) {
    try {
        closeable.close();
    }
    catch (IOException ignore) {
        // Already dealing with this
    }

    System.out.println("Body error!");
}
finally {
    try {
        closeable.close();
    }
    catch (IOException e) {
        System.out.println("Body error!");
    }
}

closeこれには、テストクラスが従わないノーオペレーションであるために2回目の呼び出しが必要であることに注意してください(AutoCloseableこれは必要ではありませんが、必要ですCloseable)。closeこれは、投げられない場合は少し良くなりますが、それほどではありません。

基本的に問題は、

  • close投げることができます
  • IOException重印刷を防ぐために対処する前に閉じる"Body error!"
  • try-with-resources の複数の初期化子で機能させる方法は明らかではありません
  • とにかくコードを複製することになります。

「保守不可能なコード」で生活することを余儀なくされていますか、それともこれに対処するための良い方法を見落としていますか?

4

2 に答える 2

1

'これには、no-op にするために閉じるための 2 番目の呼び出しが必要であることに注意してください' - いいえ、ブロックは常に実行されるためclose()catchブロック内に は必要ありません。ブロック内のような呼び出しで JVM を終了する場合finallyにのみ、ブロックclose()内を使用します。通常、クロックから呼び出し元にスローしますが、ほとんどの場合、ブロックでクリーンアップを実行します。catchSystem.exit()catchExceptioncatchfinally

Try-with-resource の方が優れていますが、throw のタイプと説明を使用Exceptionして、何がどこで間違っていたかを解読できます。

編集

私の知る限り、私は提案します:

1)リソースで試してください:

try(Resource resource = new Resource()){
    // use resource.
}catch(Exception e){
    // handle exception.
    // OR better to throw exception to caller.
    throw e;
}

2) 従来のスタイル:

Resource resource = null;
try{
    resource = new Resource();
    // use resource
}catch(Exception e){
    // handle exception.
    // OR better to throw exception to caller.
    throw e;
} finally {
   if(resource != null){
       try{
           resource.close();
       } catch(Exception e){
           // most of time you wont or cant do anything here.
       }
   }
}
于 2014-11-15T07:48:41.313 に答える