默认情况下 Java 是否声明 "throws Exception"?

Does Java declare "throws Exception" by default?

考虑以下 classes:

class X
{
public void met()
   {
   }
}

class Y extends X
{
    public void met() throws NullPointerException
    {
        throw new NullPointerException();
    }
}

根据我阅读的其他问题 (Why can't overriding methods throw exceptions broader than the overridden method? and Java method throwing exception)

我知道子class中的重写方法必须抛出与重写方法中抛出的异常相同的异常或子class异常。

Java 方法总是抛出至少一个 Exception 类型的异常吗?

...换句话说,编译器添加 throws Exception

所以 class X 看起来像这样

class X {
    public void met() throws Exception {

    }
}

我想澄清一下,我没有看错默认的异常处理程序Exception总是被添加的。

相关问题:

IOException vs RuntimeException Java

有两种类型的异常:已检查的异常(如 ParseException 解析文本时)和未检查的异常(如 NullPointerException)。

检查异常必须在方法签名中声明。未经检查的异常可以在方法签名中声明。

当重写方法(从接口或超级 class)时,您只需指定要在实现中 抛出的异常 。您不能声明在覆盖方法中不允许的实现中抛出已检查的异常。

这是允许的:

class X { void someMethod() }
class Y extends X { @Override void someMethod() throws UncheckedException }

这是不允许的:

class X { void someMethod() }
class Y extends X { @Override void someMethod() throws CheckedException }

这也是允许的:

class X { void someMethod() throws CheckedException }
class Y extends X { @Override void someMethod() }

什么 slartidan said in 是完全正确的。再解释一下:

如果您在方法体内抛出一个 "Checked Exception",您需要处理它(使用 catch 块)或声明一个 throws-clause

重申之前链接的JLS:

  1. 异常是 class 扩展 Throwable
  2. 错误也是class 扩展 Throwable
    • 错误通常不应该被捕获,因为它们表示严重的问题。 (例如 OutOfMemoryError
    • 捕获 Exception 捕获错误
  3. 还有RuntimeException。这是一个 class 扩展 Exception

错误和运行时异常在编译时未检查,因为这正是"checked exception"的意思。

您可以在代码中的任何地方添加 ErrorRuntimeException

现在这对 throws 子句有何影响:

throws 子句指定调用声明的方法可能会导致指定的异常。有趣的是抛出期望 Throwable,这使得以下声明有效:

public void method() throws WhosebugError, NullPointerException {
    //...
}

在 throws 子句中声明非检查异常时没有编译器效果,但有时这样做是为了在源代码中更加清晰。

此外,JavaDoc 中有时会提到此类异常(例如 BigInteger#divide

但是编译器在覆盖方法时会检查 throws 子句。它有点类似于覆盖方法时的可见性规则。这意味着总是可以抛出未经检查的异常(并声明相应的 throws 子句)。以下声明有效:

public interface Demo {
    void test();
}
public class DemoImpl implements Demo {
    public void test() throws NullPointerException {
        throw new NullPointerException();
    }
}

反之亦然。编译器忽略 throws 子句中的未经检查的异常,因为它们与编译时检查无关:

public interface Demo {
    void test() throws NullPointerException;
}
public class DemoImpl implements Demo {
    public void test() {
        throw new NullPointerException();
    }
}

throws-clause 继承的一般规则是:一个接口来统治它们:接口必须声明所有可以通过实现 classes 抛出的检查异常。或者换句话说:

Implementing classes may declare a subset of the declared checked Exceptions in the interface method's throws-clause in the throws-clause of the implementing method

这意味着以下是有效的:

public interface Demo {
    void test() throws IOException, ParseException;
}
public class DemoImpl implements Demo {
    public void test() throws IOException {
        throw new IOException();
    }
}

在实现方法的 throws 子句中声明一个已检查的异常是无效的,而在相应的接口方法的子句中没有声明:

public interface Fail {
    void test() throws ParseException;
}
public class FailImpl implements Fail {
    public void test() throws IOException {
        throw new IOException();
    }
}