7

次のインターフェースを検討してください。

public interface Generator {
    String generate() throws IOException;
}

および次の実装:

public class EmptyStringGenerator implements Generator {
    @Override
    public String generate() {
        return "";
    }
}

インターフェイスthrows IOExceptionで指定された署名の一部を省略したことに注意してください。Generatorそれでも、コンパイラ エラーやコンパイラ警告はなく、@Override注釈も文句を言いません。

これが意図したとおりに機能していることは承知しています。ただし、この背後にある意図を知りたいと思います。私のメソッドが実際に をスローしない場合は、スローしないIOExceptionだけで問題ありません。署名から削除する必要はありません。しかし、 のメソッド シグネチャからそれを削除するとEmptyStringGenerator、このクラスの現在および将来のすべてのサブクラスが、インターフェイスで実際に指定されている例外をスローする可能性を放棄することになります。

私には、これは実際には何のメリットももたらさない機能のように思えますが (2、3 のキーストロークを節約することは別として、これはまったくメリットではありません)、実際に使用するとひどい間違いになる可能性があります。

私の質問は、事実上、次のとおりthrowsです。派生クラスで例外を省略することのポイントは何ですか? この可能性が解決する問題は何ですか? なぜこれが許可されているのですか?

アップデート

「しかし、それのどこに害があるのですか?」と尋ねる人のために、私のコメントの1つからの私の例を次に示します. ちなみに、それはまさに私が今扱っているものなので、大げさではありません。

プログラマー A はインターフェイス I を指定します。プログラマー B は実装クラス X を記述しますが、スローを追加するのを忘れます。ここでは警告すら出されていないので、彼も決して気づきません。プログラマー C は、クラス X から継承する実装クラス Y を作成します。彼は、スローするつもりなので、そこにスローを配置することも特に望んでいます。しかし、インターフェイスにはそれが規定されていますが、B の見落としにより、彼はもはやそうすることが許可されていません。ここでその例外を使用することは事実上許可されていません。それはかなり大きな害です。特にクラスXがあなたの管理下にない場合。

4

3 に答える 3

1

派生クラスで例外を省略すると、throws例外をキャッチしなくても派生クラスのメソッドを呼び出すことができます。

のサブクラスEmptyStringGeneratorも例外をスローしないようにします。そうしないと、コードが処理する必要があるチェック済み例外がメソッド呼び出しによって発生する可能性があるかどうか、コンパイラーにとって確信が持てなくなります。その場合、throwsまったく意味がありません。

于 2013-09-11T11:58:01.257 に答える
0

Java では、Java 開発者の設計上の決定である実装または拡張時に、クラスの制限を緩和できるのは問題ありません。Sun がなぜこのように決定したのかはわかりません。もちろん、あなたの問題は理解できますが、現在の方法にもいくつかの利点があります。

インターフェイスは、1 つのジョブに対して複数の実装を持つ可能性があると考えています。たとえば、さまざまなニーズに合わせてさまざまな実装を持つ List クラスです。ただし、それらはすべて List インターフェイスを介して使用できます。要素がリストの一部でない場合、remove メソッドが CheckedException をスローするとします。私の実装で制限を緩和できない場合は、すべての List クラスがこの CheckedException をスローする必要があります。

したがって、クラスの内部で remove メソッドを使用すると、CheckedException を処理する必要があります。Interface を使用せずに List クラスを直接使用すると、例外をキャッチする必要があります。しかし、どちらの場合も、私はそれを必要とせず、決して起こらないと確信しています。したがって、現在のアプローチでは、多くの「try catch ignore」ブロックを節約できます。

現在のソリューションのもう 1 つの利点は、クラスが類似のインターフェイスに簡単に一致できることです。

たとえば、あるライブラリで誰かが追加しました:

public interface Generator {
    String generate() throws IOException;
}

そして他のライブラリでは:

public interface GeneratorInterface {
    String generate();
}

CheckedException なしで生成メソッドを使用してクラスを作成すると、これを簡単に使用して両方のインターフェイスを満たし、両方のライブラリで動作する可能性があります。

public class EmptyStringGenerator implements Generator,GeneratorInterface {

    @Override
    public String generate() {
        return "";
    }
}

また、私が知る限り、Java は Checked 例外と Unchecked 例外を処理する唯一の言語であるため、Java を介してプルする設計上の決定は、Checked 例外を持たない他の言語と比較して奇妙です。

于 2013-09-11T15:31:21.693 に答える