Почему попытка {…} наконец {…} хороший; попробовать {…} выгоду {} плохо?

Исключение нулевого указателя генерируется, когда приложение пытается использовать null в случае, когда требуется объект. К ним относятся:

  1. Вызов метода экземпляра объекта null.
  2. Доступ или изменение поля объекта null.
  3. Принимая длину null, как если бы это был массив.
  4. Доступ или изменение слотов null, как если бы это был массив.
  5. Бросок null как будто это было значение Throwable.

Приложения должны бросать экземпляры этого класса, чтобы указать на другие незаконные использования объекта null.

Ссылка: http://docs.oracle.com/javase/8/docs/api/java/lang/NullPointerException.html

196
задан FMFF 1 September 2011 в 09:04
поделиться

17 ответов

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

354
ответ дан Khoth 23 November 2019 в 05:18
поделиться

попробуйте {†¦}, выгода {} не всегда плохо. Это не общий шаблон, но я действительно склонен использовать его, когда я должен завершить работу ресурсов, неважно, что, как закрытие (возможно) открытые сокеты в конце потока.

0
ответ дан Martin Liesén 23 November 2019 в 05:18
поделиться

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

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

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

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

Кстати, Поток и StreamReader и реализуют IDisposable и могут быть обернуты в блок 'использования'. 'Используя' блоки семантический эквивалент попытки/наконец (никакая 'выгода'), таким образом, Ваш пример мог быть более кратко выражен как:

using (StreamReader reader = new  StreamReader("myfile.txt"))
{
  int i = 5 / 0;
}

..., который закроется и избавится от экземпляра StreamReader, когда он выйдет из объема. Надежда это помогает.

0
ответ дан Jared 23 November 2019 в 05:18
поделиться

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

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

0
ответ дан David Mohundro 23 November 2019 в 05:18
поделиться

Среди, вероятно, многих причин исключения очень не спешат выполняться. Можно легко нанести вред времени выполнения, если это происходит много.

0
ответ дан lotsoffreetime 23 November 2019 в 05:18
поделиться

Хорошо для одного, это - плохая практика для ловли исключений, которые Вы не потрудились обрабатывать. Выезд Глава 5 о.Net Производительности от Улучшающаяся Производительность приложения.NET и Масштабируемость . Примечание стороны, необходимо, вероятно, загружать поток в блоке попытки, том пути, можно поймать подходящее исключение, если это перестало работать. Создание потока вне блока попытки побеждает свою цель.

1
ответ дан Factor Mystic 23 November 2019 в 05:18
поделиться

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

1
ответ дан Kibbee 23 November 2019 в 05:18
поделиться

Взятый от: здесь

Повышение и ловля исключений не должны обычно происходить как часть успешного осуществления метода. При разработке библиотек классов клиентскому коду нужно дать возможность протестировать на состояние ошибки прежде, чем предпринять операцию, которая может привести к повышаемому исключению. Например, Система. IO.FileStream обеспечивает свойство CanRead, которое может быть проверено до вызова метода Read, предотвратив потенциальное повышаемое исключение, как проиллюстрировано в следующем фрагменте кода:

Тусклый str Как Поток = GetStream (), Если (str. CanRead), Тогда 'кодируют для чтения конца потока, Если

решение о том, проверить ли состояние объекта до вызова конкретного метода, который может повысить исключение, зависит от ожидаемого состояния объекта. Если объект FileStream создается с помощью пути к файлу, который должен существовать и конструктор, который должен возвратить файл в режиме чтения, проверив, что свойство CanRead не необходимо; неспособность считать FileStream была бы нарушением ожидаемого поведения вызовов метода, сделанных, и исключение должно быть повышено. Напротив, если метод документируется как возврат ссылки FileStream, которая может или не может быть читаемой, проверив, что свойство CanRead прежде, чем попытаться считать данные желательно.

Для иллюстрирования влияния производительности, что с помощью "выполненный, пока исключение" кодирование техники не может вызвать выполнение броска, который бросает InvalidCastException, если бросок сбои, сравнивается с C# как с оператором, который возвраты аннулирует, если состав исполнителей перестал работать. Производительность этих двух методов идентична для случая, где бросок допустим (см. Тест 8.05), но для случая, где бросок недопустим, и использование броска, вызывает исключение, использование броска в 600 раз медленнее, чем использование как оператор (см. Тест 8.06). Высокоэффективное влияние бросающей исключение техники включает стоимость выделения, броска и ловли исключения и стоимости последующей сборки "мусора" объекта исключения, что означает, мгновенное влияние выдачи исключения не является этим высоко. Поскольку больше исключений выдается, частая сборка "мусора" становится проблемой, таким образом, полное влияние частого использования исключения - бросающий кодирование техники будет подобно для Тестирования 8.05.

