Различные стили потока программы?

Я студент-информатика, поэтому я не так много знаю.

Недавно я разговаривал с другом, который только что получил работу в качестве разработчика программного обеспечения (java). Он сказал мне, что на его работе есть парень, который действительно опытен на С++, но, к сожалению, каждый раз, когда он пишет код в java, он использует try-catch для управления потоком программы. По словам моего друга, это неправильный стиль в Java. Это правда? Каковы различия (если они есть) при использовании try-catch (-finally в java) между С++ и Java?

Ответ 1

Использование try-catch для управления потоком программы не так где угодно... Обработка исключений - это то, что она говорит: Обработка исключительных обстоятельств.

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

Использование исключений для управления потоком программы происходит, если вы ожидаете, что определенные исключения будут выбрасываться в нормальной операционной среде, и вы принимаете логические решения на основе этих исключений.

Например, управление потоком программы в псевдокоде:

try {
  write update to file
} catch (IOException) {
  write update to alternate file
}

В этом случае было бы лучше фактически протестировать существование пути до слепого выполнения записи.

Я удалил заметки проверки разрешений, потому что это плохой пример

Хорошее использование обработки исключений: (псевдокод снова)

try {
  do stuff
} catch(OutOfMemoryException) {
  fail gracefully (don't try and do something else to achieve the same result)
}

Ответ 2

Я бы сказал, что с точки зрения программной архитектуры цель исключений одинакова в Java и С++. Они должны использоваться для обработки исключительных случаев, а не для прямого нормального потока программы.

Наиболее распространенным аргументом против использования исключений является то, что они медленны. Как и большинство аргументов, основанных на скорости кода, он почти всегда неактуальен в настоящее время, особенно если исключения используются правильно.

Ответ 3

Я думаю, что он говорит, что он использует исключения для не исключительных условий, таких как нормальные концы цикла. Это считается не-нет программистами на большинстве языков, которые предоставляют исключения, включая С++.

Причиной этого является то, что исключения, как правило, перетаскивают справедливую информацию вместе с ними. На некоторых платформах они вызывают весь столбец в точке исключения, чтобы отображать его в хорошем отладочном сообщении. Это очень дорого, если все, что вам действительно нужно, - безусловный контроль.

Вместо этого вы должны использовать такие выражения, как break, return или даже (в реальном сжатии) goto.

Ответ 4

Я бы ожидал, что миры С++ и Java будут в значительной степени похожи в своих представлениях:

  • Контроль потока с помощью блоков try/catch не сразу очевиден.
  • это дорогостоящее исполнение. На практике это может не быть проблемой, но во многих сценариях (например, жестких циклах) это, безусловно, повлияет на вас.

Ответ 5

Единственной целью try/catch является управление потоком. Он предназначен для того, чтобы позволить нам выйти из любого цикла и даже пройти мимо вызывающего абонента и до функции более высокого уровня.

Однако он предназначен для исключительных условий, таких как использование нулевых ссылок, переполнение подразделения или отказ ввода-вывода файла. Это ошибки, которые не позволяют программе продолжать работу и должны быть обработаны. Как правило, их трудно предсказать или очень редки.

Когда возникает исключительное условие, самое лучшее, что нужно сделать, это изменить поток управления, чтобы исключение было выброшено так далеко, как должно быть, чтобы найти блок catch, готовый обработать его. Любой метод между ними прерывается и разматывается, даже если у него нет кода для проверки результатов.

Когда люди жалуются на использование try/catch для управления потоком, что они должны означать, это то, что он не для управления потоком в не исключительных условиях. Если все, что вы хотите сделать, это выйти из цикла, используйте break или return; не бросайте исключение, а затем ловите его. Это не то, для чего нужны исключения, и не то, для чего они хороши.

Ответ 6

Блок try-catch предназначен для того, чтобы делать то же самое на всех языках - исключения - один из многих способов восстановления, когда что-то идет не так. В java следующие два утверждения идентичны:

if(x != null){
  //do the normal thing
}
else{
  //recover from the error
}

и

try{
  //do the normal thing
}
catch(NullPointerException ex){
  //recover
}

Однако использование исключений никогда не бывает хорошей идеей по ряду причин:

  • стоимость, связанная с выбросом исключения (т.е. генерирование Throwable в Java)
  • поток управления не сразу становится очевидным - например, если исключение NullPointerException может быть выбрано несколькими операторами в блоке try, как вы можете определить, какой из них его бросил в блок catch.
  • и т.д.

Ответ 7

То, что он может хотеть, - это несколько способов не выполнять бит кода... так, а не (в java)

if (cond1) {
  some_code();
  if (cond2) {
    some_more_code();
    if (condN) {
      ad_infinitum
    }
  }
}

Это может быть "сплющено", выбросив немного мусора...

try {
  if (!cond1) throw new Throwable();
  some_code();
  if (!cond2) throw new Throwable();
  some_more_code();
  if (!condN) throw new Throwable();
  ad_infinitum();
} catch (Throwable ignore) { }

Проблема в том, что если какое-то реальное исключение было брошено? Я думаю, что ваш коллега должен написать, если он хочет сгладить углубление, это примерно так:

do {
  if (!cond1) break;
  some_code();
  if (!cond2) break;
  some_more_code();
  if (!condN) break;
  ad_infinitum();
} while (false);

Так как do/while всегда выполняется, мы можем использовать break для аппроксимации goto (пока все идет в одно и то же место).

Ответ 8

Ваш вопрос слишком расплывчатый без примера кода. В С++ нет finally.

EDIT В общем, вы не хотите использовать exceptions как средство управления потоком. exceptions предполагается использовать только для исключительных (непредвиденных ситуаций) случаев.