我很难理解这一点;
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:我知道这不是“最小的完整和可验证的”,但是这里有太多的东西使它完整和可验证,而且它本来真的很难理解。我希望这里的内容足够了。
您的问题很难理解,代码显然不是真实的,但我认为您在询问为什么消息以意外的顺序显示。
一个可能的答案是:
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
如果您需要按照代码编写的顺序显示错误消息或堆栈跟踪,只需使用一个流来处理消息。
接受的答案是不正确的或至少是模棱两可的。
如果用System.out替换System.err,则两个println的顺序将相同:错误,然后是新文件的开头。
什么是乱序是堆栈跟踪。
原因是一样的。 java.lang.Throwable.printStackTrace()方法在System.err上写入。
如果需要预期的订单,请在同一个流中打印堆栈跟踪和消息。
要在System.out上打印堆栈跟踪,请使用:
e.printStackTrace(System.out);