Исключение нулевого указателя генерируется, когда приложение пытается использовать null в случае, когда требуется объект. К ним относятся:
null
. null
. null
, как если бы это был массив. null
, как если бы это был массив. null
как будто это было значение Throwable. Приложения должны бросать экземпляры этого класса, чтобы указать на другие незаконные использования объекта null
.
Ссылка: http://docs.oracle.com/javase/8/docs/api/java/lang/NullPointerException.html
Большая разница - то, что try...catch
будет глотать исключение, скрывая то, что ошибка произошла. try..finally
выполнит Ваш код очистки, и затем исключение будет продолжать идти, обрабатываться чем-то, что знает, что сделать с ним.
попробуйте {†¦}, выгода {} не всегда плохо. Это не общий шаблон, но я действительно склонен использовать его, когда я должен завершить работу ресурсов, неважно, что, как закрытие (возможно) открытые сокеты в конце потока.
Эффективное различие между Вашими примерами незначительно, пока никакие исключения не выдаются.
, Если, однако, исключение выдается, в то время как в пункте 'попытки', первый пример будет глотать его полностью. Второй пример повысит исключение до следующего, повышают стека вызовов, таким образом, различие в установленных примерах - то, что каждый полностью затеняет любые исключения (первый пример), и другой (второй пример) сохраняет информацию об исключении для потенциала позже обработка, все еще выполняя содержание в 'наконец' пункт.
, Если, например, необходимо было поместить код в пункт 'выгоды' первого примера, который выдал исключение (или тот, который был первоначально повышен, или новый), код очистки читателя никогда не будет выполняться. Наконец выполняется невнимательный из того, что происходит в пункте 'выгоды'.
Так, основное различие между 'выгодой' и 'наконец' то, что содержание 'наконец' блок (за несколькими редкими исключениями) можно рассмотреть , гарантировал для выполнения, даже перед лицом непредвиденной исключительной ситуации, в то время как любой код в соответствии с пунктом 'выгоды' (но вне 'наконец' пункта) не будет нести такую гарантию.
Кстати, Поток и StreamReader и реализуют IDisposable и могут быть обернуты в блок 'использования'. 'Используя' блоки семантический эквивалент попытки/наконец (никакая 'выгода'), таким образом, Ваш пример мог быть более кратко выражен как:
using (StreamReader reader = new StreamReader("myfile.txt"))
{
int i = 5 / 0;
}
..., который закроется и избавится от экземпляра StreamReader, когда он выйдет из объема. Надежда это помогает.
Проблема с блоками попытки/выгоды, которые ловят все исключения, состоит в том, что Ваша программа находится теперь в неопределенном состоянии, если неизвестное исключение происходит. Это идет полностью против сбоя, быстро управляют - Вы не хотите, чтобы Ваша программа продолжилась, если исключение происходит. Вышеупомянутая попытка/выгода даже поймала бы OutOfMemoryExceptions, но это - определенно состояние, в котором не будет работать Ваша программа.
блоки Попытки/наконец позволяют, Вы для выполнения очищаете код при тихом сбое быстро. Для большинства обстоятельств Вы только хотите поймать все исключения на глобальном уровне, так, чтобы можно было зарегистрировать их, и затем выходить.
Среди, вероятно, многих причин исключения очень не спешат выполняться. Можно легко нанести вред времени выполнения, если это происходит много.
Хорошо для одного, это - плохая практика для ловли исключений, которые Вы не потрудились обрабатывать. Выезд Глава 5 о.Net Производительности от Улучшающаяся Производительность приложения.NET и Масштабируемость . Примечание стороны, необходимо, вероятно, загружать поток в блоке попытки, том пути, можно поймать подходящее исключение, если это перестало работать. Создание потока вне блока попытки побеждает свою цель.
С наконец, можно очистить ресурсы, даже если оператор выгоды выдает исключение до программы вызова. С Вашим примером, содержащим пустой оператор выгоды, существует мало различия. Однако, если в Вашей выгоде, Вы сделаете некоторую обработку и бросите ошибку, или даже просто не будете даже иметь выгоды вообще, то наконец будет все еще выполнен.
Взятый от: здесь
Повышение и ловля исключений не должны обычно происходить как часть успешного осуществления метода. При разработке библиотек классов клиентскому коду нужно дать возможность протестировать на состояние ошибки прежде, чем предпринять операцию, которая может привести к повышаемому исключению. Например, Система. IO.FileStream обеспечивает свойство CanRead, которое может быть проверено до вызова метода Read, предотвратив потенциальное повышаемое исключение, как проиллюстрировано в следующем фрагменте кода:
Тусклый str Как Поток = GetStream (), Если (str. CanRead), Тогда 'кодируют для чтения конца потока, Если
решение о том, проверить ли состояние объекта до вызова конкретного метода, который может повысить исключение, зависит от ожидаемого состояния объекта. Если объект FileStream создается с помощью пути к файлу, который должен существовать и конструктор, который должен возвратить файл в режиме чтения, проверив, что свойство CanRead не необходимо; неспособность считать FileStream была бы нарушением ожидаемого поведения вызовов метода, сделанных, и исключение должно быть повышено. Напротив, если метод документируется как возврат ссылки FileStream, которая может или не может быть читаемой, проверив, что свойство CanRead прежде, чем попытаться считать данные желательно.
Для иллюстрирования влияния производительности, что с помощью "выполненный, пока исключение" кодирование техники не может вызвать выполнение броска, который бросает InvalidCastException, если бросок сбои, сравнивается с C# как с оператором, который возвраты аннулирует, если состав исполнителей перестал работать. Производительность этих двух методов идентична для случая, где бросок допустим (см. Тест 8.05), но для случая, где бросок недопустим, и использование броска, вызывает исключение, использование броска в 600 раз медленнее, чем использование как оператор (см. Тест 8.06). Высокоэффективное влияние бросающей исключение техники включает стоимость выделения, броска и ловли исключения и стоимости последующей сборки "мусора" объекта исключения, что означает, мгновенное влияние выдачи исключения не является этим высоко. Поскольку больше исключений выдается, частая сборка "мусора" становится проблемой, таким образом, полное влияние частого использования исключения - бросающий кодирование техники будет подобно для Тестирования 8.05.
Если Вы не знаете, какой тип исключительной ситуации поймать или что сделать с ним, нет никакого смысла в наличии оператора выгоды. Необходимо просто оставить его для вызывающей стороны большой шишки, которая может иметь больше информации о ситуации для знания, что сделать.
Вы должны все еще иметь наконец оператор там в случае, если существует исключение, так, чтобы можно было очистить ресурсы, прежде чем то исключение будет выдано вызывающей стороне.
Наконец является дополнительным - нет никакой причины иметь "Наконец" блок, при отсутствии ресурсов для чистки.
Попытка.. наконец блок все еще выдаст любые исключения, которые повышены. Весь finally
делает, гарантируют, что код очистки выполняется, прежде чем исключение выдается.
попытка.. выгода с пустой выгодой полностью использует любое исключение и скроет то, что это произошло. Средство чтения будет закрыто, но нет никакого сообщения, если корректная вещь произошла. Что, если Ваше намерение состояло в том, чтобы записать я в файл? В этом случае Вы не доберетесь до той части кода и , myfile.txt будет пуст. Все нисходящие методы обрабатывают это правильно? Когда Вы будете видеть пустой файл, Вы будете в состоянии правильно предположить, что это пусто, потому что исключение было выдано? Лучше, чтобы выдать исключение и позволить ему быть известным, что Вы делаете что-то не так.
Другой причиной является попытка.. поймайте сделанный как это, является абсолютно неправильным. То, что Вы говорите путем выполнения этого, "Неважно, что происходит, я могу обработать его". Что относительно StackOverflowException
, можно ли вымыться после этого? Что относительно OutOfMemoryException
? В целом необходимо только обработать исключения, которые Вы ожидаете и знаете, как обработать.
Я соглашаюсь с тем, что, кажется, согласие здесь - пустая 'выгода' плоха, потому что это маскирует любое исключение, возможно, произошел в блоке попытки.
кроме того, с точки зрения удобочитаемости, когда я вижу блок 'попытки', я предполагаю, что будет соответствующий оператор 'выгоды'. Если Вы только используете 'попытку', чтобы удостовериться, что ресурсы освобождены в 'наконец' блок, Вы могли бы рассмотреть оператор 'использования' вместо этого:
using (StreamReader reader = new StreamReader('myfile.txt'))
{
// do stuff here
} // reader.dispose() is called automatically
можно использовать оператор 'использования' с любым объектом, который реализует IDisposable. Объект располагает (), метод называют автоматически в конце блока.
Наконец выполняется несмотря ни на что. Так, если Ваш блок попытки был успешен, он выполнится, если Ваш блок попытки перестанет работать, он тогда выполнит блок выгоды, и затем наконец блок.
кроме того, лучше попытаться использовать следующую конструкцию:
using (StreamReader reader=new StreamReader("myfile.txt"))
{
}
, Поскольку оператор использования автоматически обертывается в попытку / наконец, и поток будет автоматически закрыт. (Необходимо будет поместить попытку / выгода вокруг оператора использования, если Вы захотите на самом деле поймать исключение).
В то время как следующие 2 блока кода эквивалентны, они не равны.
try
{
int i = 1/0;
}
catch
{
reader.Close();
throw;
}
try
{
int i = 1/0;
}
finally
{
reader.Close();
}
наконец блоки являются особенными. CLR распознает и рассматривает скручивание жгутов кода наконец блок отдельно от блоков выгоды, и CLR идет на многое, чтобы гарантировать, что наконец блок будет всегда выполняться. Это не просто синтаксический сахар из компилятора.
Поскольку, когда та одна одна строка выдает исключение, Вы не знали бы это.
С первым блоком кода, исключение просто будет , поглотил , программа продолжит выполняться, даже когда состояние программы могло бы быть неправильным.
Со вторым блоком, исключение будет брошено и пузыри , но эти reader.Close()
, как все еще гарантируют, будет работать.
, Если исключение не ожидается, то не помещайте попытку.. блок выгоды именно так, будет трудно отладить позже, когда программа вошла в плохое состояние, и у Вас нет идеи почему.
"Наконец" оператор "Чего-то, что необходимо всегда делать, чтобы удостовериться, что состояние программы нормально". По сути, это всегда - хорошая форма для имения один, если существует возможность, что исключения могут отбросить состояние программы. Компилятор также идет на многое, чтобы гарантировать, чтобы Ваш Наконец кодировали, выполняется.
"Выгода" является оператором, "Я могу восстановиться с этого исключения". Необходимо только восстановиться с исключений, которые действительно можно исправить - ловят без аргументов, говорит "Эй, я могу восстановиться с чего-либо!", который почти всегда неверен.
, Если бы было возможно восстановиться с каждого исключения, тогда это действительно был бы семантический каламбур, о том, чем Вы объявляете свое намерение быть. Однако это не, и почти наверняка структурирует выше Вашего, будет лучше оборудован для обрабатывания определенных исключений. По сути, используйте наконец, получите свой код очистки, выполненный бесплатно, но все еще позвольте более хорошо осведомленным обработчикам заниматься проблемой.
С точки зрения удобочитаемости это более явно говорит, что будущие читатели кода "этот материал в здесь важны, это должно быть сделано, неважно, что происходит". Это хорошо.
кроме того, пустые операторы выгоды имеют тенденцию иметь определенный "запах" им. Они могли бы быть знаком, что разработчики не продумывают различные исключения, которые могут произойти и как обработать их.