19

Parentのクラスは:

import java.io.IOException;
public class Parent {
        int x = 0;
        public int getX() throws IOException{
        if(x<=0){
         throw new IOException();
        }
       return x;
      }
 }

私はextendこのクラスでサブクラスを作成しますChild

public class Child1 extends Parent{
     public int getX(){
        return x+10;
   }
}

クラスのgetXメソッドをオーバーライドしているときに、メソッド定義から句を削除したことに注意してください。これで、コンパイラーによる異常な動作が予想されます。Childthrows

new Parent().getX() ;

try-catch予想どおり、ブロックで囲まずにコンパイルすることはありません。

new Child().getX() ;

ブロックで囲まずにコンパイルしtry-catchます。

ただし、以下のコード行にはtry-catchブロックが必要です。

Parent p = new Child();
p.getX();

これは予測可能であるため、つまり、実行時のポリモーフィズム中に親クラス参照を使用して子メソッドを呼び出すことができるので、Javaの設計者が、特定の親クラスメソッドをオーバーライドするときにメソッド定義にthrows句を含めることを必須にしないのはなぜですか?つまり、親クラスのメソッドの定義にthrows句が含まれている場合、それをオーバーライドするときに、オーバーライドするメソッドにもthrows句を含める必要があります。

4

4 に答える 4

35

いいえ、これは適切です-オーバーライドされたメソッドは、コンパイル時にオーバーライドされたメソッドを使用することを知っていて、わざわざしたくない呼び出し元に役立つ可能性があるため、スロー(および返される)の内容をより制限することができます。発生しない例外などを除きます。ただし、親宣言を介してアクセスする呼び出し元を驚かないように、より制限的である必要があります。

タイプの参照を介してオーバーライドされたメソッドを使用してもParent、「スローされる可能性があります」というコントラクトに違反することはIOExceptionありません。例外がなくても、コントラクトに違反することはありません。逆の場合(親が例外を宣言しなかったが、オーバーライドするメソッドが宣言した場合)、コントラクト違反になります。

于 2012-01-27T15:50:41.080 に答える
3

オーバーライドするメソッドは例外をまったくスローしない(または少なくとも少数の例外)可能性があるため、throw句(またはthrow句全体)から例外を削除できます。

オーバーライドするメソッドがすべての例外をキャッチし、それらをログに記録して、特別な値を返すとします。これは適切なスタイルではありませんが(メソッドのセマンティクスが変更されるため)、それでも可能であり、コンパイル時に処理していることがわかっている場合は、スローされない例外をキャッチする必要はありませんChild

参照を介してアクセスするクラスのユーザーは、追加される可能性Parentのある例外を認識していないため、例外のChild追加は機能しません。

于 2012-01-27T15:51:07.453 に答える
3

覚えやすい

  1. アクセス修飾子は、制限されたものから制限の緩いものに変更できます。
    たとえば、保護されたものからパブリックに変更できますが、その逆はできません。
  2. スロー署名は、親例外から子例外クラスに変更できますが、その逆はできません

このコードは有効です

public class A  {

    protected String foo() throws Exception{
        return "a";
    }

    class B extends A {
        @Override
        public String foo() throws IOException{
            return "b";
        }
    }
}

オーバーライドされた foo メソッドにはパブリック アクセスがあり、保護されておらず、例外の子である IOException をスローします

このコードは無効です

public class A  {

    public String foo() throws IOException{
        return "a";
    }

    class B extends A {
        @Override
        protected String foo() throws Exception{
            return "b";
        }
    }
}

オーバーライドされた foo メソッドには、より制限されたアクセス修飾子があり、IOException の子ではない例外をスローします

ちなみに、スーパークラスのメソッドをオーバーライドして、ecxeptions をまったくスローしないようにすることもできます

このコードは有効です

public class A  {

    public String foo() throws IOException{
        return "a";
    }

    class B extends A {
        @Override
        public String foo(){
            return "b";
        }
    }
}
于 2015-07-07T20:03:26.803 に答える
2

throws キーワードを使用せずにメソッドを自由にオーバーライドできます。すべての例外を制御してメソッドを開発したい場合は、throws 句を使用せずにメソッドをオーバーライドすることで実現できるからです。

ただし、throws 句をサブクラス メソッドに含める場合、throws 句は、スーパークラス メソッドによってスローされるものと同じか、例外のサブクラスに関連付ける必要があることに注意してください。例えば-

class Super{
    void a()throws IOException{
        ......
    }
}
class Sub extends Super{
    void a()throws IOException{
        ......
    }
}

クラス Sub の a() メソッドは、IOException または IOException の任意のサブクラスをスローする必要があります。そうしないと、コンパイラはエラーを表示します。

つまり、あなたが書くなら

void a()throws Exception

クラス Sub では、コンパイル エラーが発生します。

于 2012-01-28T05:49:04.180 に答える