7

私は次のクラスを持っています

public abstract interface X 
{
    public abstract void f() throws java.io.IOException;
}


public class Y implements X 
{
    public void f() throws java.io.IOException 
    {
        throw new java.ioIOException("Hello");
    }

    public static void main(String [] args)
    {
        X x = new Y();
        try
        {
            x.f();
        }
        catch (IOException e)
        {
            System.out.println("Caught");
        }
    }

}

今、私は両方をコンパイルして取得X.classY.classます。

ここで、X を変更してスローを削除します

public abstract interface X 
{
    public abstract void f();
}

明らかに、X と Y の両方を再コンパイルすると、Y のコンパイルは失敗します。

Y.java:4: f() in Y cannot implement f() in X; overridden method does not throw j
ava.io.IOException

ただし、X.java を再コンパイルし、古い X.java でコンパイルされた Y.class を保持する場合はどうすればよいでしょうか。

そのような場合はどうなりますか - それは明確に定義されていますか?

それとも、未定義のカテゴリに分類されますか?つまり、何かが起こる可能性がありますか?

保証はまったくありますか? つまり、Windows で常に Java 1.6.32 の下で実行している場合、悪いことが起こらないことに頼ることができますか?

更新:IncompatibleClassChangeError実行時に取得すると回答があったため、更新しました。しかし、私はしません。

手順

1) 上記のように X.java と Y.java の両方をコンパイルします。Y を実行します。

出力: キャッチ

2) X.java を変更して、スローをコメント化します。X.java を再コンパイルします。Y.java を再コンパイルしないでください。

実行 Y

出力: キャッチ

Windows 7でJavaを実行しています

コンパイラ

javac 1.6.0_35

ランタイム

java version "1.6.0_35"
Java(TM) SE Runtime Environment (build 1.6.0_35-b10)
Java HotSpot(TM) Client VM (build 20.10-b01, mixed mode, sharing)
4

1 に答える 1

4

これは現在の Java の制限です。現在のインターフェースを拡張するサブインターフェースを作成し、本当に必要な場合は例外なくメソッドをオーバーライドします。一般的に言えば、これは「バイナリ変更」と呼ばれ、コードの実行時にリンクが壊れてしまい、JLS で明確に定義されています ( JLS 13という章全体があり、具体的にはJLS 13.5が必要です)。

編集:さらに調査した結果、私が間違っていたことが判明しました。JLS 13.4.21から:

メソッドまたはコンストラクターの句を変更しても、throws既存のバイナリとの互換性は失われません。これらの句は、コンパイル時にのみチェックされます。

ただし、チェックされた例外が実行時に本質的にチェックされなくなる可能性があることを意味するため、これを行わないことをお勧めします。

于 2013-02-06T16:52:05.767 に答える