在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")
}
}
我有两个不同的Java程序,其中一个将Exception
在运行时编译并运行到一个,而另一个将不编译。
编译:
import myscala.SFoo;
import myscala.SFoobar;
public class Foobar {
public static void main(String[] args) {
SFoo mySFoo = new SFoobar();
mySFoo.bar();
}
}
不编译(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();
}
}
我真的不明白。为什么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");
}
}
它不能编译,因为:
error: bar() in SFoobar cannot override bar() in SFoo
void bar() throws Exception {
^
overridden method does not throw Exception
Java强制执行以下规则:重写方法不能抛出被其重写的方法未抛出的异常。这使得检查时向上转型,如转换时的异常类型安全的SFooBar
一个SFoo
。
如果并且已经用Java定义,则您对FooBar
类的第一个定义(将anSFooBar
存储在SFoo
变量中)将是绝对安全的。Java编译器知道an not throw ,并假设已遵守重写方法的规则,因此在此不做任何额外的检查。SFoo
SFooBar
SFoo.bar
Exception
但是,Scala编译器不在乎此规则是否适用于重写方法,而是可以让您打破这种类型的安全性。Java编译器忽略了这一事实,因此会生成在运行时中断的代码。Java和Scala之间的不匹配是任何编译器都无法解决的。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句