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.classand Y.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 回答