use*_*353 6 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 static void main(String [] args)
{
X x = new Y();
try
{
x.f();
}
catch (IOException e)
{
System.out.println("Caught");
}
}
}
Run Code Online (Sandbox Code Playgroud)
现在我编译两个并得到X.class
和Y.class
.
现在我改变X来移除投掷
public abstract interface X
{
public abstract void f();
}
Run Code Online (Sandbox Code Playgroud)
显然,如果我重新编译X和Y,Y的编译将失败
Y.java:4: f() in Y cannot implement f() in X; overridden method does not throw j
ava.io.IOException
Run Code Online (Sandbox Code Playgroud)
但是,我只是重新编译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
Run Code Online (Sandbox Code Playgroud)
运行
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)
Run Code Online (Sandbox Code Playgroud)
这是目前 Java 的一个限制。创建一个子接口来扩展当前接口并覆盖该方法,如果您确实需要的话,毫无例外。一般来说,这称为“二进制更改”,会在代码运行时导致链接断开,并且在 JLS 中定义良好(有一整章关于它,JLS 13,您特别需要JLS 13.5)。
编辑:经过进一步调查,事实证明我错了。从JLS 13.4.21开始:
对方法或构造函数子句的更改
throws
不会破坏与预先存在的二进制文件的兼容性;这些子句仅在编译时检查。
但是,我仍然建议不要这样做,因为这意味着已检查的异常实际上可以在运行时变为未检查的。