Один try — сколько угодно catch
Конструкция try-catch в языке Java помогает обрабатывать исключения. В блоке catch мы указываем класс исключений, которые «ловим». Взгляните на код ниже — если в try случится ArithmeticException, управление перейдёт к блоку catch и программа выдаст ошибку: Что ты делаешь, говорили же не делить на ноль!.
Но что будет, если в коде случится другое исключение, которое мы не предусматривали?
Зайдём издалека: в Java ссылочная переменная может ссылаться на любой объект, созданный из её дочернего класса. Например, если класс Child наследуется от класса Parent, то ссылка на переменную типа Child может храниться в переменной типа Parent: Parent man = new Child();.
Это правило работает везде — catch (ArithmeticException e) обработает любое исключение, если оно наследуется от ArithmeticException. Но если в блоке случится событие, которое не относится ни к ArithmeticException, ни к его классам-наследникам, try-catch для него не сработает.
Кроме ArithmeticException есть и другие исключения, одно из них — NullPointerException. Оно возникает, когда ссылка на объект хранит null и по ней пытаются получить значение поля объекта или вызвать его метод.
Пример:
На практике NullPointerException по сравнению с другими встроенными в Java исключениями возникает очень часто, поэтому у него есть сокращённое название: NPE.
Желательно писать код так, чтобы NPE не возникали. Для этого нужно, чтобы null никогда не передавался в качестве аргумента и не возвращался в результате метода null. Тогда и обрабатывать NPE не придётся.
Но если мы хотим перехватывать ArithmeticException и NullPointerException одновременно, после try можно написать сколько угодно catch и в каждом из них обработать нужное исключение:
Когда в try возникает исключение, Java по порядку проверяет блоки catch и находит первый подходящий.
В нашем примере это произойдёт так: если в try произошло исключение, Java проверит — это ArithmeticException? Если да, то запустится код из первого catch. Если нет, Java пойдёт дальше. Возникло NPE? Тогда сработает второй catch. Если ничего не совпало, то ни один из catch не подошёл — программа «выбросит» исключение, как будто его никто и не «ловил».
Рекламный персонаж
С первой рекламы Барби представили не просто как игрушку. «Моя кукла Барби настоящая» — пели за кадром. Она миниатюрная, опрятная, очаровывает окружающих на вечеринках — так говорят не о товаре, а о человеке. За первый год компания продала 300 000 Барби.
В случае с Mattel все понятно. Не сделать из красавицы-куклы рекламного персонажа было бы странно. Но это хороший ход для любого бизнеса, и не только для продавцов детских товаров. Помните братьев Эрла и Симуса, которые создают разные палочки Twix?
А вот свежий пример — цифровой сервис Chess.com запустил в Instagram* ролики со своим персонажем и подсадил подростков на шахматы. На видео бумер в нелепом костюме пешки все время попадает в неловкие ситуации.
Персонажа можно создать даже с минимальным бюджетом — вот пример Aviasales. Самолеша живет в Twitter и шутит шутки. Графика — простейшая.
Выполнение VEH.
Выполнение VEH в Windows XP Beta 2 исключительно прямолинейно. AddVectoredExceptionHandler является форвадером RtlAddVectoredExceptionHandler из NTDLL. Рисунок 4 показывает псевдокод функции RtlAddVectoredExceptionHandler. Список VEH-обработчиков хранится как связанный список. Каждый зарегистрированный обработчик представлен 12-ти байтным узлом, расположенным в куче процесса. Критическая секция защищает код, который фактически вставляет новый обработчик в голову или конец списка. Если параметр FirstHandler не ноль, новый элемент вставляется в начало списка, иначе — в конец. Довольно просто! Нет кода, который проверяет, а не зарегистрирован ли уже этот новый обработчик, так что для некоторого обработчика возможно, что он будет зарегистрирован (и вызван) более одно раза.
Другая примечательная особенность VEH — то, как вызываются обработчики. Как я написал в моей статье про SEH, KiUserExceptionDispatcher (в NTDLL) вызывает RtlDispatchException. Рисунок 5 показывает, как VEH был добавлен в код RtlDispatchException в NTDLL. Если вы сравните этот и оригинальный код из моей ранней статьи, вы увидите, что добавился только вызов функции RtlCallVectoredExceptionHandlers в самом начале RtlDispatchException. Это доказывает, что VEH-обработчика вызываются перед SEH-обработчиками.
Псевдокод RtlCallVectoredExceptionHandlers показан на рисунке 6. Снова, код очень простой. Критическая секция охраняет цикл while. Так цикл проходит через каждый зарегистрированный обработчик и вызывает функцию обработчика. Если обработчик вернул EXCEPTION_CONTINUE_EXECUTION, цикл прекращается без обхода остальных обработчиков. Также функция заботится о возвращаемом значении, говорящем RtlDispatchException, стоит ли затевать поиск SEH-обработчиков.
Итак, VEH является существенным дополнением к Windows XP. Мне остается только сожалеть, что эта возможность не была добавлена раньше. Я продемонстрировал одно из многих преимуществ VEH и надеюсь, что в будущем эта технология будет широко использоваться в различных инновационных проектах.
Из Microsoft Systems Journal. Сентябрь 2001.
Мэт Питрек, пер. pawa
Преемственность стиля
Барби уже могла бы быть бабушкой — ей больше 60 лет. За это время куклу не раз перекраивали — менялось ее лицо и даже фирменная точеная фигура. Тем не менее для аудитории она одна — глянцевая, стильная и, конечно, в розовом.
Менялся и логотип Барби, но единый стиль сохраняли и для него.
Все это — для формирования узнаваемости бренда и ощущения стабильности у аудитории. Изменения вызывают тревогу клиента. Mattel ее отрабатывал, например, так:
Разберем эту рекламу по пунктам — что делает Mattel:
-
перечисляет преимущества новой модели куклы;
-
предлагает не выкидывать, а обменять старую куклу на новую;
-
предлагает ограниченное количество моделей со скидкой.
Идентификация покупателя с продуктом
Барби изначально общалась с возможными покупателями так, чтобы они начали ассоциировать себя с куклой.
Барби — это образ идеальной девушки с нереалистичными параметрами фигуры (что не раз подвергалось критике), безграничными финансовыми возможностями (домами и кабриолетами) и прочим. Но каждый раз Барби обещала в рекламе, что любая девочка может стать похожей на нее.
Один из слоганов рекламы — «Когда девочка играет с Барби, она представляет все, кем может стать». За кадром рекламы пели: «Барби, я притворяюсь, что я — это ты», «Мы, девочки, любим быть в центре внимания», «Куда бы мы не двинулись, мы затмеваем всех».
Это работает для любых продуктов. Один из самых популярных принципов рекламы — продавать не продукт, а мечту. Не робот-пылесос, а отдых после работы, не шампунь, а ухоженные волосы. У Mattel получилось.
Мир ждет выхода полнометражки «Барби», которая расскажет о кукле еще больше. Представят фильм 20 июля — посмотрим, как на этот раз вырастут продажи Барби. Идете в кино?
*Компания Meta, а также ее продукты Facebook и Instagram признаны экстремистскими в России.
Новая векторная обработка исключений в Windows XP — Архив WASM.RU
Работая с Win32 более 8 лет назад, я создал список особенностей (уровня API), которые мне удалось заметить. Главным образом, они делали мою программистскую жизнь легче, а также помогали проще писать полезные инструменты. Когда я установил бета-версию Windows XP (известную под именем «Whistler»), я не ожидал увидеть так много новых API и был приятно этим удивлен. В этом месяце я собираюсь описать одно из нововведений, известное как векторная обработка исключений.
Я наткнулся на VEH, работая с утилитой PEDIFF. Вы указываете путь к двум разным копиям DLL, и PEDIFF выдает список отличающихся API, экспортируемых модулями. Так я обнаружил VEH, сравнивая директории экспорта kernel32.dll от Win2000 и WinXP. Имелось много новых API, но сразу бросилась в глаза функция AddVectoredExceptionHandler. Как дополнительный бонус, эта API была документирована в одном из последних выпусков MSDN Library, так что я не должен был охотиться за информацией.
Обзор SEH.
Так что такое VEH? Для начала, следует рассмотреть регулярную обработку исключений и заметить, чем отличается VEH. Статья рассчитана на подготовленных читателей, знающих основы SEH и языка программирования C++. SEH реализован в C++ с помощью выражений try/catch или расширением компилятора MS C++ __try/__except. Для детального ознакомления как работает SEH, смотрите мою статью «A Crash Course in Structured Exception Handling» за январь 1997 в MSJ. Короче говоря, SEH использует размещенные в стеке узлы. Когда вы используете блок try, информация об обработчике исключений сохраняется в стековом кадре текущей процедуры. В архитектуре x86, Microsoft использовала значение в fs: для указания на текущий фрейм обработчика исключений. Фрейм содержит адрес кода, который будет вызван при возникновении исключения.
Если вы вызываете некоторую функцию внутри блока try, эта новая функция может установить свой собственный обработчик. Когда это происходит, в стеке создается новый фрейм обработчика и устанавливается указатель на предыдущий фрейм, как показано на рисунке 1. В сущности, SEH-фреймы образуют связанный список, начало которого адресуется через FS:
Следует обратить внимание, что каждый последующий узел должен располагаться в стеке выше предыдущего. Операционная система предписывает это правило, следовательно, вы не можете создать произвольно как новый фрейм и вставить его в список
Рисунок 1. Обработчики исключений в стеке. |
Сей факт, что фреймы хранятся как узлы связанного списка, не только значительная деталь в великой схеме вещей, а ключ к пониманию механизма работы SEH. Когда происходит исключение, система начинает с головы списка и вызывает обработчики со словами: «Произошло исключение. Не желаете ли его обработать?». Обработчик может обработать исключение, решив проблему, и вернуть статус EXCEPTION_CONTINUE_EXECUTION.
Обработчик также может отклонить предложение и вернуть EXCEPTION_CONTINUE_SEARCH. Когда это происходит, система перемещается к следующему узлу в списке и задает тот же вопрос. Это продолжается до тех пор, пока кто-то не решится обработать исключение, или список не закончится. Я здесь не в давался в детали, но этого вполне достаточно для наших целей.
Каковы особенности архитектуры SEH? Важно, что данный обработчик может решить, что делать с исключением, несмотря на то, что другие обработчики (которые далее по списку) хотели бы обработать это исключение. Иногда это может быть проблемой
Следующий пример покажет почему.
Скажем, вы написали самый лучший в мире обработчик исключений. Когда происходит что-то плохое, ваш обработчик определяет причину, регистрирует необходимые детали, решает проблему мирового голода и за неделю отменяет назначенную встречу. Кроме того, вы помещаете ваш обработчик в WinMain, чтобы вся программа была охвачена. Теперь, в некотором месте вы вызываете внешний компонент, который никак не можете контролировать. Этот компонент также устанавливает обработчик. При первом же исключении, этот обработчик выходит из программы. Ваш обработчик никогда не получит шанса выполниться, потому что другой обработчик оказался первым в списке обработчиков. Короче говоря, прелести SEH ограничены тем фактом, что обработчики эффективны, пока кто-то глубже в цепи запросов не установил свой собственный обработчик.
Позвольте мне указать на еще одну особенность SEH перед тем, как перейти к VEH. Когда программа отлаживается, и происходит исключение, выполняется еще несколько шагов. Сперва отладчик получает первый шанс обработать исключение или позволить отлаживаемому процессу увидеть это самое исключение. Если этот дочерний процесс видит исключение, происходят ранее описанные действия. Если в процессе не нашлось обработчика, отладчик получает вторую возможность обработать исключение. (Обычно это происходит, когда отладчик выскакивает с диалогом необработанного исключения.)
Finally — выполнить при любых условиях
У конструкции try-catch есть ещё один блок, он называется finally
Исполняемая программа попадает в него всегда — неважно, произошло ли исключение в try и сработал ли какой-то catch
Блок finally сработает, даже если в try или в catch код наткнётся на return. Сначала выполнится finally, а потом программа выйдет из метода.
Единственный случай, когда finally не срабатывает, — критическая ошибка, когда программа вылетела или у неё закончилась выделенная память.
Приведём пример ситуации, в которой полезен finally. Представим, что нужно открыть файл, получить данные и закрыть его. Java работает с файлами через потоки ввода-вывода. Не страшно, если вы с ними не знакомы
Важно то, что для работы с потоком его нужно открыть, а в конце работы закрыть, чтобы в операционной системе не было утечки ресурсов
Звучит несложно: открыть поток, поработать с ним и закрыть его. Но что будет, если в процессе произойдёт исключение и поток не закроется? Спасает finally: в блок try нужно поместить весь код для работы с потоком, в catch — для обработки возможных ошибок, а в finally — для закрытия потоков.
Похоже, с такой целью finally использовали так часто, что в Java 7 придумали расширенную форму try и назвали её try-with-resources.
Эффект сериала в рекламе
Mattel не просто создала рекламного персонажа — компания продумала мир, в котором живет Барби, и погрузила в него клиентов.
Аудитория видит своего рода сериал, который вызывает у нее эмоциональную привязанность. Например, сейчас Барби ведет свой блог — в YouTube выходят Shorts, на которых кукла танцует, участвует во флешмобах и показывает свою жизнь.
В основном через призму мира Барби Mattel рассказывает о новых моделях куклы, аксессуарах или доппродуктах. Вот Барби купила телефон. А вот дом, где она живет. А еще она создала танцевальное шоу.
Развивайте реальность рекламного персонажа. У Twix, например, продукт не менялся так кардинально — изменения происходили в мире рекламных персонажей.
Аудитория будет смотреть и досматривать рекламу, чтобы узнать, что нового произошло у персонажей, которых она полюбила. Итог — повышение узнаваемости бренда и вовлечение аудитории.
ВВЕДЕНИН В VEH.
В общем, векторная обработка исключений подобна SEH с тремя ключевыми отличиями:
- Обработчика не привязаны к определенной функции и стековому фрейму.
- Компилятор не имеет ключевых слов (типа try/catch) для добавления новых обработчиков в список обработчиков.
- Обработчики явно добавляются вашим кодом, а не являются плодом конструкции try/catch.
Новая API-функция AddVectoredExceptionHandler принимает указатель на функцию как аргумент и добавляет его в связанный список обработчиков. Так как система использует связанный список для хранения обработчиков, то программа может установить сколько угодно VEH-обработчиков.
Как VEH сосуществует с SEH? В WinXP, список VEH будет обработан перед списком SEH. Это сделано для совместимости с уже существующим кодом. Если бы VEH список обрабатывался после SEH, и SEH-обработчик мог обработать исключение, то VEH-обработчики не получили бы шанса заметить произошедшее исключение.
В отношении отладки, VEH работает подобно SEH. То есть, когда программа отлаживается, отладчик первым получает уведомление о произошедшем исключении. Если отладчик решает не обрабатывать исключение и передает его отлаживаемому процессу, то вызывается VEH-обработчик.
Прототип AddVectoredExceptionHandler можно найти в WINBASE.H:
Код (Text):
- WINBASEAPI PVOID WINAPI AddVectoredExceptionHandler(
- ULONG FirstHandler,
- PVECTORED_EXCEPTION_HANDLER VectoredHandler );
Первый параметр сообщает системе, должен ли обработчик помещен в начало связанного списка обработчиков, либо в его конец. Список обработчиков не привязан к конкретному потоку и глобален для всего процесса. Таким образом, вы можете запросить поместить обработчик в начало списка, но вы не можете гарантировать, что ваш обработчик будет вызван первым. Вы не будете первым, если другой участок кода вызовет AddVectoredExceptionHandler после вас и поместил обработчик в начало списка. Каждый раз, когда вызывается AddVectoredExceptionHandler, новый обработчик помещается либо в начало, либо в конец списка.
Второй параметр — адрес функции обработчика исключений. Вот его прототип:
Код (Text):
- LONG NTAPI VectoredExceptionHandler(PEXCEPTION_POINTERS);
PEXCEPTION_POINTERS — указатель, который дает функции полную информацию об исключении, включая тип исключения, адрес и значения регистров. Функция должна возвратить одно из значений: EXCEPTION_CONTINUE_SEARCH или EXCEPTION_CONTINUE_EXECUTION.
Если обработчик вернул EXCEPTION_CONTINUE_EXECUTION, система пытается перезапустить выполнение процесса. VEH-обработчики, расположенные дальше по списку, не вызываются. Также не вызываются и SEH-обработчики. Если же получен код возврата EXCEPTION_CONTINUE_SEARCH, система вызывает следующий VEH-обработчик. После того, как все VEH-обработчики будут вызваны, система начинает обход списка SEH.
В дополнение AddVectoredExceptionHandler, также существует RemoveVectoredExceptionHandler, которая удаляет предварительно установленный обработчик из списка. Это неинтересно, и здесь упоминается лишь для законченности.
2 ответа
5
Лучший ответ
В зависимости от этапа обработки, в котором вы хотите удалить неиспользуемое пространство, это может быть довольно просто. Например, при обработке фрагмента HTML вы можете просто удалить строку «& nbsp» из текстовых элементов:
13 май 2014, в 08:56
Поделиться
lxml.html может быть более подходящей для вас библиотекой, которая заменит » & nbsp» и другие HTML-теги на правильные символы.
17 март 2018, в 11:14
Поделиться
Ещё вопросы
- 1Java: независимая запись звука с 2 разных микрофонных входов
- 1Как я могу преобразовать обнуляемый TimeSpan в строку с определенным форматом?
- asp: текстовое содержимое ярлыка не отображается как
- Получить всю зарплату сотрудника из таблиц сотрудников с 3-й по величине зарплаты в MYSQL
- Правильный способ получения данных из многомерного массива
- Можно ли переопределить метод универсального класса в Java?
- преобразование pcloudXYZ в pcloudXYZRGB с использованием pcl 1.6
- php paypal pro (продвинутая) проблема интеграции
- 1Linq проблема со вставкой новых строк, которые имеют ссылки на существующие записи
- Настройте сервер AngularJS и NodeJS
- Laravel / Omnipay PayPal, передать пользовательскую сумму доставки
- Выберите последнюю запись столбца с group_by
- 1Как открыть конкретный экран после нажатия на уведомление?
- 1OpenCV / Python — Найти угловые координаты прямоугольника с рисунком в оттенках серого по серому изображению?
- 1Android — не удается обнаружить QR-код с библиотекой zxing
- Получить учетные данные базы данных из файла context.xml
- MySQL / Hibernate SQLQuery, как привести unsigned int (10) к smallint?
- Подсчет вхождений различных значений при возврате различных значений
- Проверка формы и отслеживание событий Analytics
- 1ASP.Net MVC длительный процесс
- Объединить результаты двух таблиц, имеющих разную структуру
- Angular 1.x, ES5 / ES6 и тестирование с Karma
- Как использовать jQuery и класс span?
- JQuery Dropdown с помощью JQuery Dummy
- 1Как: Сортировать элементы DataGrid
- Объединить 2 ассоциативных массива путем сопоставления значения подмассива?
- Управление конфликтом событий в родительско-дочернем div
- Выражение с участием модульных возведения в степень в C ++
- Риск запуска cronjob каждую минуту
- Создание анимированного макета 1-3 столбца с использованием Angular
- 1Генерация строки на основе регулярных выражений с RandExp
- Нет подходящей функции для вызова c ++
- 1Неоднозначный вызов Math.Round (int64 / int64, int)
- Cordova Hybrid App Design — Контроллеры
- Почему препроцессор пропускает файл, основываясь на его «модифицированной дате»?
- codeigniter извлекает таблицу mysql с where_in + сохраняет порядок массива ключей в массиве результатов
- 1SVG круговой путь анимации
- MySQLIntegrityConstraintViolationException не показывает имена столбцов в сообщении об исключении
- 1Сортировка вставок со строками
- Каковы отношения веб-фреймворков и других
- динамическое window.find не работает с jQuery
- 1Express.js — обернуть каждое промежуточное ПО / маршрут в «декоратор»
- 1Threejs применяет отсечение к определенной области объекта
- 1Преобразование даты в Java-приложении
- Получение углового контроллера через $ scope в модульном тесте
- нижний индекс std :: vector вне диапазона при чтении файла в вектор строк в C ++
- 1Android P фоновое ограничение для Firebase Cloud Messaging
- jQuery 1.6.2, jquery 1.10.2 и IE 8.0 — JQuery нулевой или не является объектом
- 1Приложение RCP + Xstream
- C ++ Неопределенная ссылка на функции