Программа продолжается до окончания блока catch - PullRequest
0 голосов
/ 08 сентября 2018

У меня проблемы с пониманием;

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. Если строка не работает, я обрабатываю исключение, очищаю вещи и продолжаю цикл со следующим блок-файлом.

Однако происходит следующее: он начинает обрабатывать исключение и одновременно запускает другой файл с другим файлом. Я могу иметь такой вывод:

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

Таким образом, printStackTrace происходит ПОСЛЕ следующего запуска foo. И я этого не понимаю. Он должен просто продолжить цикл функций бара и остальную часть foo, прежде чем вернуться к основному циклу и запустить другой foo.

Может кто-нибудь объяснить мне это странное поведение? А может, подскажете, что изменить, чтобы все в подвохе запустилось до начала следующего foo?

PS: я знаю, что это не «Минимально завершенный и проверяемый», но в нем слишком много всего, чтобы сделать его полным и проверяемым, и это было бы действительно труднее понять. Я надеюсь, что здесь будет достаточно.

Ответы [ 2 ]

0 голосов
/ 08 сентября 2018

Принятый ответ неверен или хотя бы неоднозначен.

Если вы замените System.err на System.out, порядок двух println будет одинаковым: ошибка, а затем начало нового файла.

Что не в порядке, так это трассировка стека.

Причина та же. Метод java.lang.Throwable.printStackTrace () записывает в System.err.

Если вы хотите получить ожидаемый порядок, распечатайте трассировку стека и сообщения в одном потоке.

Чтобы напечатать трассировку стека в System.out, используйте:

e.printStackTrace(System.out);

java.lang.Throwable.printStackTrace ()

0 голосов
/ 08 сентября 2018

Ваш вопрос очень сложен для понимания, и код явно не реален, но я думаю, что вы спрашиваете, почему сообщения отображаются в неожиданном порядке.

Один из возможных ответов таков:

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

Если вам нужно, чтобы ваши сообщения об ошибках или трассировки стека появлялись в том порядке, в котором их пишет код, просто используйте ОДИН поток для сообщений.

...