调试错误:异常永远不会在相应的try语句的主体中抛出

时间:2016-11-06 02:03:18

标签: java

我有一个类似的调试任务,我似乎无法弄清楚。我们被告知要调试赋值,以便赋值的输出看起来像这样。

输出:

There is a problem with the Eagle!
Java Result: 9999

给出的代码如下:

//Superclass for the custom exception.
public class EagleLandingException extends Exception
{
    public EagleLandingException(String msg)
    {
      super(msg);
    }
}

和主要课程

public class ThrowEagleExceptionTest {

public static void main(String[] args) {
    try {
        EagleLanding();
    }
     catch (EagleLandingException badEagle) {
        System.out.printf("%s\n", badEagle.getMessage());
        System.exit(9999);
    }
}
private static void EagleLanding () {
    EagleLandingException("There is a problem with the Eagle!");
    System.exit(9999);
}

我在第

行收到“永远不会抛出异常”的错误
catch (EagleLandingException badEagle)

并在行

上收到“无法找到符号”错误
EagleLandingException("There is a problem with the Eagle!");

我不明白为什么会这样,并且已经查看了已发布的其他问题,但似乎无法弄清问题是什么。先感谢您。

4 个答案:

答案 0 :(得分:2)

问题出在这里。

private static void EagleLanding () {
    EagleLandingException("There is a problem with the Eagle!");
    System.exit(9999);
}

EagleLandingException(...)被解释为对名为EagleLandingException的方法的调用。但这不是一种方法。它是一个构造函数,其名称(类名)不在Java查找方法名称的名称空间中。编译错误(实际上)说“我找不到方法调用...”。

另一个问题是您的EagleLanding方法未被声明为抛出异常。因此,当您尝试在调用者中捕获异常时,编译器会说“这是一个已检查的异常,并且由于异常未声明为抛出,因此无法在此处进行”。因此编译错误。

写这个的正确方法是:

private static void eagleLanding () throws EagleLandingException {
    throw new EagleLandingException("There is a problem with the Eagle!");
}

注意:

  1. new导致创建异常对象
  2. throw会导致抛出异常。
  3. throws子句声明该方法抛出已检查的异常。
  4. throw无法访问后的语句。如果不删除它们,则会出现编译错误。 (并且,除了在类似的方法中调用exit之外,这是一个坏主意......)
  5. 我更改了方法名称以符合Java样式规则。方法应以小写名称开头。
  6. 在他的回答中,@ javaguy建议EagleLandingException不应该被取消;即声明为RuntimeException的子类型。

    这是对的吗?可能是,可能不是。在你给我们的(高度人为的)背景中,不可能确切地知道。

    但是,Java设计人员建议开发人员应遵循一些一般性指导原则:

    • 已检查的例外情况适用于可能针对例外做出某些事情的预期事件。

    • 未经检查的异常适用于意外事件(例如错误),其中(通常)程序员可能做的事情不多。

    人们在决定是否使用已检查或未检查的异常时使用的另一个标准是最小化样板代码的数量;即throws条款。很多人发现它们很烦人,并会花很多时间来避免它们;例如通过将所有自定义异常声明为未选中,在自定义异常中包装标准异常,等等。

    我认为最佳途径介于两者之间。仔细考虑将每个异常声明为已选中或未选中的含义,并使用异常层次结构来管理throws声明的大小。

答案 1 :(得分:1)

问题是你永远不会抛出异常,你甚至不创建它。行EagleLandingException("There is a problem with the Eagle!");不执行任何操作,但会导致错误。您需要使用throw关键字,如下所示:

private static void EagleLanding () throws EagleLandingException {
    throw new EagleLandingException("There is a problem with the Eagle!");
}

您也可以省略System.exit(9999);,因为它永远不会到达,因为异常会中断您的程序流并直接返回catch分支。方法声明中的throws声明表示您未在方法EagleLanding中处理异常。

答案 2 :(得分:0)

更改

EagleLandingException("There is a problem with the Eagle!");

throw new EagleLandingException("There is a problem with the Eagle!");

此外,由于EagleLandingException是经过检查的,因此您需要将其添加到 EagleLanding()方法签名。

private static void EagleLanding () throws EagleLandingException {

说明:

您需要在抛出异常之前创建异常实例。在java中,这是通过 new 运算符完成的。

EagleLanding中的最后一行永远不会执行,因为在它之前抛出异常会导致方法提前退出。然后控件进入你的catch块。

答案 3 :(得分:0)

问题在于此行EagleLandingException("There is a problem with the Eagle!");在语法上是不正确的,因此需要更改如下:

private static void EagleLanding () throws EagleLandingException{
    //the below statement creates a new EagleLandingException and then hrowing it
    new throw EagleLandingException("There is a problem with the Eagle!");
}

Checked Exception的主要规则是方法必须处理异常(使用catch块),或者必须使用throws关键字在方法签名中声明它。

此外,throw语句之后的任何语句都不会被执行(finally阻止try阻止(如果有的话),因此我删除了System.exit

你需要注意的重点是你实际上是在创建/抛出一个检查过的异常,一般来说,不是首选的,也不是必需的(除非你在抛出/接收异常时有一些恢复策略),所以我更好建议是使用RuntimeException转换代码,如下所示:

//Extend with RuntimeException instead of Exception
public class EagleLandingException extends RuntimeException
{
    public EagleLandingException(String msg)
    {
      super(msg);
    }
}

    public class ThrowEagleExceptionTest {

public static void main(String[] args) {
    try {
        EagleLanding();
    }
     catch (EagleLandingException badEagle) {
        System.out.printf("%s\n", badEagle.getMessage());
        System.exit(9999);
    }
}

  //now you don't need to declare the EagleLandingException
  private static void EagleLanding () {
      throw new EagleLandingException("There is a problem with the Eagle!");
 }