在Java中,如何强制异常“冒泡”?

时间:2014-06-12 22:02:59

标签: java exception

我有一个抛出异常的方法,它调用抛出异常的方法等等。所以“抛出异常”的几个方法是菊花链式的。 调用子方法的第一个方法是将该子方法放在try-catch块中,该块捕获在该调用中抛出的任何Exception。理论上。实际上,try-catch块没有捕获到Exception。有没有办法解决这个问题?

以下是代码:

          try {
                CSVSingleton.tryToReadBothFiles(FILE1_PATH, FILE2_PATH);

                } catch (Exception e) { // THIS BLOCK NEVER GETS ENTERED BY THE PATH O EXECUTION
System.out.println("There was an exception reading from at least one of the files. Exiting.");
                    System.exit(0);
                }

这是CSVSingleton类的方法:

public static void tryToReadBothFiles(String filePath1, String filePath2) throws Exception {

        file1 = new CSVFileForDwellTime1(filePath1);
        file2 = new CSVFileForDwellTime2(filePath2);
    }

这是来自CSVFileForDwellTime1类的代码:

public CSVFileForDwellTime1(String filePath) throws Exception {
        super(filePath);
    }

然后这是实际抛出原始FileNotFoundException的代码:

public GenericCSVFile(String filePath) throws Exception{
        this.filePath = filePath;
        try {
            fileReader = new FileReader(filePath);
            csvReader = new CSVReader(
                    fileReader);
            header = getActualHeaderNames();
        } catch (FileNotFoundException e) {
            System.out.println("Could not read file with name: " + filePath);
            // e.printStackTrace();
        }
    }

我的猜测是,最后一个方法中的FileNotFoundException被catch块捕获,因此不会“冒泡”。但有没有办法迫使它冒泡?

5 个答案:

答案 0 :(得分:14)

立即回答:

你的想法是完全正确的,

    try {
        fileReader = new FileReader(filePath);
        csvReader = new CSVReader(
                fileReader);
        header = getActualHeaderNames();
    } catch (FileNotFoundException e) {
        System.out.println("Could not read file with name: " + filePath);
        // e.printStackTrace();
    }

这可以抑制异常 删除try-catch块(除非您可以对异常执行某些操作,否则需要删除)或将其重新抛出catch块。

<强> 解释

一般情况下,checked这样的例外有2个选项

  1. 抓住异常并采取措施纠正异常
  2. 将异常抛给调用者
  3. 你在这里所做的事情属于第一类,只是你没有在catch块中做过任何有用的事情(在这种情况下打印到控制台很少有用,因为异常消息本身通常有足够的信息可供查看出了什么问题)

    第二类是通过不使用try-catch块并因此将throws FileNotFoundException添加到方法签名来实现的。或者明确地throw使用以下命令捕获的异常:

    catch(FileNotFoundException e)
    {
        //do something
        throw e;
    }
    

    然而,在这种情况下,如果do something不值得,你就会不必要地抓住一些东西,只是为了把它扔掉。

    你可以这样想:

    Alice throws a ball to Charlie
    Bob intercepts the ball
    Bob then looks at the ball and then throws it to Charlie
    

    奖励积分

    当您知道可能发生的异常时,请确保实际catchthrow该异常,而不是该异常的父级。 例如,采用以下方法签名:

    public String method1() throws Exception
    
    public String method2() throws FileNotFoundException
    

    这里method2清楚地告诉调用者会发生什么,然后可以帮助找出调用异常的原因(无需读取代码或遇到错误)。

    其次可能发生其他异常并且您可能正在捕获错误的异常,请采用以下示例:

    try{
        fileReader = new FileReader(filePath); //could potentially throw FileNotFoundException
        fileReader = null; //woops
        csvReader = new CSVReader(fileReader); //throws NullPointerException but the compiler will not know this 
        //....other stuff....//
    }
    catch(Exception e){
        // the compiler told me that a FileNotFoundException can occur so i assume that is the reason the catch has executed
        System.err.println("You have entered an invalid filename");
        //doing anything here that would fix a FileNotFoundException is pointless because that is not the exception that occured
    }
    

答案 1 :(得分:4)

在catch子句中使用throw

} catch (FileNotFoundException e) {
    System.out.println("Could not read file with name: " + filePath);
    // Continue up, Mr. Exception!
    throw e;
}

或者,根据需要包装异常(因为这里检查了IOException) - 这称为Chained Exception。然后,根据抛出的内容,可以从方法签名中删除throws Exception

throw new RuntimeException("Could not read file: " + filePath, e);

答案 2 :(得分:3)

如果你不想抓住它,那就不要了。或者,您可以使用throw语句再次抛出它。你也可以抛出你喜欢的任何类的新例外。您应该只在可以对其做出正确反应的级别捕获异常。正如你所发现的那样,在低水平下捕捉它是没有用的,所以不要抓住它。

答案 3 :(得分:1)

一旦捕获到异常,就可以重新抛出异常,以便让进一步向上的callees处理。如果新类型的异常在更高级别更有意义,您也可以更改它的异常。

catch (SomeSpecificException e)
{
    some code here
    throw new AMoreBroadException("I really need the callee to handle this too");
}

答案 4 :(得分:0)

从技术上讲,您只需在throw e之后添加System.out.println("Could not read file with name: " + filePath);,异常就会传播到第一种方法。

但是,这不是一种处理异常的简洁方法,因为在这种情况下,您所做的只是以更改原始FileNotFoundException的位置为代价打印错误消息。理想情况下,当您需要检查异常堆栈跟踪时,您希望抛出异常的代码行成为真正导致异常的实际行。

方法声明中的throws Exception应被视为方法合同的一部分,即它描述方法的可能行为。你应该总是问自己:将FileNotFoundException指定为我正在编写的方法/构造函数的可能异常行为是否有意义?换句话说,我是否希望让我的方法的调用者知道此异常并将其留给调用者来处理它?如果答案是肯定的(在这种情况下我会说它有意义),那么避免将代码包装在try-catch块中。如果不是,那么您的catch块应该负责处理异常本身。在此特定示例中,您可以在catch语句中执行多少操作,因此只需删除try-catch

正如其他人所说,您应该在方法签名(throws FileNotFoundException而不是throws Exception)中声明 最具体的 例外。