Java是否默认声明“抛出异常”?

时间:2021-10-16 11:41:04

Consider following classes:

考虑以下课程:

class X
{
public void met()
   {
   }
}

and

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

From what I have read on other questions ( Why can't overriding methods throw exceptions broader than the overridden method? and Java method throwing exception )

从我在其他问题上阅读的内容(为什么不能覆盖方法抛出比重写方法更广泛的异常?和抛出异常的Java方法)

I understand that the overriding method in the subclass, has to throw either the same or a subclass of the exception thrown in the overridden method.

我理解子类中的重写方法必须抛出重写方法中抛出的异常的相同或子类。

Do Java methods always throw at least an exception of the type Exception?

Java方法总是抛出异常类型的异常吗?

...In other words the compiler adds throws Exception

...换句话说,编译器添加了抛出异常

So the class X would look like this

所以X类看起来像这样

class X {
    public void met() throws Exception {

    }
}

I want to clarify that I am not mistaken about the fact that the default exception handler Exception is always added.

我想澄清一点,我并没有错误地总是添加默认异常处理程序Exception。

Related questions:

IOException vs RuntimeException Java

IOException与RuntimeException Java

2 个解决方案

#1


There are two types of Exceptions: checked Exceptions (like ParseExceptionwhen parsing text) and unchecked Exceptions (like NullPointerException).

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

Checked Exceptions must be declared in the method signature. Unchecked Exceptions may be declared in the method signature.

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

When overriding methods (from an interface or a super class) you only have to specify the exceptions, that you are throwing in your implementation. You cannot declare to throw checked exceptions in an implementation that are not allowed in the overridden method.

当重写方法(来自接口或超类)时,您只需指定实例中的异常。您不能声明在重写方法中不允许的实现中抛出已检查的异常。

This is allowed:

这是允许的:

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

This is not allowed:

这是不允许的:

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

This is also allowed:

这也是允许的:

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

#2


What slartidan said in their answer is fully correct. To explain a little more:

slartidan在回答中说的是完全正确的。再解释一下:

If you are throwing a "Checked Exception" inside the body of a method, you are required to either handle it (using a catch-block) or to declare a throws-clause

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

To reiterate the previously linked JLS:

重申先前链接的JLS:

  1. An Exception is a class extending Throwable
  2. Exception是一个扩展Throwable的类

  3. An Error also is a class extending Throwable
    • Errors usually should not be caught, because they indicate serious problems. (e.g. OutOfMemoryError)
    • 通常不应该发现错误,因为它们表明存在严重问题。 (例如OutOfMemoryError)

    • catching Exception does not catch Errors
    • 捕获异常不会捕获错误

  4. 错误也是一个扩展Throwable错误的类通常不应该被捕获,因为它们表明存在严重问题。 (例如OutOfMemoryError)捕获异常不会捕获错误

  5. There also is RuntimeException. This is a class extending Exception
  6. 还有RuntimeException。这是一个扩展Exception的类

Errors and Runtime Exceptions are not checked at compile time, because that exactly is what "checked exception" means.

在编译时不会检查错误和运行时异常,因为这正是“已检查异常”的含义。

You may throw Errors and RuntimeExceptions anywhere in your code.

您可以在代码中的任何位置抛出Errors和RuntimeExceptions。

Now how does this affect throws clauses:

现在,这如何影响throws子句:

A throws clause specifies that an invocation of the declared method may result in the exception specified. Interestingly throws expects a Throwable, which makes following declaration valid:

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

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

There is no compiler effect when declaring non-checked Exceptions in a throws clause, but it's sometimes done for additional clarity in your sourcecode.

在throws子句中声明未检查的异常时没有编译器效果,但有时为了进一步明确源代码而这样做。

Additionally such Exceptions are sometimes mentioned in JavaDoc (e.g. BigInteger#divide)

另外,JavaDoc中有时会提到这样的异常(例如BigInteger#divide)

But the compiler checks the throws clause when overriding methods. It's somewhat similar to the visibility rules when overriding methods. This means throwing unchecked Exceptions (and declaring corresponding throws clauses) can always be done. Following declaration is valid:

但是当重写方法时,编译器会检查throws子句。在覆盖方法时,它与可见性规则有些相似。这意味着可以始终执行抛出未经检查的异常(并声明相应的throws子句)。以下声明有效:

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

It's the same the other way round. Unchecked exceptions in throws clauses are disregarded by the compiler, because they aren't relevant to compile-time checking:

反过来也是如此。 throws子句中未经检查的异常会被编译器忽略,因为它们与编译时检查无关:

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

The general rule for throws-clause inheritance is: One interface to rule them all: The interface must declare all checked exceptions that can be thrown by implementing classes. Or in other words:

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

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

实现类可以在实现方法的throws-clause中的接口方法的throws-clause中声明声明的已检查异常的子集

This means following is valid:

这意味着以下有效:

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

What's not valid is declaring a checked exception in the implementing method's throws-clause that's not declared in the corresponding interface method's clause:

什么是无效的是在实现方法的throws-clause中声明一个未在相应的接口方法子句中声明的已检查异常:

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

#1


There are two types of Exceptions: checked Exceptions (like ParseExceptionwhen parsing text) and unchecked Exceptions (like NullPointerException).

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

Checked Exceptions must be declared in the method signature. Unchecked Exceptions may be declared in the method signature.

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

When overriding methods (from an interface or a super class) you only have to specify the exceptions, that you are throwing in your implementation. You cannot declare to throw checked exceptions in an implementation that are not allowed in the overridden method.

当重写方法(来自接口或超类)时,您只需指定实例中的异常。您不能声明在重写方法中不允许的实现中抛出已检查的异常。

This is allowed:

这是允许的:

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

This is not allowed:

这是不允许的:

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

This is also allowed:

这也是允许的:

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

#2


What slartidan said in their answer is fully correct. To explain a little more:

slartidan在回答中说的是完全正确的。再解释一下:

If you are throwing a "Checked Exception" inside the body of a method, you are required to either handle it (using a catch-block) or to declare a throws-clause

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

To reiterate the previously linked JLS:

重申先前链接的JLS:

  1. An Exception is a class extending Throwable
  2. Exception是一个扩展Throwable的类

  3. An Error also is a class extending Throwable
    • Errors usually should not be caught, because they indicate serious problems. (e.g. OutOfMemoryError)
    • 通常不应该发现错误,因为它们表明存在严重问题。 (例如OutOfMemoryError)

    • catching Exception does not catch Errors
    • 捕获异常不会捕获错误

  4. 错误也是一个扩展Throwable错误的类通常不应该被捕获,因为它们表明存在严重问题。 (例如OutOfMemoryError)捕获异常不会捕获错误

  5. There also is RuntimeException. This is a class extending Exception
  6. 还有RuntimeException。这是一个扩展Exception的类

Errors and Runtime Exceptions are not checked at compile time, because that exactly is what "checked exception" means.

在编译时不会检查错误和运行时异常,因为这正是“已检查异常”的含义。

You may throw Errors and RuntimeExceptions anywhere in your code.

您可以在代码中的任何位置抛出Errors和RuntimeExceptions。

Now how does this affect throws clauses:

现在,这如何影响throws子句:

A throws clause specifies that an invocation of the declared method may result in the exception specified. Interestingly throws expects a Throwable, which makes following declaration valid:

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

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

There is no compiler effect when declaring non-checked Exceptions in a throws clause, but it's sometimes done for additional clarity in your sourcecode.

在throws子句中声明未检查的异常时没有编译器效果,但有时为了进一步明确源代码而这样做。

Additionally such Exceptions are sometimes mentioned in JavaDoc (e.g. BigInteger#divide)

另外,JavaDoc中有时会提到这样的异常(例如BigInteger#divide)

But the compiler checks the throws clause when overriding methods. It's somewhat similar to the visibility rules when overriding methods. This means throwing unchecked Exceptions (and declaring corresponding throws clauses) can always be done. Following declaration is valid:

但是当重写方法时,编译器会检查throws子句。在覆盖方法时,它与可见性规则有些相似。这意味着可以始终执行抛出未经检查的异常(并声明相应的throws子句)。以下声明有效:

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

It's the same the other way round. Unchecked exceptions in throws clauses are disregarded by the compiler, because they aren't relevant to compile-time checking:

反过来也是如此。 throws子句中未经检查的异常会被编译器忽略,因为它们与编译时检查无关:

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

The general rule for throws-clause inheritance is: One interface to rule them all: The interface must declare all checked exceptions that can be thrown by implementing classes. Or in other words:

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

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

实现类可以在实现方法的throws-clause中的接口方法的throws-clause中声明声明的已检查异常的子集

This means following is valid:

这意味着以下有效:

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

What's not valid is declaring a checked exception in the implementing method's throws-clause that's not declared in the corresponding interface method's clause:

什么是无效的是在实现方法的throws-clause中声明一个未在相应的接口方法子句中声明的已检查异常:

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