3

たとえば、 getFoo() メソッドを使用して Foo オブジェクトを取得する必要があります。

Foo foo = getFoo();

この後、 getFoo() が Foo オブジェクトを正常に返さなかった場合を処理したいと考えています。これには、次の 2 つのケースが含まれます。

  1. getFoo() は例外をスローします。
  2. getFoo() の戻り結果は、null、空の文字列、0、または「空の結果」として扱われるべきものです。

理想的には、 getFoo() が空の結果を返す代わりに例外をスローすることを望みますが、それは私が所有していない別のパッケージのメソッドへの呼び出しである場合があります。

これらは私が考えることができる方法です:

1. 重複処理コード

Foo foo = null;
try {
    foo = getFoo();
} catch (ResourceNotFoundException ex) {
    logger.warn("blablabla");
    foo = defaultFoo;
    someOtherComplicatedStuff();
}
if (null == foo) {
    logger.warn("blablabla");
    foo = defaultFoo;
    someOtherComplicatedStuff();
}

これは間違いなく良い考えではありません。

2. 処理ロジックを個別の関数に移動

Foo foo = null;
try {
    foo = getFoo();
} catch (ResourceNotFoundException ex) {
    handleNullFoo(var1, var2, var3, var4);
}
if (null == foo) {
    handleNullFoo(var1, var2, var3, var4);
}

問題は、ロジックが多くのローカル変数を使用する可能性があることです。これらの変数を外部関数に渡すことはあまり意味がありません。さらに悪いことに、このプロセス中に一部の変数を変更する必要がある場合があります。引数がプリミティブ型の場合に発生する可能性がある問題は言うまでもなく、関数内の引数を変更することは良い習慣ではないと思います。

3.偽の例外をスローする

Foo foo = null;
try {
    foo = getFoo();
    if (null == foo) {
        throw new ResourceNotFoundException();
    }
} catch (ResourceNotFoundException ex) {
    logger.warn("blablabla");
    foo = defaultFoo;
    someOtherComplicatedStuff();
}

これは最もクリーンな方法ですが、一種のハックに似ています。例外クラスが属していないパッケージで ResourceNotFoundException をスローするのは適切でない場合があります。また、例外が関数内で処理されていることに気付かない可能性があるため、コードの可読性も低下します。

それで、あなたの提案は何ですか?

どうもありがとうございました!

4

4 に答える 4

3

別の方法を次に示します。

Foo foo = null;
try {
    foo = getFoo();
} catch (ResourceNotFoundException ex) {
    //TODO: log exception?
    foo = null;
}

if (null == foo) {
    logger.warn("blablabla");
    foo = defaultFoo;
    someOtherComplicatedStuff();
}

foo = null;句のincatchはほぼ確実に不要であることに注意してください。foo = getFoo()をスローできるコードが後にある場合にのみ必要ですResourceNotFoundException

于 2013-01-17T20:23:22.670 に答える
3

どうですか

class WrappedFooFactory extends FooFactory {
  public foo tryGetFoo() throws ResourceNotFoundException {
    Foo foo = getFoo();
    if (null == foo) throw new ResourceNotFoundException();
    return foo;
  }
}

そして後でちょうど

Foo foo = null;
try {
    foo = tryGetFoo();
} catch (ResourceNotFoundException ex) {
    logger.warn("blablabla");
    foo = defaultFoo;
    someOtherComplicatedStuff();
}
于 2013-01-17T20:25:31.477 に答える
2

そのような代替案はどうですか?これはより一般的であり、他の同様のケースにも適用できます。

1) 静的メソッドを作成します。

public static <E> E wrapNulls(Callable<E> callable, E defaultValue) {
    E result = null;
    try {
        result = callable.call();
    } catch (Exception e) {
        // log exception
    }
    return result == null ? defaultValue : result;
}

2) オブジェクトをそのようなスタイルで取得します。

    Foo foo = wrapNulls(new Callable<Foo>() {
        @Override
        public Foo call() throws Exception {
            return getFoo();
        }
    }, defaultValue);

UPD:このコードは少し冗長であると考えている方には、次のような機能強化を提案できます。

3) 静的クラスを作成します。

static abstract class C<E> implements Callable<E> {

    public abstract E c();

    @Override
    public E call() throws Exception {
        return c();
    }
}

Callableインターフェイスの代わりに使用します。

4)

Foo foo = wrapNulls(new C<Foo>() {public Foo c() { return getFoo(); }}, defValue);
于 2013-01-17T20:31:19.450 に答える
0

バージョン 3 は断然最悪です。(最もきれいではありません!)フロー制御に例外を使用しないでください!

アプリケーションによって多少異なりますが、通常は 2 つの異なるログ ステートメントを使用できるため、1 が最適です。

Foo foo = null;
try {
    foo = getFoo();
} catch (ResourceNotFoundException ex) {
    logger.warn("Foo: ", ex);
    foo = defaultFoo;
    someOtherComplicatedStuff();
}
if (null == foo) {
    logger.warn("Foo: Got unexpected null");
    foo = defaultFoo;
    someOtherComplicatedStuff();
}
于 2013-01-17T20:25:04.863 に答える