调用函数时为什么需要“抛出异常”?

时间:2012-07-21 03:52:28

标签: java exception-handling unhandled-exception throws checked-exceptions

class throwseg1
{
    void show() throws Exception
    {
        throw new Exception("my.own.Exception");
    }

    void show2() throws Exception  // Why throws is necessary here ?
    {
        show();
    }

    void show3() throws Exception  // Why throws is necessary here ?
    {
        show2();
    }

    public static void main(String s[]) throws Exception  // Why throws is necessary here ?
    {
        throwseg1 o1 = new throwseg1();
        o1.show3();
    }
}

为什么编译器会报告方法show2()show3()main()

  

未报告的异常必须捕获​​或声明抛出的异常

当我从这些方法中删除throws Exception时?

8 个答案:

答案 0 :(得分:127)

在Java中,您可能知道,异常可以分为两类:一个需要throws子句,或者如果您没有指定一个而必须处理,另一个则不需要。现在,请看下图:

enter image description here

在Java中,您可以抛出任何扩展Throwable类的内容。但是,您不需要为所有类指定throws子句。具体而言,是ErrorRuntimeException的类或这两者的任何子类。在您的情况下,Exception不是ErrorRuntimeException的子类。因此,它是一个经过检查的异常,必须在throws子句中指定,如果您不处理该特定异常。这就是你需要throws子句的原因。


来自Java Tutorial

  

异常是在程序执行期间发生的事件,它会破坏程序指令的正常流程。

现在,如您所知,异常分为两类:已选中和未选中。为什么这些分类?

Checked Exception:它们用于表示在程序执行期间可以恢复的问题。他们通常不是程序员的错。例如,用户指定的文件不可读,或者没有可用的网络连接等。在所有这些情况下,我们的程序不需要退出,而是可以采取警告用户或进入后备的操作机制(如网络不可用时离线工作)等。

未选中的例外:它们又可以分为两个:错误和RuntimeExceptions。它们不受限制的一个原因是它们数量众多,要求处理所有这些都会使我们的程序混乱并降低其清晰度。另一个原因是:

  • 运行时异常:它们通常是由于程序员的错误而发生的。例如,如果出现ArithmeticException除以零或发生ArrayIndexOutOfBoundsException,那是因为我们在编码时不够谨慎。它们通常是因为我们的程序逻辑中存在一些错误。因此,必须在我们的程序进入生产模式之前清除它们。它们是未经检查的,因为我们的程序在发生时必须失败,以便我们程序员可以在开发和测试时自行解决它。

  • 错误:错误通常是程序无法恢复的情况。例如,如果发生StackOverflowError,我们的程序就不会做太多事情,例如增加程序函数调用堆栈的大小。或者如果发生OutOfMemoryError,我们无法增加可用于我们程序的RAM量。在这种情况下,最好退出程序。这就是他们被取消选中的原因。

有关详细信息,请参阅:

答案 1 :(得分:23)

Java要求您处理或声明所有异常。如果您没有使用try / catch块处理异常,则必须在方法的签名中声明它。

例如:

class throwseg1 {
    void show() throws Exception {
        throw new Exception();
    }
}

应写成:

class throwseg1 {
    void show() {
        try {
            throw new Exception();
        } catch(Exception e) {
            // code to handle the exception
        }
    }
}

这样你就可以摆脱方法声明中的“throws Exception”声明。

答案 2 :(得分:3)

Exception是一个已检查的异常类。因此,任何调用声明它throws Exception的方法必须处理或声明它的代码。

答案 3 :(得分:3)

throws Exception声明是一种自动跟踪可能因预期但不可避免的原因而抛出异常的方法的方法。声明通常特定于可能抛出的异常类型,例如throws IOExceptionthrows IOException, MyException

我们都已经或者最终会编写意外停止的代码并报告由于我们在运行程序之前没有预料到的异常,例如除零或索引越界。由于该方法不期望错误,因此无法使用try catch子句“捕获”它们。任何毫无防备的方法用户也不会知道这种可能性,他们的程序也会停止。

当程序员知道可能发生某些类型的错误但希望在方法之外处理这些异常时,该方法可以将一种或多种类型的异常“抛出”到调用方法而不是处理它们。如果程序员没有声明方法(可能)抛出异常(或者如果Java没有能力声明它),编译器就无法知道,并且将由该方法的未来用户知道,捕获并处理方法可能抛出的任何异常。由于程序可以有许多不同程序编写的多层方法,因此很难(不可能)跟踪哪些方法可能会抛出异常。

尽管Java具有声明异常的能力,但您仍然可以使用未处理和未声明的异常编写新方法,Java将对其进行编译,您可以运行它并希望获得最佳效果。 Java不允许你做的是编译你的新方法,如果它使用一个被声明为抛出异常的方法,除非你在方法中处理声明的异常或声明你的方法抛出它例外或如果有多个例外,你可以处理一些并抛出其余部分。

当程序员声明该方法抛出特定类型的异常时,它只是一种警告其他程序员使用该方法的自动方式,即异常是可能的。然后程序员可以决定处理异常或通过声明调用方法也引发相同的异常来传递警告。由于编译器已在此新方法中被警告异常,因此它可以自动检查新方法的未来调用者是否处理异常或声明异常,并强制执行其中一个或另一个。

这种解决方案的优点在于,当编译器报告Error: Unhandled exception type java.io.IOException时,它会提供声明抛出异常的方法的文件和行号。然后,您可以选择简单地传递降压并声明您的方法也“抛出IOException”。这可以一直到主方法,然后它将导致程序停止并向用户报告异常。但是,最好捕获异常并以一种很好的方式处理它,例如向用户解释发生了什么以及如何解决它。当方法捕获并处理异常时,它不再需要声明异常。可以说,降压停在那里。

答案 4 :(得分:0)

package javaexception;


public class JavaException {
   void show() throws Exception
    {
        throw new Exception("my.own.Exception");
    }

void show2() throws Exception  // Why throws is necessary here ?
{
    show();
}

void show3() throws Exception  // Why throws is necessary here ?
{
    show2();
}
public static void main(String[] args) {

   JavaException a = new JavaException();

   try{
   a.show3();
   }catch(Exception e){
       System.out.println(e.getMessage());
   }
}

程序中只有很小的变化。许多关于主要问题似乎被误解的是,每当你抛出异常时你需要处理它,在同一个地方没有必要(例如程序中的show1,2,3方法),但你必须首先调用方法在' main'内。总而言之,就是“扔掉”,必须有“捕捉/尝试”,即使是异常发生的方法也不一样。

答案 5 :(得分:0)

void show() throws Exception
{
    throw new Exception("my.own.Exception");
}

由于在show()方法中检查了异常,但在该方法中没有处理,因此我们使用throws关键字来传播异常。

void show2() throws Exception //Why throws is necessary here ?
{
show();
}

由于您在show2()方法中使用了show()方法,并且至少传播了异常,因此您应该在此处理。如果您没有在此处理异常,那么您正在使用throws关键字。 这就是在方法签名处使用throws关键字的原因。

答案 6 :(得分:0)

如果通过在当前方法的签名中声明throws指令来传播异常,则必须在行或调用堆栈的某个位置使用try / catch构造来处理异常。

答案 7 :(得分:-1)

基本上,如果未在引发异常的地方处理异常,则可以在函数定义中使用“引发异常”。