默认情况下 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:
- 异常是 class 扩展
Throwable
- 错误也是class 扩展
Throwable
- 错误通常不应该被捕获,因为它们表示严重的问题。 (例如
OutOfMemoryError
)
- 捕获
Exception
不 捕获错误
- 还有
RuntimeException
。这是一个 class 扩展 Exception
错误和运行时异常在编译时未检查,因为这正是"checked exception"的意思。
您可以在代码中的任何地方添加 Error
和 RuntimeException
。
现在这对 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();
}
}
考虑以下 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:
- 异常是 class 扩展
Throwable
- 错误也是class 扩展
Throwable
- 错误通常不应该被捕获,因为它们表示严重的问题。 (例如
OutOfMemoryError
) - 捕获
Exception
不 捕获错误
- 错误通常不应该被捕获,因为它们表示严重的问题。 (例如
- 还有
RuntimeException
。这是一个 class 扩展Exception
错误和运行时异常在编译时未检查,因为这正是"checked exception"的意思。
您可以在代码中的任何地方添加 Error
和 RuntimeException
。
现在这对 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();
}
}