Возврат из наконец блока в Java

Когда вы объявляете ссылочную переменную (т. е. объект), вы действительно создаете указатель на объект. Рассмотрим следующий код, в котором вы объявляете переменную примитивного типа int:

int x;
x = 10;

В этом примере переменная x является int, и Java инициализирует ее для 0. Когда вы назначаете его 10 во второй строке, ваше значение 10 записывается в ячейку памяти, на которую указывает x.

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

Integer num;
num = new Integer(10);

Первая строка объявляет переменную с именем num, но она не содержит примитивного значения. Вместо этого он содержит указатель (потому что тип Integer является ссылочным типом). Поскольку вы еще не указали, что указать на Java, он устанавливает значение null, что означает «Я ничего не указываю».

Во второй строке ключевое слово new используется для создания экземпляра (или создания ) объекту типа Integer и переменной указателя num присваивается этот объект. Теперь вы можете ссылаться на объект, используя оператор разыменования . (точка).

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

Например, вы можете имеют следующий метод:

public void doSomething(SomeObject obj) {
   //do something to obj
}

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

doSomething(null);

В этом случае obj имеет значение null. Если метод предназначен для того, чтобы что-то сделать для переданного объекта, целесообразно бросить NullPointerException, потому что это ошибка программиста, и программисту понадобится эта информация для целей отладки.

Альтернативно, там могут быть случаи, когда цель метода заключается не только в том, чтобы работать с переданным в объекте, и поэтому нулевой параметр может быть приемлемым. В этом случае вам нужно будет проверить нулевой параметр и вести себя по-другому. Вы также должны объяснить это в документации. Например, doSomething может быть записано как:

/**
  * @param obj An optional foo for ____. May be null, in which case 
  *  the result will be ____.
  */
public void doSomething(SomeObject obj) {
    if(obj != null) {
       //do something
    } else {
       //do something else
    }
}

Наконец, Как определить исключение & amp; причина использования Трассировки стека

168
задан Matt Sheppard 7 January 2016 в 05:41
поделиться

4 ответа

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

, Даже если существует изобретенный пример, где это "лучше", рассмотрите разработчика, который должен поддержать Ваш код позже и кто не мог бы знать о тонкости. То, что бедный разработчик мог бы даже быть Вами....

85
ответ дан Jason Cohen 23 November 2019 в 20:56
поделиться

Мне пришлось ДЕЙСТВИТЕЛЬНО нелегко для разыскивания ошибки несколько лет назад, которая была вызвана этим. Код был чем-то как:

Object problemMethod() {
    Object rtn = null;
    try {
        rtn = somethingThatThrewAnException();
    }
    finally {
        doSomeCleanup();
        return rtn;
    }
}

то, Что произошло, - то, что исключение было выдано вниз в некотором другом коде. Это было поймано и зарегистрировано и повторно брошено в somethingThatThrewAnException() метод. Но исключение не распространялось прошлое problemMethod(). После Долгого времени рассмотрения этого мы наконец разыскали его к методу возврата. Метод возврата в наконец блок в основном останавливал исключение, которое произошло в блоке попытки от распространения даже при том, что это не было поймано.

Как другие сказали, в то время как законно возвратиться из наконец блок согласно спецификации Java, это - ПЛОХАЯ вещь и не должно быть сделано.

141
ответ дан Flow 23 November 2019 в 20:56
поделиться

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

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

21
ответ дан Tom Hawtin - tackline 23 November 2019 в 20:56
поделиться

Добавление управляющих структур и возвратов к наконец {} блоки являются просто другим примером "просто, потому что Вы можете" злоупотребления, которые рассеиваются всюду по фактически всем языкам разработки. Jason был прав в предложении, это могло легко стать кошмаром обслуживания - аргументы против ранних возвратов из функций применяются больше так к этому случаю "поздних возвратов".

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

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

13
ответ дан Ian 23 November 2019 в 20:56
поделиться
Другие вопросы по тегам:

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