我正准备自己进行测试,我发现这段代码我不明白。
如果我覆盖这样的方法,它就无法编译。好,可以。我必须在第2行抛出一个父异常,(比如抛出异常),它会工作得很好...... 但是,为什么有可能改变第7行 public void charlie抛出NullPointerException ??这样编译得很好,因为我仍然没有在第2行中抛出任何东西。
1.public class A {
2. public void charlie()
3. {
4.
5. }
6. class B extends A{
7. public void charlie() throws IOException
8. {}
9. }
10.}
答案 0 :(得分:8)
NullPointerException
是未经检查的例外(因为它扩展了RuntimeException
)。它永远不需要声明,并且可以声明而不会影响其他任何内容。
您应该修改对已检查和未检查例外的理解。
Java exceptions tutorial可能是一个合理的起点。
答案 1 :(得分:1)
答案很简单: 如果A类中的原始方法不“支持”抛出它,则不能在B类覆盖methot中抛出异常。
假设您将从其他地方调用您的方法:
A a = new A();
a.charlie();
由于类charlie
中的方法A
会抛出任何异常,因此没问题。如果该方法会抛出异常,则必须编写
A a = new A();
try {
a();
} catch(IOException ex) { //or any other exception
//oh noes
}
但现在它变得复杂了,因为一种叫做类多态的东西会使你的工作模式变得复杂:
private A getA() {
return new B(); //this will work since B extends A
}
private void doSomething() {
A a = new A(); //you could also write A a = new B();
a.charlie();
}
现在,此代码采用a
,因为它是类A
中的对象,并且方法charlie()
没有抛出异常。尽管a
是来自类B
的对象,但是编译器不知道它并且不查看类B
中的方法中抛出的异常,因为a
来自等级A
,至少从编纂者的角度来看。
这就是为什么类charlie()
中的方法B
必须与类A
中的方法相同(输入参数,返回类型和抛出异常),您只能更改方法的主体。
但是,您仍然可以抛出NullPointerException或UnsuportedOperationException,因为它们属于RuntimeException,并且Java中的每个现有方法都会自动抛出RuntimeException,因此您可以随时抛出任何这些。
答案 2 :(得分:0)
IOException
是一个必须抓住的例外;你不能在没有throws
阻止的情况下调用try-catch
的方法。
但是,现在考虑以下内容:
A myObject;
myObject = new B(); // legal - polymorphism
myObject.charlie();
有人可能会认为这不会引发错误,因为A
没有throws
声明,但B
会声明{{1}}。因此,此代码不合法。
方法可能会声明更少的抛出异常,但更多。