Почему люди Java часто потребляют исключения молча?

Раньше я никогда не делал серьезных Java-кодировок, но я изучил синтаксис, библиотеки и концепции на основе моих существующих навыков (Delphi & C #). Единственное, что я почти не понимаю, это то, что я видел столько кода, который молча потребляет исключения после printStackTrace следующим образом:

  public void process() { try { System.out.println("test"); } catch(Exception e) { e.printStackTrace(); } } 

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

  public void process() { try { System.out.println("test"); } catch(Exception e) { e.printStackTrace(); throw new AssertionError(e); } } 

В большинстве случаев исключение должно обрабатываться в самом внешнем цикле, который относится к базовой структуре (например, Java Swing). Почему он похож на норму для кода, подобного этому в мире Java? Я озадачен.

Основываясь на моем предположении, я бы предпочел полностью удалить printStackTrace. Я бы просто бросил как необработанное RuntimeException (или, что еще лучше, AssertionError ), а затем поймать и RuntimeException в самое подходящее место: крайний внешний контур.

  public void process() { try { System.out.println("test"); } catch(Exception e) { throw new AssertionError(e); } } 

Я всегда думал, что это похоже на следующий сценарий:

«Человек выстрелил.

Он затаил дыхание и имеет достаточную силу, чтобы сесть на автобус.

Спустя 10 миль человек выходит из автобуса, проходит пару блоков и умирает ».

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

Лучше:

«Человек получает выстрел, и он умирает мгновенно, и тело лежит именно там, где только что произошло убийство».

Когда полиция прибывает, все доказательства имеются.

Если система терпит неудачу, лучше будет быстро

Обращаясь к вопросу:

  1. Невежество.
      +
  2. леность

РЕДАКТИРОВАТЬ:

Конечно, секция улова полезна.

Если что-то можно сделать с исключением, вот где это должно быть сделано.

Вероятно, это НЕ исключение для данного кода, возможно, это то, что ожидается (и по моей аналогии похоже пуленепробиваемая куртка, и мужчина ждал выстрела на первое место).

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

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

Это плохая форма, без сомнения.

  1. Java заставляет вас обрабатывать все Исключения явно. Если метод, вызываемый вашими кодами, генерирует исключение FooException и BarException, ваш код ДОЛЖЕН обрабатывать (или бросать) эти исключения. Единственным исключением из этого является RuntimeException , которое является тихим, как ниндзя.
  2. Многие программисты ленивы (включая меня), и очень просто просто распечатать трассировку стека.

Это classический соломенный аргумент . printStackTrace() – это отладочная помощь. Если вы видели его в блоге или в журнале, это объяснялось тем, что писатель больше интересовался иллюстрацией точки, отличной от обработки исключений. Если вы видели это в производственном коде, разработчик этого кода был невежественным или ленивым, не более того. Это не следует воспринимать как пример обычной практики в «java world».

Я нахожу, что это часто бывает 2 причины

  1. Программист был ленив
  2. Программист хотел охранять точку входа в компонент (правильно или неправильно)

Я не считаю, что это явление ограничено Java. Я часто видел такое кодирование в C # и VB.Net.

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

 Foo* pFoo = ...; pFoo->SomeMethod(); // Void or swallowing errors, who knows? 

Этот код выглядит лучше, но если SomeMethod () должен был возвращать HResult, он был бы семантически ничем не отличающимся от проглатывания исключения.

потому что Checked Exceptions – неудачный эксперимент

(возможно, printStackTrace () – настоящая проблема ? 🙂

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

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

У меня есть проблема, я полагаю, заключается в том, что вы ветерок через кучу статей и fragmentов кода в Интернете, не утруждая себя рассмотрением контекста. По правде говоря, когда вы пишете техническую статью, пытающуюся объяснить, как работает какой-то конкретный API, или как начать с чего-то, тогда вы, скорее всего, пропустите некоторые аспекты кода – обработка ошибок, которая не напрямую связанный с тем, что вы демонстрируете, является вероятным кандидатом на удаление, особенно если исключение вряд ли произойдет в сценарии примера.

Люди, которые пишут статьи такого характера, должны поддерживать разумное соотношение сигнал / шум и, скорее, довольно справедливо, это означает, что они должны предположить, что вы знаете некоторые основы языка, в котором вы разрабатываете; как правильно справляться с ошибками и кучей других вещей. Если вы сталкиваетесь с какой-либо статьей и замечаете отсутствие надлежащей проверки ошибок, тогда это нормально; просто убедитесь, что, когда вы включаете эти идеи (но, конечно, никогда не являетесь точным кодом, не так ли?) в свой производственный код, вы будете иметь дело со всеми этими битами и бобами, которые автор разумно упустил, таким образом, подходит для того, что вы разрабатываете.

У меня действительно есть проблема с очень высокоуровневыми вводными статьями, которые веют о таких проблемах, даже не возвращаясь к ним, но, пожалуйста, имейте в виду, что в отношении обработки ошибок нет определенного «мышления» программистов на Java; Я знаю много ваших любимых программистов на C #, которые тоже не беспокоятся о всех своих проблемах.

Печать System.out или e.printStackTrace () – что подразумевает использование System.out, как правило, красного флага, означающего, что кто-то не потрудился выполнять усердную работу. За исключением настольных приложений Java, большинство приложений Java лучше используют протоколирование.

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

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

Он потребляется только тихо, если блок catch пуст.

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

Очевидно, что вы правы, но исключения должны быть зарегистрированы, если их «игнорируют».

Как указывали другие, причина, по которой вы это видите, связана с одной из трех причин:

  1. IDE сгенерировала блок try-catch
    • Код был скопирован и вставлен
    • Разработчик поставил stacktrace для отладки, но никогда не возвращался, чтобы обрабатывать исключение должным образом

Последний момент наименее вероятен. Я говорю это, потому что я не думаю, что кто-то действительно отлаживает этот путь. Выполнение кода с помощью отладчика – гораздо более простой способ для отладки.

Лучшее описание того, что должно быть сделано в блоке catch, можно найти в главе 9 « Эффективная Java » Джошуа Блоха .

В C # все исключения – это исключения во время выполнения, но на Java у вас есть исключения времени выполнения и проверенные исключения, которые вы должны либо поймать, либо объявить в своих методах. Если вы вызываете какой-либо метод, который имеет «броски» в конце, вы должны либо поймать исключения, упомянутые там, либо ваш метод должен также объявить эти исключения.

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

Вы должны видеть это очень часто, если программист выполняет свою работу правильно. Игнорирование Исключения – плохая, плохая практика! Но есть некоторые причины, почему некоторые могут это сделать и более удобные решения:

  • «Это не случится!» Несомненно, когда-нибудь вы «знаете», что это исключение не произойдет, но его еще более целесообразно реконструировать исключение во время выполнения, в то время как исключение Exception как «причина» вместо того, чтобы просто игнорировать его. Бьюсь об заклад, что это произойдет в будущем. 😉

  • Код прототипирования. Если вы просто печатаете свой материал, чтобы узнать, работает ли он, вы можете игнорировать все Исключения, которые могут возникнуть. Это единственный случай, когда я делаю ленивый улов (Throwable). Но если код превратится во что-то полезное, я включу правильную обработку исключений.

  • «Я не знаю, что делать!» Я видел много кода, особенно код библиотеки, который проглатывает исключения, потому что на этом уровне приложения не может быть выполнена надлежащая обработка. Не делайте этого! Просто переверните исключение (либо добавив предложение throws в подпись метода, либо обернув исключение в конкретную библиотеку).

Вы всегда должны пересылать его или обращаться с ним соответствующим образом в реальном контексте. Многие статьи и учебные пособия упростят их код, чтобы получить более важные точки, хотя одна из самых простых вещей для упрощения – обработка ошибок (если только вы не пишете статью об обработке ошибок: :)). Поскольку java-код будет проверять обработку исключений, тогда простой catch (или logging statement) catch-блок – это самый простой способ предоставить рабочий пример.

Если вы найдете это в чем-либо, кроме кода примера, не стесняйтесь пересылать код на TDWTF, хотя у них может быть слишком много его примеров к настоящему времени 🙂

Я боюсь, что большинство программистов Java не знают, что делать с Исключениями, и довольно часто считают это раздражением, которое замедляет их кодирование «номинального» случая. Конечно, они совершенно неправы, но их трудно убедить в том, что важно правильно разбираться с исключениями. Каждый раз, когда я встречаюсь с таким программистом (это часто случается), я даю ему две записи для чтения:

Кстати, я категорически согласен с тем, что глупо перехватывать типизированное исключение, чтобы восстановить его в RuntimeException:

  • если вы его поймаете, ОБРАЩАЙТЕ.
  • в противном случае измените свою подпись метода, чтобы добавить возможные исключения, которые вы / не могли бы обрабатывать, поэтому у вашего вызывающего абонента была бы возможность сделать это самостоятельно.

Сочетание проверенных исключений и интерфейсов приводит к тому, что код должен обрабатывать выходы, которые никогда не будут выбрасываться. (То же самое относится и к нормальному наследованию, но это более распространено и проще объяснить с помощью интерфейсов)

Причина: реализация интерфейса не может исключать (проверять) исключения, отличные от тех, которые определены в спецификации интерфейса. По этой причине создатели интерфейса, не зная, какие методы classа, реализующего интерфейс, действительно должны были бы генерировать исключение, могут указать, что все методы могут вызывать по крайней мере один тип исключения. Пример: JDBC, где объявлено, что все и его бабушка бросают SQLException.

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

Как указывалось, вызов printStackTrace () не является действительно тихой обработкой.

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

Его ленивая практика – ничего, кроме нее.

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

Я не согласен с тем, что перестройка проверенного исключения – лучшая идея. Уловка означает обработку; если вам нужно реконструировать, вы не должны ловить. В этом случае я добавлю предложение throws к сигнатуре метода.

Я бы сказал, что перенос проверенного исключения в unchecked (например, способ, которым Spring обертывает проверенное SQLException в экземпляр его неконтролируемой иерархии) является приемлемым.

Ведение журнала можно рассматривать как обработку. Если этот пример был изменен для записи трассировки стека с использованием log4j вместо записи на консоль, это сделает его приемлемым? Не так много изменений, ИМО.

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

Никогда, никогда, никогда не завершайте проверенное исключение в неконтролируемом исключении.

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

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

Потому что они еще не усвоили этот трюк:

 class ExceptionUtils { public static RuntimeException cloak(Throwable t) { return ExceptionUtils.castAndRethrow(t); } @SuppressWarnings("unchecked") private static  X castAndRethrow(Throwable t) throws X { throw (X) t; } } class Main { public static void main(String[] args) { // Note no "throws" declaration try { // Do stuff that can throw IOException } catch (IOException ex) { // Pretend to throw RuntimeException, but really rethrowing the IOException throw ExceptionUtils.cloak(ex); } } } 

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

Если исключение представляет собой ошибку (в большинстве случаев), наиболее разумным способом справиться с ней является сбой и переход к некоторому верхнему уровню. Повторное использование другого исключения следует учитывать, если к нему добавлена ​​значимая семантика, то есть эта ошибка представляет собой необычную системную ошибку / временную (сетевую) проблему / это ошибка на стороне клиента или сервера и т. Д.

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


Люди Sun хотели, чтобы код был более явным и принудительным программистом, чтобы писать, какие исключения могут быть выбраны с помощью какого метода. Казалось, что это правильный ход: любой будет знать, чего ожидать взамен от любого вызова метода с учетом его прототипа (он может вернуть значение этого типа или бросить экземпляр одного из указанных classов (или его подclassа)).

Но, как выяснилось, с множеством неосведомленных Java-программистов, они теперь рассматривают обработку исключений, как если бы это была ошибка языка / «функция», которая нуждалась в обходном пути и написала код наихудшим или почти наименее возможным способом:

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

Как написать «правильный путь», чем?

  • Укажите каждый базовый class исключений, которые могут быть выбраны в заголовке метода. AFAICR Eclipse может делать это автоматически.
  • Сделайте список бросков в прототипе метода значимым. Long lists are pointless and “throw Exception” is lazy (but useful when you not bother much about exceptions).
  • When writing the “wrong way” simple “throw Exception” is much better and takes less bytes than “try{ … } catch(Exception e) { e.printStackTrace(); }”.
  • Rethrow chained exception if needed.

If you want your exception to be handled outside the scope of the current method you don’t need to to catch it actually, instead you add ‘throws’ statement to the method signature.

The try/catch statements that you’ve seen are only in the code where programmer explicitly decided to handle the exception in place and therefore not to throw it further.

I think developers also try to consider the importance of “doing the right thing” in a particular context. Often times for throw away code or when propagating the exception upwards wouldn’t buy anything because the exception is fatal, you might as well save time and effort by “doing the wrong thing”.

You would usually swallow an exception when you cannot recover from it but it is not critical. One good example is the IOExcetion that can be thrown when closing a database connection. Do you really want to crash if this happens? That’s why Jakarta’s DBUtils have closeSilently methods.

Now for checked exception that you cannot recover but are critical (usually due to programming errors), don’t swallow them. I think exceptions should be logged the nearest as possible to the source of the problem so I would not recommend removing the printStackTrace() call. You will want to turn them into RuntimeException for the sole purpose of not having to declare these exceptions in you business method. Really it doesn’t make sense to have high level business methods such as createClientAccount() throws ProgrammingErrorException (read SQLException), there is nothing you can do if you have typos in your sql or accessing bad indexes.

From experience, Swallowing an exception is harmful mostly when it’s not printed. It helps to bring attention if you crash, and I’ll do that deliberately at times, but simply printing the exception and continuing allows you to find the problem and fix it, and yet usually doesn’t negatively effect others working on the same codebase.

I’m actually into Fail-Fast/Fail-HARD, but at least print it out. If you actually “Eat” an exception (which is to truly do nothing: {}) It will cost someone DAYS to find it.

The problem is that Java forces you to catch a lot of stuff that the developer knows won’t be thrown, or doesn’t care if they are. The most common is Thread.sleep(). I realize there are holes that might allow threading issues here, but generally you know that you are not interrupting it. Период.

There can be many reasons why one would use catch Exception. In many cases it is a bad idea because you also catch RuntimeExceptions – and well you don’t know in what state the underlying objects will be after this happens ? That is always the difficult thing with unexpected conditions: can you trust that the rest of the code will not fail afterwards.

Your example prints the stacktrace so at least your will know what the root cause might have been. In bigger software projects it is a better idea to log these things. And lets hope that the log component does not throw exceptions either our you might end up in an infinite loop (which will probably kill your JVM).

If you have a checked exception and you don’t want to handle it in a method, you should just have the method throw the exception. Only catch and handle exceptions if you are going to do something useful with it. Just logging it is not very useful in my book as users rarely have time to be reading logs looking for exceptions or know what to do if an exception is thrown.

While wrapping the exception is an option, I would not suggest you do this unless; you are throwing a different exception to match an exist interface or there really is no way such an exception should be thrown.

BTW: If you want to re throw a checked exception you can do this with

 try { // do something } catch (Throwable e) { // do something with the exception Thread.currentThread().stop(e); // doesn't actually stop the current thread, but throws the exception/error/throwable } 

Note: if you do this, you should make sure the throws declaration for the method is correct as the compiler is unable to do this for you in this situation.

because it is a best practice. I thought everybody knew.
but the cold truth is that nobody really understands how to work with exceptions. The C error handing style made so much more sense.

  • Что такое ApplicationException для .NET?
  • Параллельная модификация Исключение: добавление в ArrayList
  • Как зарегистрировать ошибку Python с информацией об отладке?
  • Должен ли я наследовать от std :: exception?
  • Как я могу безопасно создать вложенный каталог в Python?
  • Asp.net mvc override OnException в базовом controllerе продолжает распространяться в Application_Error
  • Определяется тип исключения после исключения?
  • Visual Studio: как разбить обработанные исключения?
  • Есть ли разница между «броском» и «броском»?
  • java.io.NotSerializableException
  • Почему существует NotImplementedException?
  • Interesting Posts

    Построение видео по возрастанию из входящих jpeg-изображений

    Изменение пути по умолчанию для сохранения исходных изображений в Windows Photo Gallery

    Android Studio: как удалить APK (или выполнить команду adb) автоматически до запуска или отладки?

    Исправлена ​​ошибка «Параметр недействителен» System.Drawing.Image

    Eclipse экспортирован Runnable JAR, не отображающий изображения

    Настройки памяти Eclipse при получении «Java Heap Space» и «Out of Memory»

    Android Studio: адаптируемая папка: как разместить изображения для нескольких точек на дюйм?

    Установка драйверов Windows 7 автоматически

    Маршрутизатор за маршрутизатором

    Каков наилучший способ переустановки видео с помощью Xvid?

    Окно OpenVPN GUI пусто. Почему я не могу подключиться к моей VPN?

    Как динамически создавать загрузочные модалы как компоненты Angular2?

    Почему не логично синхронизировать логику?

    Google Chrome не может получить доступ к доменам localhost

    Inno Setup: скопируйте папку, вложенные папки и файлы рекурсивно в раздел кода

    Давайте будем гением компьютера.