2
ответ дан SpoiledTechie.com 23 November 2019 в 05:18
поделиться

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

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

2
ответ дан Mark Cidade 23 November 2019 в 05:18
поделиться

Наконец является дополнительным - нет никакой причины иметь "Наконец" блок, при отсутствии ресурсов для чистки.

2
ответ дан Guy Starbuck 23 November 2019 в 05:18
поделиться

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

попытка.. выгода с пустой выгодой полностью использует любое исключение и скроет то, что это произошло. Средство чтения будет закрыто, но нет никакого сообщения, если корректная вещь произошла. Что, если Ваше намерение состояло в том, чтобы записать я в файл? В этом случае Вы не доберетесь до той части кода и , myfile.txt будет пуст. Все нисходящие методы обрабатывают это правильно? Когда Вы будете видеть пустой файл, Вы будете в состоянии правильно предположить, что это пусто, потому что исключение было выдано? Лучше, чтобы выдать исключение и позволить ему быть известным, что Вы делаете что-то не так.

Другой причиной является попытка.. поймайте сделанный как это, является абсолютно неправильным. То, что Вы говорите путем выполнения этого, "Неважно, что происходит, я могу обработать его". Что относительно StackOverflowException, можно ли вымыться после этого? Что относительно OutOfMemoryException? В целом необходимо только обработать исключения, которые Вы ожидаете и знаете, как обработать.

3
ответ дан OwenP 23 November 2019 в 05:18
поделиться

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

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

using (StreamReader reader = new StreamReader('myfile.txt'))
{
    // do stuff here
} // reader.dispose() is called automatically

можно использовать оператор 'использования' с любым объектом, который реализует IDisposable. Объект располагает (), метод называют автоматически в конце блока.

5
ответ дан Chris Lawlor 23 November 2019 в 05:18
поделиться

Наконец выполняется несмотря ни на что. Так, если Ваш блок попытки был успешен, он выполнится, если Ваш блок попытки перестанет работать, он тогда выполнит блок выгоды, и затем наконец блок.

кроме того, лучше попытаться использовать следующую конструкцию:

using (StreamReader reader=new  StreamReader("myfile.txt"))
{
}

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

21
ответ дан Mark Ingram 23 November 2019 в 05:18
поделиться

В то время как следующие 2 блока кода эквивалентны, они не равны.

try
{
  int i = 1/0; 
}
catch
{
  reader.Close();
  throw;
}

try
{
  int i = 1/0;
}
finally
{
  reader.Close();
}
  1. 'наконец' показывающий намерение код. Вы объявляете к компилятору и другим программистам, которых этот код должен выполнить несмотря ни на что.
  2. , если у Вас есть несколько блоков выгоды, и у Вас есть код очистки, Вам нужно наконец. Без наконец, Вы копировали бы свой код очистки в каждом блоке выгоды. (Принцип DRY)

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

8
ответ дан Robert Paulson 23 November 2019 в 05:18
поделиться

Поскольку, когда та одна одна строка выдает исключение, Вы не знали бы это.

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

Со вторым блоком, исключение будет брошено и пузыри , но эти reader.Close(), как все еще гарантируют, будет работать.

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

32
ответ дан chakrit 23 November 2019 в 05:18
поделиться

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

"Выгода" является оператором, "Я могу восстановиться с этого исключения". Необходимо только восстановиться с исключений, которые действительно можно исправить - ловят без аргументов, говорит "Эй, я могу восстановиться с чего-либо!", который почти всегда неверен.

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

60
ответ дан Adam Wright 23 November 2019 в 05:18
поделиться

С точки зрения удобочитаемости это более явно говорит, что будущие читатели кода "этот материал в здесь важны, это должно быть сделано, неважно, что происходит". Это хорошо.

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

2
ответ дан Ryan 23 November 2019 в 05:18
поделиться
Другие вопросы по тегам:

Похожие вопросы: