程序在catch块结束之前继续

问题描述 投票:2回答:2

我很难理解这一点;

public static void main(String[] args){
    int nulberOfTests = 10;
    for( int i=0 ; i < numberOfTest ; i++){
        try{
            File file = getRandomFile(directory);
            foo(file);
        }catch(IOException){
            System.out.println("Failed to split the file: " + file.getName());
        }
    }
}

foo(File file) throws IOException{
    System.out.println("Starting foo with " +file.getName());
    List<String> blockFiles = split(file);  //this throws IOException.
    for(int i =0 ; i< blockFiles.size(); i++){
        try{
            bar(blockFiles.get(i)); //this throws some exceptions
        }catch (Exception e){
            System.err.println("Failed bar on " + blockFiles.get(i));
            e.printStackTrace();
            //Handle the exception
        }finally{
            //clean up
        }
    }
//continue with the function
}

在我看来是这样的:我发起了一个foo;它试图删除文件;如果它失败,它会抛出IOException,我只是写它并继续使用另一个foo(文件)(与另一个文件)。这是按预期工作的。

如果它工作,那么我有一个blockFiles名称列表,我进入另一个循环,在每个blockFiles上运行bar。如果一个栏失败,那么我处理异常,清理这些东西,然后用下一个块文件继续循环。

但是,会发生什么:它开始处理异常,同时用另一个文件启动另一个foo。我可以有这样的输出:

Starting foo with file7
Failed bar on file7.block3
Starting foo with file12
Java.lang.NullPointerException
....

所以printStackTrace会在下一个foo开始之后发生。我不明白这一点。它应该继续使用bar函数的循环和foo的其余部分,然后再返回主循环并启动另一个foo。

有人能解释我这种奇怪的行为吗?也许告诉我要改变什么,以便捕获中的所有内容在另一个foo开始之前运行?

PS:我知道这不是“最小的完整和可验证的”,但是这里有太多的东西使它完整和可验证,而且它本来真的很难理解。我希望这里的内容足够了。

java try-catch
2个回答
2
投票

您的问题很难理解,代码显然不是真实的,但我认为您在询问为什么消息以意外的顺序显示。

一个可能的答案是:

System.out.println("Failed to split the file: " + file.getName());
System.out.println("Starting foo with " +file.getName());
System.err.println("Failed bar on " + blockFiles.get(i));
e.printStackTrace();

您是否注意到其中一些打印到System.out,其他打印到System.err

这是两个不同的流。即使它们被重定向到相同的位置,在Java中,两个流也分别缓冲并具有不同的“自动刷新”特性。这意味着输出可能以意想不到的方式散布。例如:

public static void (String[] args) {
     System.out.println("Hi");
     System.err.println("Mom");
}

可能输出:

Hi
Mom

要么

Mom
Hi

如果您需要按照代码编写的顺序显示错误消息或堆栈跟踪,只需使用一个流来处理消息。


0
投票

接受的答案是不正确的或至少是模棱两可的。

如果用System.out替换System.err,则两个println的顺序将相同:错误,然后是新文件的开头。

什么是乱序是堆栈跟踪。

原因是一样的。 java.lang.Throwable.printStackTrace()方法在System.err上写入。

如果需要预期的订单,请在同一个流中打印堆栈跟踪和消息。

要在System.out上打印堆栈跟踪,请使用:

e.printStackTrace(System.out);

java.lang.Throwable.printStackTrace()

© www.soinside.com 2019 - 2024. All rights reserved.