Java 在不重新编译实现类的情况下更改接口

Java 在不重新编译实现类的情况下更改接口,java,exception,undefined-behavior,throws,Java,Exception,Undefined Behavior,Throws,我有以下课程 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 s

我有以下课程

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.class
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下的Java1.6.32下运行它,我能指望没有什么不好的事情发生吗

更新:更新它是因为一些答案说我会在运行时得到一个
不兼容的ClassChangeError
。但我没有

台阶

1) 按照上面给出的方法编译X.java和Y.java。跑Y

输出:捕获

2) 更改X.java以注释掉抛出。重新编译X.java不要重新编译Y.java

流淌

输出:捕获

我在Windows7上运行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)

这是Java目前的一个限制。创建扩展当前接口的子接口,并在确实需要时重写该方法而不发生异常。一般来说,这被称为“二进制更改”,在代码运行时会导致链接中断,并且在JLS中有很好的定义(有一整章专门讨论它,您特别想要)

编辑:经过进一步调查,结果证明我错了。发件人:

对方法或构造函数的
throws
子句的更改不会破坏与预先存在的二进制文件的兼容性;这些子句仅在编译时检查


但是,我仍然建议不要这样做,因为这意味着选中的异常在运行时基本上可以变成未选中状态。

1。你为什么不试试呢?2.我想说,在实现程序中抛出的“多余”也会产生编译时错误消息。@TheBlastOne我确实试过了。它很好用。可能是您没有正确阅读我的文章-只有在我重新编译Y时才会发生编译时错误。Java 8
default
在这里没有帮助。删除异常并不是创建新方法。它正在以与其接口不一致的方式更改现有方法。@StephenC发现我完全错了,请参阅我的编辑。谢谢,Brian-所以现在看来它不是很危险。@user93353正确。您应该记录旧版本的接口可能会在Javadoc中引发异常。这样,如果您或任何其他人得到一个未捕获的
IOException
,您会记得这是一个更改,并且可以理解为什么。