web-dev-qa-db-ja.com

例外をスローしてキャッチするか、instanceofを使用しますか?

変数に例外があります(スローされません)。

最良の選択肢は何ですか?

Exception exception = someObj.getExcp();
try {
    throw exception;
} catch (ExceptionExample1 e) {
    e.getSomeCustomViolations();
} catch (ExceptionExample2 e) {
    e.getSomeOtherCustomViolations(); 
}

または

Exception exception = someObj.getExcp();
if (exception instanceof ExceptionExample1) {
    exception.getSomeCustomViolations();
} else if (exception instanceof ExceptionExample2) {
    exception.getSomeOtherCustomViolations();
}
21
Ruslan

instanceofを使用することをお勧めします。例外のスローは、複雑で費用のかかる操作です。 JVMは、例外しないでくださいが発生した場合に高速になるように最適化されています。例外は例外的でなければなりません。

throwテクニックはおそらく示されているようにコンパイルされないことに注意してください。例外タイプがチェック済み例外である場合、コンパイラーはそのタイプをキャッチするか、またはスローされたものとして宣言する必要があると不平を言うでしょう(else { ... }句に対応特定のサブタイプではない例外をどのように処理するかに応じて、instanceofテクニックを使用します)。

9
Boann

みんなのバブルを破りたくないのですが、try/catchを使うのは速いです。それが「正しい」方法であると言っているわけではありませんが、パフォーマンスが重要であれば、それが勝者です。以下は、次のプログラムの結果です。

実行1

  • サブラン1:Instanceof:130 ms
  • サブラン1:試行/キャッチ:118ミリ秒
  • サブラン2:Instanceof:96 ms
  • サブラン2:試行/キャッチ:93ミリ秒
  • サブラン3:Instanceof:100 ms
  • サブラン3:試行/キャッチ:99ミリ秒

実行2

  • サブラン1:Instanceof:140 ms
  • サブラン1:試行/キャッチ:111ミリ秒
  • サブラン2:Instanceof:92 ms
  • サブラン2:試行/キャッチ:92ミリ秒
  • サブラン3:Instanceof:105 ms
  • サブラン3:試行/キャッチ:95ミリ秒

実行

  • サブラン1:Instanceof:140 ms
  • サブラン1:試行/キャッチ:135 ms
  • サブラン2:Instanceof:107ミリ秒
  • サブラン2:試行/キャッチ:88ミリ秒
  • サブラン3:Instanceof:96 ms
  • サブラン3:試行/キャッチ:90ミリ秒

テスト環境

  • Java:1.7.0_45
  • Mac OSXマーベリックス

各実行のウォームアップサブランを割り引くと、instanceofメソッドはtry/catchのパフォーマンスのみを達成します。 instanceofメソッドの平均(割引ウォームアップ)は98ミリ秒で、try/catchの平均は92ミリ秒です。

各メソッドがテストされた順序は変更しなかったことに注意してください。私は常にinstanceofのブロックをテストしてから、try/catchのブロックをテストしました。これらの結果と矛盾または確認している他の結果を見たいです。

public class test {

    public static void main (String [] args) throws Exception {
        long start = 0L;
        int who_cares = 0; // Used to prevent compiler optimization
        int tests = 100000;

        for ( int i = 0; i < 3; ++i ) {
            System.out.println("Testing instanceof");
            start = System.currentTimeMillis();
            testInstanceOf(who_cares, tests);
            System.out.println("instanceof completed in "+(System.currentTimeMillis()-start)+" ms "+who_cares);

            System.out.println("Testing try/catch");
            start = System.currentTimeMillis();
            testTryCatch(who_cares, tests);
            System.out.println("try/catch completed in "+(System.currentTimeMillis()-start)+" ms"+who_cares);
        }
    }

    private static int testInstanceOf(int who_cares, int tests) {
        for ( int i = 0; i < tests; ++i ) {
            Exception ex = (new Tester()).getException();
            if ( ex instanceof Ex1 ) {
                who_cares = 1;
            } else if ( ex instanceof Ex2 ) {
                who_cares = 2;
            }
        }
        return who_cares;
    }

    private static int testTryCatch(int who_cares, int tests) {
        for ( int i = 0; i < tests; ++i ) {
            Exception ex = (new Tester()).getException();
            try {
                throw ex;
            } catch ( Ex1 ex1 ) {
                who_cares = 1;
            } catch ( Ex2 ex2 ) {
                who_cares = 2;
            } catch ( Exception e ) {}
        }
        return who_cares;
    }

    private static class Ex1 extends Exception {}

    private static class Ex2 extends Exception {}

    private static Java.util.Random Rand = new Java.util.Random();

    private static class Tester {
        private Exception ex;
        public Tester() {
            if ( Rand.nextBoolean() ) {
                ex = new Ex1();
            } else {
                ex = new Ex2();
            }
        }
        public Exception getException() {
            return ex;
        }
    }
}
10
disrvptor

実際にプレーンオブジェクトを使用して「制約」を表すことを強くお勧めします。マーキングインターフェイス(例:Message)またはJava.lang.String あなた次第です。例外は、どちらかを機能させることができたとしても、意図したとおりに使用することを意図したものではありません(2番目はより高速であると予想されますが、時期尚早に最適化されます...)。

4
Elliott Frisch

また、getCustomViolation()メソッドを含むカスタム例外のインターフェースを作成して、ポリモーフィズムを使用することもできます。次に、各カスタム例外はそのインターフェースとそのメソッドを実装します。

2
Joe