我有以下类(class)
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 以删除 throws
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)
最佳答案
这是目前 Java 中的一个限制。创建一个扩展您当前接口(interface)的子接口(interface),如果您确实需要它,则无一异常(exception)地覆盖该方法。一般来说,这称为“二进制更改”,会在代码运行时导致链接断开,并且在 JLS 中定义明确(有一整章,JLS 13,您特别需要 JLS 13.5)。
编辑:经过进一步调查,事实证明我错了。来自 JLS 13.4.21 :
Changes to the
throws
clause of methods or constructors do not break compatibility with pre-existing binaries; these clauses are checked only at compile time.
但是,我仍然建议不要这样做,因为这意味着已检查的异常在运行时基本上可以变成未检查的。
关于java - 在不重新编译实现类的情况下更改接口(interface),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14734345/