2rs*_*2ts 6 java annotations scala exception throws
在Java中,throws如果原始抽象方法不能(overridden method does not throw Exception.),则无法指定重写的抽象方法是否有异常.但是在Scala中,您可以执行此操作,因为它没有检查异常.很好,但如果您使用的@throws注释应该将Java编译器发送给正在发生的事情,对吧?
鉴于此Scala代码:
package myscala
abstract class SFoo {
def bar(): Unit
}
class SFoobar extends SFoo {
@throws[Exception]
override def bar(): Unit = {
throw new Exception("hi there")
}
}
Run Code Online (Sandbox Code Playgroud)
我有两个不同的Java程序,其中一个将Exception在运行时编译并运行,另一个将无法编译.
编译:
import myscala.SFoo;
import myscala.SFoobar;
public class Foobar {
public static void main(String[] args) {
SFoo mySFoo = new SFoobar();
mySFoo.bar();
}
}
Run Code Online (Sandbox Code Playgroud)
不编译(unreported exception Exception; must be caught or declared to be thrown):
import myscala.SFoo;
import myscala.SFoobar;
public class Foobar {
public static void main(String[] args) {
SFoobar mySFoo = new SFoobar(); // only difference is the declared type
mySFoo.bar();
}
}
Run Code Online (Sandbox Code Playgroud)
我真的不明白.为什么Java编译器没有注意到我声明SFoobar.bar抛出异常的事实,即使Foo.bar没有这样的声明,结果引发类似的编译错误?
如果转换斯卡拉代码SFoo和SFooBar以等效的Java代码:
abstract class SFoo {
void bar() {}
}
class SFoobar extends SFoo {
void bar() throws Exception {
throw new Exception("hi there");
}
}
Run Code Online (Sandbox Code Playgroud)
它不编译,因为:
error: bar() in SFoobar cannot override bar() in SFoo
void bar() throws Exception {
^
overridden method does not throw Exception
Run Code Online (Sandbox Code Playgroud)
Java强制执行以下规则:重写方法不能抛出它们覆盖的方法未抛出的异常.这使得在向上转换时检查异常类型是安全的,例如在转换为a SFooBar时SFoo.
如果并且已经在Java中定义了,那么FooBar类的第一个定义( 其中a SFooBar存储在SFoo变量中)将是完全安全的.Java编译器知道a 不抛出,假设已经遵守了重写方法的规则,因此这里不做任何额外的检查.SFooSFooBarSFoo.barException
但是,Scala编译器不关心重写方法的此规则,并允许您打破此类型的安全性.Java编译器忽略了这一事实,因此产生了在运行时中断的代码.这是Java和Scala之间的不匹配,两个编译器都无法解决.