- Русские Блоги
- Вопросы инициализации управления Android-студией Android: сборка не проблема, но при запуске симулятора есть проблема. Код ошибки: Java.lang.runtimeexception: невозможно мгновенно
- ОБНОВЛЕНО: Android: java.lang.RuntimeException: не удалось запустить Activity ComponentInfo
- android java lang runtimeexception не удается подключиться к службе камеры
- 12 ответов
- Java lang runtimeexception что это
- Что это за ошибка java.lang.nullpointerexception
- Как исправить ошибку java.lang.nullpointerexception
- Для пользователей
- Для разработчиков
- try / catch / finally и исключения
- Исключение как явление
- Классификация исключений
- java.lang.Exception
- java.lang.RuntimeException
- java.lang.Error
- Инициация исключений
- Обработка исключений
- Перехват исключений, вызвавших завершение потока
- Конструкция try / catch / finally – тонкости
- Отсутствие транзакционности
Русские Блоги
Вопросы инициализации управления Android-студией Android: сборка не проблема, но при запуске симулятора есть проблема. Код ошибки: Java.lang.runtimeexception: невозможно мгновенно
При использовании Android Studio при запуске симулятора появляется следующая ошибка:
Информация в Logcat выглядит следующим образом:
java.lang.RuntimeException:Unable to instantiate activityComponentInfo
1. Невозможно создать экземпляр ActivityComponentinfo, перевод Baidu на: невозможно создать информацию о компонентах деятельности. Видно, что определенный класс имеет проблемы в создании возмещения.
2. Попытка вызвать VirtualMethod ‘android.content.res.resources android.content.context.getresources ()’ На ссылке на нулевой объект, перевод Baidu на: попытаться вызвать виртуальные методы на пустых ссылках на объект «android.cord.res. Realthaddio.calth.calist.getrealscues () «. Это означает, что мы не можем использовать NULL (пустой) объект, и нет объекта назначения «Android.cord.res.Realthdio.calth.calist.ruealthdio.calth.calist.getrealscusts ()», но странно, я никогда не использовал этот метод., Используйте поиск Baidu, нечего найти
3. В это время вы должны установить и пустые объекты от объекта. Поскольку мой проект только что установлен, нет много новых, это удобнее. Новый код составляет всего 2 строки:
В создании TextView укажите его параметр, и в среде Android Studio3 она автоматически добавит контекст: я пытаюсь «= новый текстовый просмотр»; «Эта часть прокомментировала, как и изображение инициализируется, и результат может быть запущен Отказ
Резюме: Это не хочет писать резюме, потому что нет фундаментальной причины, просто найдите временное решение, но в духе написания статьи, по-прежнему написали это предложение.
Источник
ОБНОВЛЕНО: Android: java.lang.RuntimeException: не удалось запустить Activity ComponentInfo
UPDATE **, поэтому я сделал почти все, что было сказано ниже, и до сих пор получил эту ошибку (см. Новый файл logcat). Его разные, хотя я не знаю, как это исправить. ** Хорошо, поэтому я начинаю, поэтому я действительно не знаю, что происходит. Когда я пытаюсь запустить это приложение в эмуляторе, все это «к сожалению, это приложение остановилось». Я ищу все вопросы, подобные этому, но не смог найти ответ. Кстати, это не готовое приложение или даже даже началось, но я хочу запустить его, прежде чем продолжить. Heres the log cat file thing.
Теперь heres activty_main.xml
Затем вот файл mainActivity.java
То второе действие DisplayMessageActivity.java
И, наконец, файл mainfest
Так оно и есть. Кто-то, пожалуйста, помогите спасибо!
Я заметил одно: вы не указали правильные значения id в некоторых своих xml.
И как мудрый для ваших других деклараций id.
Вы заметите, что в вашей трассе стека он дает номер строки в вашем xml для определения местоположения ошибки.
Это может быть что-то другое. Но по существу у вас плохо сформировался xml.
Ошибка 2
Вам нужно просмотреть трассировку стека назад, чтобы найти источник вашей ошибки, тогда вы, скорее всего, найдете решение самостоятельно.
Сверху вниз вы попадете на строку MainActivity.oncreateOptionsMenu () Выше того, что вы увидите, что она пытается раздуть (ваше меню опций xml), то есть loadXmlResourceParser ()
Это не значит, что вы указываете номер строки xml, но он говорит вам, что проблема с идентификатором ресурса недействительна.
Вам нужно будет опубликовать свои варианты xml в своем вопросе, если вы хотите получить ответ. Но я посмотрю, сможешь ли ты сначала разобраться с этим. Попробуйте прокомментировать элементы и верните их, чтобы посмотреть, что сломано. Я говорю это, потому что на вопрос должен ответить только один вопрос о переполнении стека.
Есть проблемы с вашим XML – вы можете сказать по строке:
Одна вещь, которую я заметил, это то, что, когда вы объявляете атрибут android: id, он должен иметь + в нем, например:
Это связано с тем, что вы создаете идентификатор, а не только для ранее существовавшего, определенного в другом месте (например, вы можете иметь строку, например, «@ string / hello» может находиться в папке значений).
В объявлении для одного из ваших TextViews вас есть:
textSize должен быть числом или размером, например:
Источник
android java lang runtimeexception не удается подключиться к службе камеры
в настоящее время я работаю над включением/выключением фонарика. Я получаю эту ошибку java.lang.RuntimeException: Fail to connect to camera service Я не знаю, почему эта ошибка возникает. Я ссылался на многие решения, но моя проблема все еще не была решена. Когда фонарик включен, ошибка не возникает, но когда фонарик выключен, то возникает ошибка.
Код Основной Код.
мое явное разрешение:
12 ответов
объявить его сверху.
У меня была та же проблема, что ни один из ответов здесь не решен, поэтому после ее решения я добавляю свой способ ее решения. Это относится к новым версиям android, которые поддерживают настройку разрешений для каждого приложения (начиная с Marshmallow, 6.0). Разрешение для камеры может быть отключено и должно быть включено в настройках приложения. Настройки — > Приложения — > [Ваше Приложение] — > Разрешения
Я также видел эту ошибку:
java.ленг.RuntimeException: не удается подключиться к службе камеры
экспериментируя с фонариком. Оказывается, я был немного небрежен с моими разрешениями и скопировал их в тело блока приложения в манифесте.XML-файл. Поэтому вам действительно нужно подчиняться синтаксису, как описано в:
в противном случае приложение не будет работать с сбоем подключения службы на камере.открытый призыв. Это должно выглядеть так, основываясь на ваших разрешениях в вопросе:
убедитесь, что ваши разрешения и список функций содержатся только в разделе манифеста, а не похоронены в разделе приложения!
эта проблема может возникнуть в Android 6.0 если вы не включили разрешение камеры для вашего приложения. Начиная с Android 6.0 вы можете обрабатывать разрешение приложения Погода вы дадите или не конкретное разрешение для приложения.
Итак, вам нужно включить разрешение settings->apps->your_app->enable camera permission если он еще не включен.
Если ваша версия ОС 6.0 или более поздней версии попробуйте это, надеюсь, это поможет.
если вы попытаетесь открыть камеру с помощью cameraID, который не существует, вы получите ту же ошибку (java.ленг.RuntimeException: не удается подключиться к службе камеры)
посмотреть код в этом блоке
вызов release() чтобы освободить камеры для использования другими приложениями. Приложения должны немедленно освободить камеру в onPause() (и повторно открыть () его в onResume().
в приведенном выше коде сразу после выпуска вы помещаете null в камера
Привет я надеюсь, что вы имеете дело с факелом своего рода приложение или что-то, связанное с flash, и было много дискуссий пошли на это раньше, и вот некоторые полезные ссылки и учебники для достижения вашей потребности, пожалуйста, пройти через них надеюсь, что они могут помочь вам
простой ответ, который я могу найти на эту проблему, заключается в том, что я не просил разрешения камеры для пользователя, и поэтому по умолчанию разрешение камеры не было доступно для моего приложения на устройствах Marshmallow. Я просто добавил проверку разрешений для камеры перед запуском камеры, и все работает нормально.
попробуйте использовать эту строку, когда вы выходите из приложения:
Я только что получил код приложения фонарик откуда-то. Он использовал System.exit(0) закрыть приложение. Я убрал его, зная, что это не лучшая практика. Затем я начал получать эти ошибки. Я попробовал решение принятого ответа, но затем я начал получать некоторые другие ошибки. Поэтому, вместо того, чтобы решать их, я просто положил это System.exit(0) линия спины. И он начал работать нормально. Я знаю, что это не очень хороший способ, но для небольшого приложения для фонарика вы можете попробовать это быстрое решение.
Если весь ваш код в порядке, вы должны проверить, есть ли какое-либо другое приложение с помощью камеры. Затем вы должны закрыть другое приложение, которое в настоящее время использует вашу камеру.
вам нужно stopPreview() и release() Как только вы вернулись с камеры, так что другое приложение может получить к нему доступ. Сделайте класс» Camera » статическим и назовите его null на onPause() . Это решает мою проблему.
в моем Android peoject имеет ту же проблему. Это моя ошибка Logcat
03-29 19:26:04.194 224-608/? V / EmulatedCamera_BaseCamera: getCameraInfo 03-29 19:26: 04.196 224-224/? I / CameraService: CameraService:: подключение вызова (PID -1 «com.proitzen.staffapp», ID камеры 1) для версии по умолчанию HAL и версии API камеры 1 03-29 19: 26:04.196 224-224/? W / ServiceManager: ошибка разрешения: андроид.разрешение.Камера от uid=10067 pid=1776 03-29 19: 26: 04.196 224-224/? E / CameraService: отказ в разрешении: невозможно использовать камеру pid=1776, uid=10067 03-29 19:26:04.196 1776-1776/com.proitzen.staffapp W / CameraBase: произошла ошибка при подключении к камере 1: сервис недоступно 03-29 19: 26: 04.200 1776-1776 / com.proitzen.staffapp D / AndroidRuntime: завершение работы VM
никакие вышеуказанные решения не работали для меня. Мое приложение для android работало на физических устройствах android и давало вышеуказанную ошибку только в Как Genymotion.
решение: запустите эмулятор Genumotion Настройки — > приложения — — — > выберите приложение — > разрешения — > включить камеру и микрофон и хранение.
Источник
Java lang runtimeexception что это
Ошибка может возникать на Windows XP, из-за отсутствия нужных библиотек для Java.
Необходимо установить на компьютер Microsoft Visual C++ 2010 Redistributable Package. Ссылка для скачивания: https://www.microsoft.com/ru-RU/download/details.aspx? >
Если Ваша проблема остаётся актуальной, запросите поддержку у TLauncher:
Ряд пользователей (да и разработчиков) программных продуктов на языке Java могут столкнуться с ошибкой java.lang.nullpointerexception (сокращённо NPE), при возникновении которой запущенная программа прекращает свою работу. Обычно это связано с некорректно написанным телом какой-либо программы на Java, требуя от разработчиков соответствующих действий для исправления проблемы. В этом материале я расскажу, что это за ошибка, какова её специфика, а также поясню, как исправить ошибку java.lang.nullpointerexception.
Скриншот ошибки NPE
Что это за ошибка java.lang.nullpointerexception
Появление данной ошибки знаменует собой ситуацию, при которой разработчик программы пытается вызвать метод по нулевой ссылке на объект. В тексте сообщения об ошибке система обычно указывает stack trace и номер строки, в которой возникла ошибка, по которым проблему будет легко отследить.
Номер строки с ошибкой
Что в отношении обычных пользователей, то появление ошибки java.lang.nullpointerexception у вас на ПК сигнализирует, что у вас что-то не так с функционалом пакетом Java на вашем компьютере, или что программа (или онлайн-приложение), работающие на Java, функционируют не совсем корректно. Если у вас возникает проблема, при которой Java апплет не загружен, рекомендую изучить материал по ссылке.
Как исправить ошибку java.lang.nullpointerexception
Как избавиться от ошибки java.lang.nullpointerexception? Способы борьбы с проблемой можно разделить на две основные группы – для пользователей и для разработчиков.
Для пользователей
Если вы встретились с данной ошибкой во время запуска (или работы) какой-либо программы (особенно это касается java.lang.nullpointerexception minecraft), то рекомендую выполнить следующее:
- Переустановите пакет Java на своём компьютере. Скачать пакет можно, к примеру, вот отсюда;
- Переустановите саму проблемную программу (или удалите проблемное обновление, если ошибка начала появляться после такового);
- Напишите письмо в техническую поддержку программы (или ресурса) с подробным описанием проблемы и ждите ответа, возможно, разработчики скоро пофиксят баг.
- Также, в случае проблем в работе игры Майнкрафт, некоторым пользователям помогло создание новой учётной записи с административными правами, и запуск игры от её имени.
Java ошибка в Майнкрафт
Для разработчиков
Разработчикам стоит обратить внимание на следующее:
- Вызывайте методы equals(), а также equalsIgnoreCase() в известной строке литерала, и избегайте вызова данных методов у неизвестного объекта;
- Вместо toString() используйте valueOf() в ситуации, когда результат равнозначен;
- Применяйте null-безопасные библиотеки и методы;
- Старайтесь избегать возвращения null из метода, лучше возвращайте пустую коллекцию;
- Применяйте аннотации @Nullable и @NotNull;
- Не нужно лишней автоупаковки и автораспаковки в создаваемом вами коде, что приводит к созданию ненужных временных объектов;
- Регламентируйте границы на уровне СУБД;
- Правильно объявляйте соглашения о кодировании и выполняйте их.
Последнее изменение: 28 октября 2007г.
try / catch / finally и исключения
Думаю, вряд ли найдется Java-разработчик, который хотя бы не слышал об исключениях. В принципе, они не являются исключительным свойством Java, есть они и в Delphi, и в C++. Однако в Java исключения используются особенно широко. И чаще всего с ними связано немало ошибок. Основная цель этой статьи – систематизация информации об исключениях, их обработке и т.п. А именно:
Исключение как явление
Что такое вообще исключение? Это сигнал о нестандартной – исключительной – ситуации. Ситуации могут быть самые различные – ожидаемые или нет, разной степени критичности. И относиться к этим ситуациям, естественно, приходится по-разному.
Как и всё в Java, исключения тоже представленны в виде классов. Корнем иерархии служит класс java.lang.Throwable , дословно – «бросаемый». Его прямыми наследниками являются java.lang.Exception и java.lang.Error, от которых и унаследованы все остальные исключения. И от которых рекомендуется наследовать собственные.
Хочу подчеркнуть, что исключения не есть нечто из ряда вон выходящее. Это нормальный механизм. Потому не стоит стараться избегать их использования любой ценой. И тем более не стоит стараться избегать исключений в конструкторах, к чему склонны разработчики, хорошо знакомые с С++. Ввиду наличия сборщика мусора утечек памяти в этом случае не будет. Разве что очень постараться, я имею в виду намеренно.
Теперь рассмотрим типы исключений ближе.
Классификация исключений
Как я уже упоминал, есть два «базовых» типа исключений – java.lang.Exception и java.lang.Error. Я бы сказал, что различаются степенью критичности. Не, разумеется, оба типа могут быть перехвачены, ибо перехватывается исключение начиная с уровня java.lang.Throwable . Это разделение скорее логическое. Если произошло что-то серьезное – не найден метод, который надо вызвать, закончилась память, переполнение стека, в общем, что-то, после чего восстановить нормальную работу уже вряд ли реально – это ошибка, java.lang.Error. Если продолжение работы теоретически возможно – это исключение, java.lang.Exception.
Кроме уже упомянутых двух типов существует также еще один класс, являющийся существенным – java.lang.RuntimeException. Он унаследован от java.lang.Exception и является корнем для всех исключений времени выполнения – т.е. возникающих при работе виртуальной машины. Нулевые ссылки, деление на ноль, неверное значение аргумента, выход за пределы массивы и т.п. – все это исключительные ситуации времени выполнения. Чем они отличаются от обычных, мы рассмотрим ниже.
Поскольку исключения – точно такие же классы, в них можно включать и собственные переменные, и даже какую-то логику. Увлекаться, правда, не стоит. Дело в том, что исключение – класс все-таки выделенный. При создании Throwable существуют большие накладные расходы – заполнение стека вызова. Это достаточно длительная процедура. И потому создавать исключение просто так – себе дороже. Его нужно создавать только тогда, когда без него не обойтись, когда оно точно будет выброшено. Проще это делать сразу вместе с директивой throw .
А вот держать в классе исключения какую-то информацию, которая позволит его обработать – вполне допустимо. Передавать эту информацию лучше через конструктор.
Итак, приступим к более подробному рассмотрению. Первый базовый тип –
java.lang.Exception
Исключения этого типа я бы охарактерировал так – они возникают в ситуациях, которые нам неподконтрольны. Скажем, десериализуем мы класс, а данные в неверном формате. И мы с этим ничего не можем сделать, кроме как адекватно отреагировать.
Любое исключение типа java.lang.Exception должно быть обработано. Это закон. За его исполнением следит компилятор. Если исключение не обработано в методе – оно должно быть декларировано в его сигнатуре и в этом случае обработано выше. Или еще выше. Но обработано оно будет. Единственное исключение – это java.lang.RuntimeException, о котором мы поговорим дальше.
Метод может декларировать любое количестко исключений. Нет, любое – это, наверное, слишком сильно сказано. Если мне не изменяет память, количество исключений ограничено 64K – 65536 штук. Для меня это уже означает, что я могу декларировать столько исключений, сколько мне заблагорассудится.
java.lang.RuntimeException
Не знаю, насколько со мной согласятся, но я бы охарактеризовал этит тип так: java.lang.RuntimeException – это ошибки разработчика . Неверное состояние монитора, деление на ноль, неверный аргумент, нулевая ссылка, выход за границы массива, неверное состояние класса – все это можно предусмотреть и предупредить. Еще раз полностью просмотрев всю иерархию исключений времени выполнения, я не нашел ни одного, которого нельзя было бы избежать какой-нибудь проверкой.
Поскольку ожидать ошибок – глупо, исключения типа java.lang.RuntimeException не декларируются. Компилятор это допускает, соответственно, позволяя их не обрабатывать. Более того, я бы сказал, что ловить java.lang.RuntimeException – дурной тон, ибо вместо того, чтобы устранять причину, мы нейстрализуем последствия. И хуже всего то, что ошибки разработчика устранить во время выполнения практически нереально, фактически, они по степени критичности приближены к java.lang.Error.
Перейдем теперь к последнему типу –
java.lang.Error
Как я уже упоминал, это критические ошибки, после которых восстановить нормальную работу практически нереально. В самом деле – ну что сделаешь при переполнении стека? Или если не найден метод? Или если вызван абстрактный метод? Или в случае ошибки в байт-коде класса? Абсолютно ничего. По крайней мере, без серьезного вмешательства человека, который может заменить библиотеку, например. Или поменять classpath .
В некоторых случаях ситуация не столь критична. Скажем, нехватка памяти, вызывающая java.lang.OutOfMemoryError . Если эта ошибка произошла в момент выделения большого объема памяти – например, при создании массива, – ее можно перехватить и попытаться выделить память в меньших объемах, изменив каким-то образом алгоритм, который будет эту память использовать.
Или, скажем, в случае, когда не JVM поддерживает системную кодировку – при попытке создать InputStreamReader без указания кодировки будет выброшена ошибка. Однако нужна ли нам системная кодировка и насколько для нас критично ее отсутствие – решать нам.
Как и в случае с java.lang.RuntimeException компилятор разрешает не декларировать и не обрабатывать ошибки из иерархии java.lang.Error . Перехватывать их или нет – решать вам. Зависит от того, можете ли вы предложить приемлемый алгоритм для восстановления.
С классификацией закончили, переходим к следующему вопросу.
Инициация исключений
А вопрос следующий – что и когда бросать.
Представим себе, что у вас создалась исключительная ситуация и работать код дальше не может. Какой именно тип исключения использовать?
Тут самое время воспользоваться характеристиками исключений, приведенными выше. Если возникшая исключительная ситуация такова, что дальнейшая работа невозможна в принципе – можно бросить исключение из иерархии java.lang.Error. Хотя у меня лично таких ситуаций не было в практике. Если исключительная ситуация возникла по вине внешних обстоятельств или пользователя приложения – не те данные дали, например, – то это случай, когда ошибки должны быть обработаны, следовательно, лучше всего использовать java.lang.Exception. Если же ситуация возникла по вине разработчика – например, передали вам в качестве параметра null , при том что в javadoc вы английским по белому написали, что этого делать нельзя – тогда это java.lang.RuntimeException.
При написании бизнес-логики – в особенности это касается библиотек – часто бывает полезным создать собственный тип исключения. Просто для того, чтобы дать возможность обрабатывать ваши исключения отдельно от остальных. Подробнее об обработке – в следующем разделе.
Пара слов насчет приведенного примера – null в качестве параметра. Теоретически в этой ситуации можно бросить два исключения – NullPointerException и IllegalArgumentException . Нескотря на кажущуюся очевидность выбора я лично предпочитаю второй вариант. На мой взгляд NullPointerException должна бросать исключительно виртуальная машина. Если же я сам проверил значение и убедился, что оно равно null , а этого быть не должно – гораздо более информативно использовать IllegalArgumentException , если это значение аргумента, или же IllegalStateException – если это значение члена класса.
Ну ладно, что бросить именно – это мы как-нибудь определим. Но иногда возникает какое-то иррациональное желание не только бросить исключение, но и как-то его конкретизировать, указав причину. Не, можно, конечно, и по исключению на каждую ошибку создать, но сойти с ума намного проще и быстрее.
Первый вариант, который видится – текстовое сообщение. Практически у любого класса исключения есть конструктор, принимающий в качестве параметра текст. Именно этот текст фигурирует в консоли при печати сообщения об исключени, его же можно получить через getMessage() . Это позлезно, когда ошибку обнаруживаем мы сами. А что делать, когда ошибка для нас тоже «внешняя», скажем – мы поймали исключение, брошенное глубже?
В этом случае может выручить механизм т.н. exception chaining – связывания исключений. Практически у каждого класса исключения есть конструктор, принимающий в качестве параметра Throwable – причину исключительной ситуации. Если же такого конструктора нет – у все того же Throwable , от которого унаследованы все исключения, есть метод initCause(Throwable) , который можно вызвать ровно один раз. И передать ему исключение, явившееся причиной того, что было инициировано следующее исключение.
Зачем это нужно. Дело в том, что хорошо спроектированный код – он как черный ящик. У него есть свои интерфейсы, определенное поведение, набор исключительных ситуаций, наконец. А что происходит внутри – это не играет роли для того, что находится снаружи. Более того – иногда может сыграть и обратный эффект. Причин для ошибки может быть добрый десяток, и ловить их все отдельно и так же обрабатывать. Чаще всего просто не нужно. Именно потому проще определить, например, свое исключение (ну или использовать имеющееся, не суть важно) и бросить именно его, указав как причину то, которое мы поймали. И волки сыты, и пользователям кода работы меньше.
Ну вот, от инициации исключений мы плавно переходим к их обработке.
Обработка исключений
Казалось бы, чего проще? Написал catch(Throwable th) – и всё. Однако именно от этого я их хочу предостеречь.
Во-первых, как я уже говорил выше, ловить исключения времени выполнения – дурной тон. Они свидетельствуют об ошибках. Ловить java.lang.Error или производные стоит только если вы точно знаете, что делаете. Восстановление после таких ошибок не всегда возможно и почти всегда нетривиально.
Во-вторых – как именно обрабатывать? Я об этом подробно писал в статье о качестве кода, раздел Обработка исключений, но повторюсь. По каждому пойманому исключению необходимо принимать решение. Просто проглотить его или вывести в консоль – самое неприятное, что можно придумать. А этим грешат, к сожалению, многие. Человек читает XML из файла, получает исключение, глотает его – и пытается дальше работать с этим XML так, как будто ничего не произошло. Естественно получает NullPointerException , поскольку класс, который он использует, не инициализировался. Ошибка разработчика, хотя и не столь очевидная.
Почему я говорил о том, что стоит заводить свои типы исключений – так вы проще сможете их выделить на стадии обработки. Представьте себе, что существуют пять причин, по которым может быть выброшено исключение, и во всех пяти случаях бросается java.lang.Exception . Вы же спятите разбираться, чем именно это исключение вызвано. А если это будет пять разных типов – тут уже проще простого. На каждый – свой блок catch .
И третье – что делать с иерархиями исключений. Пусть у вас метод может выбросить как IOException , так и Exception . Так вот, совершенно не все равно, в каком порядке будут стоять блоки catch , поскольку они обрабатываются ровно в той последовательности, как объявлены. И если первым будет catch(Exception ex) – до второго ( catch(IOException ioex) ) управление просто не дойдет. Компилятор об этом, конечно, предупредит, более того – это считается ошибкой. Тем не менее об этом стоит помнить.
Следующее, чего бы я хотел коснуться –
Перехват исключений, вызвавших завершение потока
При использовании нескольких потоков бывают ситуации, когда надо знать, как поток завершился. В смысле – если это произошло из-за исключения, то из-за какого именно. Для этой цели начиная с версии Java 5 существует специальный интерфейс – Thread.UncaughtExceptionHandler . Его реализацию можно установить нужному потоку с помощью метода setUncaughtExceptionHandler . Можно также установить обработчик по умолчанию с помощью статического метода Thread.setDefaultUncaughtExceptionHandler .
Интерфейс Thread.UncaughtExceptionHandler имеет один единственный метод – uncaughtException(Thread t, Throwable e) – в который передается экземпляр потока, завершившегося исключением, и экземпляр самого исключения. Восстановить работу потока, естественно, уже не удастся, но зафиксировать факт его ненормального завершения таким образом можно.
Следующее, о чем я хотел бы поговорить – сама конструкция try / catch / finally .
Конструкция try / catch / finally – тонкости
С блоком try , думаю, вопросов не возникает. С блоком catch – надеюсь, уже тоже нет. Остается блок finally . Что это, и с чем его едят?
Блок finally идет в самом конце конструкции try / catch / finally . Ключевая его особенность в том, что он выполняется всегда, вне зависимости от того, сработал catch или нет.
Зачем это нужно. Посмотрите вот на этот фрагмент кода:
Казалось бы все в порядке. А что будет, если, например, при вызове rs.first() произойдет исключение? Да, оно обработается. Однако ни ResultSet , ни Statement , ни Connection закрыты не будут. Последствия весьма печальны – исчерпание открытых курсоров, соединений в пуле и т.п.
Можно, конечно, поместить этот же код и в блок catch . Однако дублировать код – не лучшая идея. Правильнее вынести код закрытия в блок finally , в этом случае он будет исполнен как в случае возникновения исключения, так и в случае, когда этого не происходит.
Рассмотрим еще один пример:
Вопрос на засыпку – каков будет результат? Выполняем тест и получаем:
Т.е. в обоих случаях результат будет одинаковый, причем не тот, которого можно было бы ожидать! Почему так происходит? В первом случае – из блока try должно вернуться значение 6 – длина переданной строки. Однако выполняется блок finally , в котором возвращается 0. В результате исходное значение теряется. Во втором случае – попытка вызвать toString() при переданном значении null приведет к исключению – NullPointerException . Это исключение будет перехвачено, т.к. является наследником Exception . Из блока catch должно вернуться значение -1, однако выполняется блок finally и возвращается опять-таки 0, а -1 – теряется!
Точно так же блок finally может вызвать потерю исключений. Посмотрите вот на этот пример:
Этот тест очень часто давался на интервью. И правильно отвечали единицы. Между тем – результатом его выполнения будет вывод в консоль b. И только. После инициации первого исключения – new Exception(«a») – будет выполнен блок finally , в котором будет брошено исключение new IOException(«b») . И именно это исключение будет поймано и обработано. Исходное же исключение теряется.
Хотелось бы затронуть еще один момент. В каких комбинациях могут существовать блоки try , catch и finally ? Понятно, что try – обязателен. Он может быть совместно с catch , либо с catch и finally одновременно. Отдельно try не используется. А есть ли еще варианты?
Есть. try может быть в паре с finally , без catch . Работает это точно так же – после выхода из блока try выполняется блок finally . Это может быть полезно, например, в следующей ситуации. При выходе из метода вам надо произвести какое-либо действие. А return в этом методе стоит в нескольких местах. Писать одинаковый код перед каждым return нецелесообразно. Гораздо проще и эффективнее поместить основной код в try , а код, выполняемый при выходе – в finally .
И последняя тема –
Отсутствие транзакционности
В самом начале я упоминал о том, что организовать утечку памяти при использовании исключений в конструкторах сложно. На самом деле – можно. Смотрим на пример.
Итак, что тут происходит. В конструкторе мы присваиваем ссылку на созданный объект статической переменной. Дальше мы инициализируем одно поле и. бросаем исключение. Я это делаю намеренно, однако это может произойти и в результате выполнения кода конструктора. В методе main это исключение обрабатывается. Однако ссылка на объект – существует! В чем можно убедиться, выполнив приведенный код:
Переменная метода main равна null , как и положено. А вот статическая переменная self – нет. Через нее можно получить доступ к объекту, инициализация которого была прервана исключением. И объект этот, естественно, в неверном состоянии. Вот она – утечка памяти. Объект не будет удален до тех пор, пока на него есть ссылка.
Пример этот искуственный, но лишь до известной степени. Он говорит об очень важной особенности исключений:
Cвойством транзакционности исключения не обладают – действия, произведенные в блоке try до возникновения исключения, не отменяются поcле его возникновения.
И это необходимо учитывать. Применительно к приведенному примеру – стоит все операции, могущие привести к исключению, выполнять как можно раньше. Например, проверять переданные параметры сразу же. В некоторых случаях для отмены уже произведенных действий может пригодиться блок finally . А если очень надо где-то сохранить ссылку на создаваемый объект, причем сделать это необходимо в конструкторе – лучше всего оставить это напоследок, когда весь критический код уже выполнен.
Ну, вот и все. Думаю, большая часть этого материала вам была знакома. Во всяком случае, надеюсь на это. Моей целью было просто упорядочить информацию для тех, кто с исключениями пока еще знаком поверхностно. Всем спасибо!
Источник