0

コーディング時。パズルを解いてみてください:

InputStreamDigestComputer が IOException をスローするときにクラス/メソッドを設計する方法は?

テンプレートメソッドは例外をスローしますが、オーバーライドされたメソッドは例外をスローしないため、この設計構造を使用できないようです。ただし、オーバーライドされたメソッドを変更してスローすると、他のサブクラスの両方がスローされます。では、この場合の良い提案はありますか?

abstract class DigestComputor{


    String compute(DigestAlgorithm algorithm){
        MessageDigest instance;
        try {
            instance = MessageDigest.getInstance(algorithm.toString());
            updateMessageDigest(instance);

            return hex(instance.digest());
        } catch (NoSuchAlgorithmException e) {
            LOG.error(e.getMessage(), e);
            throw new UnsupportedOperationException(e.getMessage(), e);
        }
    }

    abstract void updateMessageDigest(MessageDigest instance);

}

class ByteBufferDigestComputor extends DigestComputor{

    private final ByteBuffer byteBuffer;

    public ByteBufferDigestComputor(ByteBuffer byteBuffer) {
        super();
        this.byteBuffer = byteBuffer;
    }

    @Override
    void updateMessageDigest(MessageDigest instance) {
        instance.update(byteBuffer);

    }

}

class InputStreamDigestComputor extends DigestComputor{


               // this place has error. due to exception. if I change the overrided method to throw it. evey caller will handle the exception. but 
    @Override
    void updateMessageDigest(MessageDigest instance) {
        throw new IOException();

    }

}
4

3 に答える 3

2

この場合、スーパークラスは例外をスローするためのものではありません。

これは、サブクラスが、その上にあるソフトウェア アーキテクチャによって予期されていない例外をスローしている場合です。したがって、次のことができます。

  1. すべてのサブクラスを更新して例外をスローします。

  2. Digestor クラス フレームワーク全体を新しいクラス システムにラップします。

  3. (最も単純な) 現在のコードを維持し、スローする例外を RuntimeException にラップするだけです。

RuntimeExceptions は、Java で例外をスローする慣用的な方法です。例外は、コンパイラまたはメソッド シグネチャによってチェックされず、予期せずに発生します。

于 2012-07-01T03:11:07.970 に答える
1

他の誰かが示唆したように、最も簡単なことは、実際の例外を実行時例外で単純にラップすることです。その結果、throws句で例外を宣言する必要はありません。十分に野心的な場合は、RuntimeExceptionの独自のサブクラスを作成し、それをより高いレベルでキャッチできます(これは、休止状態が行うことであり、スローされたすべてのSQLExceptionをキャッチし、ランタイム例外であるDataAccessExceptionのサブクラスにラップします)。

于 2012-07-01T03:29:12.010 に答える
1

あなたの要件は統合失調症です。

DigestComputor.updateMessageDigestメソッドが をスローできるかできないかを決定する必要がありIOExceptionます。それを可能にしたい場合は、基本クラスの署名に追加する必要があります。これが、呼び出し元にIOException. しかし、欠点は、他のサブクラスの呼び出し元にもIOException... を処理するように強制することです。これは発生しません。

オーバーライドされたメソッドがスローしないチェック例外をスローするメソッド オーバーライドを作成することはできません。これはサブタイプの代入可能性を壊しますが、Java はそれを許可しません。

それは道の分岐点のようなものです。どちらかの方法で行くことを決定する必要があります。同時に両方に行くことはできません。


ただし、(一種の) 妥協点があります。

public abstract class Base {
    public abstract void method() throws IOException;
}

public class A extends Base {
    public void method() throws IOException {
        //
    }
}

public class B extends Base {
    public void method() {  // Doesn't throw!!!
        //
    }
}

ここで、呼び出し元がそのインスタンスを持っていることを知っている場合、次のBようなことができます:

Base base = ...
B b = (B) base;
b.method();  // No need to catch or propagate IOException

(IIRC、これを行う機能...つまり、オーバーライドメソッドでスローされる例外を減らす機能は、Java 1.5で追加されました。)

于 2012-07-01T03:48:31.953 に答える