Вопрос о возврате дизайна Java try-finally

В Java попытка {…} наконец {…} выполняется несколько неинтуитивно для меня. Как проиллюстрировано в другом вопросе, окончательно ли выполняется Java на Java? , если у вас есть оператор return в блоке try, он будет проигнорирован, если определен блок finally. Например, функция

boolean test () { try { return true; } finally { return false; } } 

всегда будет возвращать false. Мой вопрос: почему это? Есть ли особая философия, лежащая в основе этого дизайнерского решения Java? Я ценю любое понимание, спасибо.

Редактировать: меня особенно интересует «почему» Java считает, что это нормально нарушать семантику, которую я определяю. Если я вернусь в блок try, метод должен вернуться туда и обратно. Но JVM решает проигнорировать мою инструкцию и вернуться из подпрограммы, которая на самом деле еще не достигнута.

С технической точки зрения, return в блок try не будет игнорироваться, если будет определен блок finally , только если этот блок finally также включает в себя return .

Это сомнительное дизайнерское решение, которое, вероятно, было ошибкой в ​​ретроспективе (подобно тому, как ссылки были обнуляемыми / изменяемыми по умолчанию и, по некоторым данным, проверенными исключениями). Во многом это поведение в точности согласуется с разговорной концепцией того, что в finally означает – «независимо от того, что происходит заранее в блоке try , всегда запускайте этот код». Следовательно, если вы return true из блока finally , общий эффект должен всегда состоять в том, чтобы вернуть true, no?

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

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

Среди других мест это также обсуждается в книге Java Puzzlers .

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

Если вы вызываете javac с -Xlint, тогда будет создано соответствующее предупреждение, указывающее, что вы не должны вызывать возврат из предложения finally. Например (компиляция простого classа с помощью вышеуказанного метода test() ):

 javac -Xlint foo.java foo.java:13: warning: [finally] finally clause cannot complete normally } ^ 1 warning 

проверьте это для справки. Наконец, выполняется ли в Java?

«Оператор try с блоком finally выполняется сначала с использованием блока try. Тогда есть выбор:
Если выполнение блока try завершается нормально, […]
Если выполнение блока try завершается внезапно из-за выброса значения V, […]
Если выполнение блока try завершается внезапно по любой другой причине R, тогда выполняется блок finally. Тогда есть выбор:
Если окончательный блок завершается нормально, то оператор try внезапно завершается по причине R.
Если блок finally завершится внезапно для разума S, то оператор try внезапно завершится по причине S (и причина R отбрасывается). ”

objective finally :

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

  • Не рекомендуется использовать оператор return в блоке finally поскольку он переопределяет оператор return из блока catch & try . и предупреждает: « наконец, блок не заканчивается нормально »

  • блок finally должен иметь оператор return только тогда, когда оба try и catch не имеют оператора return .

  • Инсайз и try и catch имеют разное значение, тогда мы не должны ничего хранить в блоке,

  • и если мы возвращаем одно и то же значение как в блоке try и catch тогда его лучше сохранить в finally и удалить return в обоих блоках try & catch .
  • Если, finally выбрасывается какое-либо исключение, то return внутри этого блока не будет выполняться.

блок finally не будет выполняться только тогда, когда:

  • При вызове System.exit ()
  • процесс убийства
  • аварии приложения / среды
  • stackoverflow / бесконечный цикл

Хотя блок finally создан для закрытия ресурсов, и оператор возврата обычно не должен быть там, и Eclipse предупреждает, что «наконец-то блок не выполняется нормально», я обнаружил, что в некоторых случаях «окончательный возврат» по-прежнему является желательным.

 ResponseType response = new ResponseType(); try{ //set some properties of the response object. response.setStatus(1); //return response; }catch (Exception e){ //Some other properties of the response object according to the exception. response.setStatus(0); //return response; }finally{ return response; } 

Если я не поставлю предложение return в блоке finally, мне придется повторять его в try и catch block, а текущий код немного яснее.

  • Почему конструктор по умолчанию требуется в родительском classе, если он имеет аргумент-редактор?
  • Пример кода кодирования и декодирования Base 64
  • пакет javax vs java
  • BitmapFactory.decodeResource возвращает измененный битмап в Android 2.2 и неизменный Bitmap в Android 1.6
  • Ошибка сборки тестов для Android: несколько файлов dex определяют Landroid / support / test / BuildConfig
  • Лучший способ сравнить даты в Android
  • Как работает BreakIterator в Android?
  • как я могу обнаружить клавиши со стрелками в java-консоли, а не в графическом интерфейсе?
  • как проверить версию jdk, используемую для компиляции файла .class
  • Android: как отображать предварительный просмотр камеры с помощью обратного вызова?
  • Токенизация строки, но игнорирование разделителей в кавычках
  • Interesting Posts

    установка ионной npm ERR! Ошибка tar.unpack

    Как использовать длинный идентификатор в Rails-приложениях?

    Фильтр аутентификации и сервлет для входа в систему

    fancybox2 / fancybox заставляет страницу прыгать вверх

    Другое: принудительно Chrome полностью загружать mp4-видео

    SignalR – отправка сообщения определенному пользователю с использованием (IUserIdProvider) * NEW 2.0.0 *

    Невозможно разобрать hibernate.cfg.xml в автономном режиме

    Как скрыть или свернуть окно X11 с консоли?

    Как избежать прохождения параметров везде в play2?

    Ошибка: XDG_RUNTIME_DIR не установлен в среде. Gtk-WARNING **: невозможно открыть дисплей:

    Создать N-элементный массив constexpr в C ++ 11

    Swift 3 сохранение и извлечение пользовательского объекта из userDefaults

    Ошибка: invalid_client нет имени приложения

    Машина Windows 7 делает маршрутизатор отключенным ВСЕМИ беспроводными соединениями

    Использование TypeScript в существующем проекте Visual Studio Web Site

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