Здесь тысячи людей, спасибо, что увидели этот момент. Надеюсь, моя статья будет вам полезна!
Сохрани свою любовь и отправляйся в горы и моря в грядущие дни!
Обработка исключений Java
😍Предисловие
Я полагаю, что у вас будут некоторые ошибки-исключения более или менее при использовании Java, так откуда же берутся эти исключения?
Исключения — это некоторые ошибки в программе, но не все ошибки являются исключениями, и иногда ошибок можно избежать. Фактически, в Java исключение — это механизм согласованности, предоставляемый Java для выявления ошибок и реагирования на них. Таким образом, код обработки исключений в программе может быть отделен от обычного бизнес-кода, что обеспечивает более элегантный программный код и повышает надежность программы.
😀1. Что такое исключение?
Ненормальный значит ненормальный. А в жизни: врач сказал, что в какой-то части вашего тела есть аномалия, эта часть немного отличается от нормальной, и функция этой части будет нарушена. В программе это означает:
-
аномальный: Относится к ненормальной ситуации, возникающей во время выполнения программы, которая в конечном итоге приведет к аварийной остановке JVM.
-
исключение не означаетГрамматические ошибки, Неправильный синтаксис, компиляция не удалась, файл байт-кода не будет сгенерирован, и его вообще нельзя запустить.
-
В объектно-ориентированных языках программирования, таких как Java, само исключение является классом, а генерация исключения заключается в создании объекта исключения и выдаче объекта исключения.
-
Java разработал набор исключениймеханизм обработки исключений, когда во время работы программы возникают какие-то ненормальные условия, программа не возвращает никакого значения, а генерирует объект исключения, который инкапсулирует информацию об ошибке. Это делает программный код более элегантным и повышает надежность программы.
Зачем создавать исключения? Во-первых, после введения исключений мы можем отделить код ошибки от нормального кода для отдельной обработки, что делает код чище; во-вторых, когда есть какие-то особые случаи, мы также можем выкинуть проверенное исключение, чтобы сообщить вызывающей стороне, что пусть они обрабатывают ее. .
😄2. Ненормальная система
-
Давайте сначала посмотрим на архитектуру исключений:
-
Вы можете увидеть общие отношения наследования классов исключений.Конечно, на приведенном выше рисунке показаны не все исключения, и есть много подклассов, которые не перечислены.Здесь наиболее часто используемые классы исключений перечислены первыми. Конечно, пользователь также может настроить реализацию исключения.
📫2.1 Метательный
Все исключения наследуются от Throwable, суперкласса всех ошибок и исключений. Throwable содержит моментальный снимок стека выполнения потока при его создании и предоставляет интерфейсы, такие как printStackTrace(), для получения данных трассировки стека и другой информации.
- Система Throwable содержит два подкласса, Error (ошибка) и Exception (ненормальное), которые обычно используются для указания на возникновение нештатной ситуации. Оба являются важными подклассами обработки исключений Java, и каждый из них содержит большое количество подклассов.
📪2.2 Ошибка
- определение: класс ошибок и его подклассы. Ошибка, которую программа не может обработать, указывающая на серьезную ошибку при запуске приложения. Большинство ошибок не имеют ничего общего с действиями автора кода, а представляют собой проблему с JVM во время выполнения кода.
-
Функции: все ошибки времени компиляции и системные ошибки выбрасываются через Error. Эти ошибки указывают на то, что сбой произошел в самой виртуальной машине или когда виртуальная машина пыталась выполнить приложение. обычно нравится
Virtual MachineError
(Ошибка запуска виртуальной машины) и т. д. Происходит, когда у JVM больше нет ресурсов памяти для продолжения операции.OutOfMemoryError
(нет ошибок памяти) иStackOverflowError
(ошибка переполнения стека) и т. д. Когда возникают эти исключения, JVM обычно выбираетпоток завершен. - Уведомление: эти ошибки являются непроверенными исключениями, ошибками, не связанными с кодированием, и непроверенными. Потому что они находятся вне контроля и вычислительной мощности приложения, и большинство из них не разрешены во время работы программы. В хорошо спроектированном приложении, даже если ошибка действительно возникает, не должно быть встроенной попытки справиться с ненормальным состоянием, которое она вызывает. Поэтому при возникновении таких ошибок приложения не должны обрабатывать такие ошибки.
📬2.3 Исключение
Exception — еще один очень важный подкласс исключений. Исключение, которое может поймать и обработать сама программа. Как только возникает такое исключение, мы должны исправить код и исправить программу. Исключения делятся на две категории: исключения времени выполнения и исключения времени компиляции.
🔎2.3.1исключение времени выполнения
-
определение:
RuntimeException
исключения класса и его подкласса, такие какNullPointerException
(исключение нулевого указателя),IndexOutOfBoundsException
(исключение нижнего индекса за пределами границ) и т. д., указывающие на возможные исключения JVM во время работы. -
Функции: этот тип исключения, который компилятор Java не проверяет, является непроверенным исключением. Обычно вызванные логическими ошибками программы, такие программы должны максимально избегать возникновения таких исключений с логической точки зрения. И когда такого рода исключение может возникнуть в программе, даже если это не полезно
try-catch
заявление, чтобы захватить его, также не работаетthrows
Объявление предложения выбрасывает его, и оно компилируется. В программе можно выбрать захват обработки, или нет. Если возникает исключение во время выполнения, вам необходимо изменить код, чтобы избежать его. Например, если происходит деление на ноль, вам нужен код, чтобы этого избежать! -
Уведомление: Исключения RuntimeException автоматически генерируются и автоматически перехватываются JVM (Даже если мы не напишем оператор перехвата исключения, среда выполнения выдаст ошибку! ! ), подавляющее большинство таких исключений — это проблемы с самим кодом, которые следует решать логически и улучшать код.
Вот, давайте посмотрим, как выглядит исключение во время выполнения. Здесь я хочу сказать, что если есть исключение, не нервничайте, скопируйте простое имя класса исключения в API для проверки. Тогда смотри, что ненормально.
Видно, что в логике нашей программы есть ошибка, поэтому возникает арифметическое исключение. Нам нужно только изменить int b = 10, иначе b не равно 0.
Так что нам не нужно беспокоиться об исключениях. Вы можете начать с просмотра имени класса исключений, посмотреть, что это за исключение, понять, в чем причина, найти неправильное место в нашей программе и изменить его для нормальной работы.
-
Тогда мы ни с чем не разобрались.Когда возникает исключение, кто его обрабатывает?
Это обработка JVM по умолчанию: имя, причина, местоположение и другая информация об исключении выводятся на консоль, но программа не может продолжать выполняться.
🔎2.3.2 Исключение, не связанное с выполнением (исключение времени компиляции)
-
определение: Исключения в Exception, отличные от RuntimeException и его подклассов.
-
Функции: такое исключение, компилятор Java проверяет его. Если такое исключение возникает в программе, это исключение, которое необходимо обрабатывать с точки зрения синтаксиса программы. Например: ClassNotFoundException (исключение указанного класса не найдено), IOException (исключение потока ввода-вывода) или через
throws
сделать заявление броском, либо с помощьюtry-catch
Обработка захвата, иначе он не может пройти компиляцию. -
Уведомление: В программе мы обычно не настраиваем этот тип исключения, а напрямую используем класс исключения, предоставленный системой.Это исключение мы должны вручную добавить оператор catch в код для обработки исключения.
Как видно из комментариев,
createNewFile()
Метод обрабатывает исключение IOException, а исключение IOException наследуется от Exception, которое не является исключением времени выполнения, поэтому исключение необходимо обрабатывать.Следовательно, если у нас есть исключение времени компиляции, во время компиляции будет сообщено об ошибке, и это исключение необходимо обработать, иначе программа не сможет быть скомпилирована.
📭2.4 Проверенные и непроверенные исключения
Как правило, исключение Java (Throwable) делится напроверенное исключение(проверенные исключения) инепроверенное исключение(непроверенные исключения).
💡2.4.1 Проверенные исключения
Компилятору требуются исключения, которые необходимо обрабатывать.
-
В процессе работы правильной программы она часто подвержена нештатным ситуациям, которые оправдывают ожидания. Как только возникает такое исключение, его необходимо каким-то образом обработать.КромеЗа исключением RuntimeException и его подклассов в Exception, все другие классы Exception и их подклассы, то есть исключения, не относящиеся к среде выполнения, являются проверенными исключениями.
-
Этот компилятор исключений проверит его, а это значит, что когда компилятор обнаружит, что где-то в приложении может быть такое исключение, он предложит вам обработать исключение — либо использовать try-catch для его перехвата, либо использовать в методе Сигнатура Throw с ключевым словом throws, иначе компиляция завершится ошибкой.
💡2.4.2 Неотмеченные исключения
Компилятор не проверяет и не требует исключений, которые необходимо обрабатывать.
- Такие исключения, когда такие исключения возникают в программе, даже если мы не
try-catch
поймать его, ни использоватьthrows
Если выброшено это исключение, компиляция пройдет нормально. Этот класс исключений включает исключения времени выполнения (RuntimeException и его подклассы) и ошибки (Error). Когда возникает RuntimeException, это означает, что в программе есть программная ошибка, поэтому вы должны найти ошибку и изменить программу, а не ловить RuntimeException.
😮3. Механизм обработки исключений (выделено)
В приложениях Java механизм обработки исключений таков: выбрасывать исключения и перехватывать исключения.
🐁3.1 Обработка исключений Java
-
В Java, когда метод вызывает исключение, система автоматически находит подходящий обработчик исключений (обработчик исключений) для обработки исключения в соответствии с объектом исключения, классифицирует различные исключения и предоставляет удобный интерфейс.
-
В Java каждое исключение — это объект, являющийся экземпляром класса Throwable или его подклассов. Когда в методе возникает исключение, создается объект исключения, который содержитинформация об исключении, вызов метода для этого объекта может перехватить исключение и обработать его.
-
Обработка исключений в Java включает пять ключевых слов: try, catch, finally, throw и throws.
-
В Java-приложениях механизм обработки исключений разделен на объявление генерирования исключений, генерирование исключения и отлов исключения try, catch, наконец.
Далее расскажу подробно.
🐂3.2 Ключевые слова для обработки исключений
-
throw: Используется для создания исключений.
-
try: для мониторинга. Поместите отслеживаемый код (код, который может генерировать исключение) внутри блока try, и когда в блоке try возникает исключение, оно генерируется.
-
catch: используется для перехвата исключений. catch используется для перехвата исключений, возникающих в блоке try.
-
finally: Блок finally выполняется всегда. В основном он используется для повторного использования ресурсов (таких как соединения с базой данных, сетевые соединения и файлы на диске), открытых в блоках try.
Уведомление: Только блок finally после завершения выполнения вернется для выполнения оператора return или throw в блоке try или catch.Если в блоке finally используется оператор метода завершения, такой как return или throw, он не будет вернитесь к выполнению и сразу остановитесь.
-
throws: используется в сигнатурах методов для объявления исключений, которые может генерировать метод.
Здесь сначала поймите ключевые слова, конкретный формат определения и использование описаны ниже:
🐅3.3 выбросить исключение
-
Когда он используется?
Как квалифицированный программист (не я ли), при написании программы мы должны учитывать ситуацию, когда программа дает сбой.
- Например, при определении метода метод должен принимать параметры. Затем, когда вызывающий метод использует полученные параметры, сначала необходимо вынести юридическое суждение о данных параметра.Если данные не являются допустимыми, он должен сообщить вызывающему и передать допустимые данные. В этом случае вызывающая сторона должна быть проинформирована путем создания исключения.
- Или, когда вы чувствуете, что некоторые проблемы с исключениями не могут быть решены и не должны обрабатываться вызывающей стороной, вы также можете генерировать исключения.
-
Роль throw: Генерирует исключение типа Throwable внутри метода. Любой код Java может вызвать исключение с помощью оператора throw.
-
Как конкретно бросить исключение?
-
Создайте объект исключения. Инкапсулируйте некоторую оперативную информацию (информацию можно написать самостоятельно).
-
Этот объект исключения должен быть уведомлен вызывающей стороне. Как сказать? Как передать этот объект исключения вызывающей стороне? Это можно сделать с помощью ключевого слова throw. бросить объект исключения.
throwиспользуется в методе, используемый для создания объекта исключения, передачи объекта исключения вызывающему объекту и завершения выполнения текущего метода.
-
-
Формат определения:
throw new 异常类名(参数);
-
пример:
throw new NullPointerException("要访问的arr数组不存在"); throw new ArrayIndexOutOfBoundsException("该索引在数组中不存在,已超出范围");
Далее продемонстрируем это с помощью программы:
public class ThrowDemo { public static void main(String[] args) { //创建一个数组 int[] arr = {2,4,52,2}; //根据索引找对应的元素 int index = 4; int element = getElement(arr, index); System.out.println(element); System.out.println("over"); } /* * 根据 索引找到数组中对应的元素 */ public static int getElement(int[] arr,int index){ //判断索引是否越界 if(index<0 || index>arr.length-1){ /* 判断条件如果满足,当执行完throw抛出异常对象后,方法已经无法继续运算。 这时就会结束当前方法的执行,并将异常告知给调用者。这时就需要通过异常来解决。 */ throw new ArrayIndexOutOfBoundsException("老弟,你的索引越界了,别这么干"); } int element = arr[index]; return element; } }
Вывод после запуска:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 老弟,你的索引越界了,别这么干 at com.it.test2.ThrowDemo.getElement(ThrowDemo.java:25) at com.it.test2.ThrowDemo.main(ThrowDemo.java:10)
Вы можете видеть, что я определил индекс равным 4, но длина массива всего 4. Так он сообщит об ошибке.
Примечание: Итак, если есть проблема, мы будем бросать класс описания проблемы, то есть исключение, то есть возвращать проблему вызывающему методу. оказаться
ArrayIndexOutOfBoundsException
Проблема выхода за пределы индекса массива.Так что же делать звонящему? Один из них — зафиксировать обработку, а другой — продолжить обсуждение постановки задачи и использовать обработку инструкции throws.
🐇3.4 Объявить исключения
Если метод может генерировать исключение, но не способен обработать такое исключение, вы можете использовать предложение throws в объявлении метода, чтобы объявить, что создается исключение. Например, когда машина на ходу, она может выйти из строя, а сама машина с этой поломкой не справится, поэтому пусть с этим справляется водитель.
-
объявить исключение: определяет проблему и сообщает о ней вызывающему абоненту. Если исключение времени компиляции вызывается в методе через throw без захвата и обработки (метод будет объяснен позже), то его необходимо объявить через throws и позволить вызывающей стороне обработать его.
Ключевое слово throws используется в объявлениях методов, чтобы указать, что текущий метод не обрабатывает исключения, а вместо этого напоминает вызывающей стороне о том, что метод должен обрабатывать исключения (выдает исключения).
-
Определите формат: Оператор throws используется для объявления типа исключения, которое будет выброшено методом, когда метод определен.Если выбран тип исключения Exception, метод объявляется для выдачи всех исключений. Несколько исключений могут быть разделены запятыми.
修饰符 返回值类型 方法名(参数) throws 异常类名1,异常类名2…{ }
Уведомление: Когда метод выдает исключение из списка исключений, метод не будет обрабатывать исключения этих типов и их подклассов, а выдаст их методу, вызвавшему метод, и позволит ему его обработать. После использования ключевого слова throws для выдачи исключения вызывающему объекту, если вызывающий объект не хочет обрабатывать исключение, он может продолжать выбрасывать вверх, но в конечном итоге должен быть вызывающий объект, который может обработать исключение. Например, если машина сломается, водитель не сможет ее починить, поэтому для ее ремонта остается только вызвать авторемонтную компанию.
-
Показывать:
Вообще броски и броски обычно идут парами, например:
public class ThrowsDemo { public static void main(String[] args) throws FileNotFoundException { readFile("a.txt"); } // 如果定义功能时有问题发生需要报告给调用者。可以通过在方法上使用throws关键字进行声明 public static void readFile(String path) throws FileNotFoundException { if(!path.equals("a.txt")) {//如果不是 a.txt这个文件 // 我假设 如果不是 a.txt 认为 该文件不存在 是一个错误 也就是异常 throw throw new FileNotFoundException("文件不存在"); } } }
И throws используется для объявления классов исключений.Если метод может иметь несколько исключений, то несколько классов исключений могут быть написаны после throws, разделенных запятыми.
public class ThrowsDemo2 { public static void main(String[] args) throws IOException { readFile("a.txt"); } //若该方法可能有多种异常情况产生,那么在throws后面可以写多个异常类,用逗号隔开 //若有异常a是异常b的子类,也可以直接省略,写b异常 private static void readFile(String path) throws FileNotFoundException, IOException { if (!path.equals("a.txt")) {//如果不是 a.txt这个文件 // 我假设 如果不是 a.txt 认为 该文件不存在 是一个错误 也就是异常 throw throw new FileNotFoundException("文件不存在"); } if (!path.equals("b.txt")) { throw new IOException(); } } }
-
выдает правила для генерации исключений:
- Если это непроверенное исключение, то есть Error, RuntimeException или их подклассы, вы можете объявить, что исключение будет выброшено без использования ключевого слова throws, и компиляция все еще может пройти гладко, но оно будет выброшено системой во время выполнения.
- Если у метода может быть проверенное исключение, используйте либо
try-catch
захвата оператора, либо объявите его с предложением throws, иначе возникнет ошибка компиляции. - Только при возникновении исключения вызывающая сторона метода должна обработать или повторно создать исключение. Если вызывающий метод не может обработать исключение, он должен продолжать генерировать исключение.
- Вызывающий метод должен следовать правилам обработки и объявления любого обнаруживаемого исключения. Если вы переопределяете метод, не объявляйте исключение, отличное от переопределенного метода. Любое объявленное исключение должно относиться к тому же классу или подклассу исключения, объявленного переопределенным методом.
🐉3.5 Поймать исключение попробовать, наконец, поймать
Эти три ключевых слова в основном имеют следующие комбинацииtry-catch
,try-finally
,try-catch-finally
.
Уведомление: оператор catch может иметь один или несколько или ни одного, наконец, не более одного, попробуйте обязательно.
Потом вы спросите, есть ли отдельный модуль try, тогда я хочу вас спросить, try используется для того, чтобы следить за тем, есть ли исключение, и если возникнет исключение, то кто его перехватит? Таким образом, ни одна попытка не появляется в одиночку. И компиляция не проходит.
Таким образом, подобные модули try, такие как catch, наконец, не могут использоваться в одиночку.
- Программа обычно не сообщает об ошибке перед запуском, но некоторые неизвестные ошибки могут возникать после запуска.Если вы не хотите, чтобы исключения вызывали завершение программы, или не хотите, чтобы вас бросали сразу на предыдущий уровень, вам нужно пройти
try-catch
Перехватывайте исключения в других формах, а затем обрабатывайте их в соответствии с другими исключениями. - поймать исключение: в Java фиксируется целевой оператор исключения, и исключение может быть обработано указанным способом.
Синтаксис для перехвата исключений следующий:
🔴3.5.1 форма попытки поймать:
try{
编写可能会出现异常的代码
}catch(异常类型 e){
处理异常的代码
//记录日志/打印异常信息/继续抛出异常
}
Например:
public class TryCatchDemo {
public static void main(String[] args) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
try {
//当产生异常时,必须有处理方式。要么捕获,要么声明。
Date date = simpleDateFormat.parse("2020-10-06");
} catch (ParseException e) {// 括号中需要定义什么呢?
//try中抛出的是什么异常,在括号中就定义什么异常类型
e.printStackTrace();//记录日志/打印异常信息/继续抛出异常
}
/*
public Date parse(String source) throws ParseException{}
//parse抛出了ParseException异常
public class ParseException extends Exception {}
*/
}
}
Как получить информацию об исключении:
Некоторые методы просмотра определены в классе Throwable:
-
public String getMessage()
: получить информацию об исключении и причине (при запросе пользователя будет указана причина ошибки. -
public String toString()
: получить информацию о типе и описании исключения. -
public void printStackTrace()
: распечатать информацию о трассировке стека исключений и вывести ее на консоль. - В частности, мы можем посмотреть на:
public class TryCathDemo2 {
public static void main(String[] args) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
try {
//当产生异常时,必须有处理方式。要么捕获,要么声明。
//演示下获取异常信息,修改了格式。
Date date = simpleDateFormat.parse("2020年10月06");
} catch (ParseException e) {
//public String getMessage():获取异常的描述信息,原因(提示给用户的时候,就提示错误原因
System.out.println(e.getMessage());//Unparseable date: "2020年10月06"
System.out.println(e.toString());//java.text.ParseException: Unparseable date: "2020年10月06"
e.printStackTrace();//输出信息而且飘红!!!
/*
java.text.ParseException: Unparseable date: "2020年10月06"
at java.text.DateFormat.parse(DateFormat.java:366)
at com.it.test3.TryCathDemo2.main(TryCathDemo2.java:13)
*/
}
}
}
И если есть несколько исключений, использующих захват, что нам делать?
- Несколько исключений обрабатываются отдельно.
- Несколько исключений перехватываются один раз и обрабатываются несколько раз.
Как правило, мы используем метод многократной обработки одного захвата в следующем формате:
try{
编写可能会出现异常的代码
}catch(异常类型A e){ 当try中出现A类型异常,就用该catch来捕获.
处理异常的代码
//记录日志/打印异常信息/继续抛出异常
}catch(异常类型B e){ 当try中出现B类型异常,就用该catch来捕获.
处理异常的代码
//记录日志/打印异常信息/继续抛出异常
}
Например:
public class TryCatchDemo3 {
public static void main(String[] args) {
//test();
test2();
}
//多个异常一次捕获,多次处理。
public static void test2(){
int[] arr = {11, 22, 66, 0};
try {
//System.out.println(arr[5]);//一旦这个报错,下面的代码就不会执行
System.out.println(arr[2]);
System.out.println(arr[0] / arr[arr.length-1]);
} catch (ArithmeticException e) {
System.out.println("除数不为0");
}catch (ArrayIndexOutOfBoundsException e) {
System.out.println("数组下标越界");
}catch (Exception e) {
e.printStackTrace();
}
}
//分别处理的方式
public static void test() {
int a = 10;
int b = 0;
try {
System.out.println(a / b);
} catch (ArithmeticException e) {
System.out.println("除数不为0");//除数不为0
}
int[] arr = {1, 2, 3};
try {
System.out.println(arr[4]);
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("数组下标越界");//数组下标越界
}
}
}
Уведомление: метод обработки исключений одного захвата и множественной обработки требует, чтобы исключения в нескольких захватах не были одинаковыми, и если существует связь между исключениями дочернего и родительского классов между несколькими исключениями в захвате, то исключение дочернего класса требует вышеуказанного catch processing. , исключение родительского класса обрабатывается в следующем catch.
Например:
🟠3.5.2 форма try-finally:
try{
//(尝试运行的)程序代码
}finally{
//异常发生,总是要执行的代码
}
try-finally
Указывает, что независимо от выполнения фрагмента кода, код в finally будет выполнен.
Например:
public class TryFinallyDemo {
public static void main(String[] args) {
int a = 10;
int b = 0;
try{
System.out.println(a / b);
System.out.println("会走try吗");
}finally{
System.out.println("会finally吗");//会finally吗
}
System.out.println("会走外面吗");
/*
没有捕获的话,他只会走finally语句然后报出异常。
会finally吗
Exception in thread "main" java.lang.ArithmeticException: / by zero
at com.it.test3.TryFinallyDemo.main(TryFinallyDemo.java:8)
*/
}
}
Видно, что программа ненормальная, и она все равно пойдет на код блока finally.
🟡3.5.3 Форма try-catch-finally:
try {
// 可能会发生异常的程序代码
} catch (异常类型A e){
// 捕获并处置try抛出的异常类型A
} finally {
// 无论是否发生异常,都将执行的语句块
}
Как и try-finally, это означает, что независимо от того, как выполняется часть кода, код в finally будет выполнен.
Когда в методе возникает исключение, код после исключения не будет выполняться.Если некоторые локальные ресурсы были получены ранее и должны быть освобождены, код для освобождения локальных ресурсов должен быть вызван в обычном конце метода. и в операторе catch, что делает код более громоздким, оператор finally может решить эту проблему.
Например:
public class TryCatchFinallyDemo {
public static void main(String[] args) {
test();
}
public static void test() {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
Date date = null;
try {
//date = simpleDateFormat.parse("2020-10-06");//第一次运行成功
date = simpleDateFormat.parse("2020年10月06日");
} catch (ParseException e) {
e.printStackTrace();
}finally{
System.out.println("finally这里一定会执行");
}
System.out.println("会走外面这里吗" + date);
}
}
Результат после запуска успешного кода:
finally这里一定会执行
会走外面这里吗Tue Oct 06 00:00:00 CST 2020
Результат после запуска сбойного кода:
java.text.ParseException: Unparseable date: "2020/10/06"
at java.text.DateFormat.parse(DateFormat.java:366)
at com.it.test3.TryCatchFinallyDemo.test(TryCatchFinallyDemo.java:19)
at com.it.test3.TryCatchFinallyDemo.main(TryCatchFinallyDemo.java:12)
finally这里一定会执行
会走外面这里吗null
Как видите, код блока finally выполняется независимо от сбоя.
-
Уведомление:
try-catch-finally
, если улов вернется, в конце концов все равно будет выполнен?public class TryCatchFinallyDemo2 { public static void main(String[] args) { test(); } public static void test() { int a = 10; try{ System.out.println(a / 0); }catch(ArithmeticException e) { e.printStackTrace(); return ; }finally { System.out.println("finally"); } } }
результат операции:
java.lang.ArithmeticException: / by zero at com.it.test3.TryCatchFinallyDemo2.test(TryCatchFinallyDemo2.java:11) at com.it.test3.TryCatchFinallyDemo2.main(TryCatchFinallyDemo2.java:5) finally
Как видите, даже если улов будет возвращен, finally будет выполнен.
Это, наконец, до возвращения или после возвращения?
Давайте посмотрим код ниже?
public class TryCatchFinallyDemo2 { public static void main(String[] args) { // test(); System.out.println(test2()); // 我有执行到吗 try System.out.println(test3()); // 我有执行到吗 catch } public static String test3() { String str = ""; try { str = "try"; System.out.println(10 / 0); return str; }catch(Exception e) { str = "catch"; return str; }finally { str = "finally"; System.out.println("我有执行到吗"); } } public static String test2() { String str = ""; try { str = "try"; return str; }catch(Exception e) { str = "catch"; return str; }finally { str = "finally"; System.out.println("我有执行到吗"); } } }
результат операции:
我有执行到吗 try 我有执行到吗 catch
Посмотрите здесь и обнаружите, что независимо от того, является ли это ненормальным или нет, finally будет выполнен, но код будет выполнен до возврата. Но почему возвращаемая строка не окончательно? Давайте подумаем об этом вместе:
-
Рассмотрим метод test2(): программа выполняет блок try и присваивает переменной str значение
"try"
, так как исключения не найдено, далее выполняется блок finally, а переменной str присваивается значение"finally"
,Потомreturn str
, то значение t равно finally, а окончательное значение str равно"finally"
, результат программы должен отображаться наконец, но фактический результат“try”
. -
На самом деле, в блоке возврата оператора try, когда мы выполняем
return str
На этом шаге нетreturn str
ноreturn “try”
Теперь обратный путь сформирован.Ссылочная переменная, возвращаемая return (str — это ссылочный тип), не является ссылочной переменной str, определенной вне оператора try, но система переопределяет локальную ссылку str2 и возвращает значение, указывающее на ссылку str2, то есть
"try"
нить.Но здесь он обнаруживает, что есть finally, поэтому продолжайте выполнять содержимое finally,
str = "finally"; System.out.println("我有执行到吗");
, Снова вернуться к предыдущему пути, продолжить возвращать "try", после того, как обратный путь сформирован, возвращаемая ссылка return здесь не переменная str, а значение, на которое ссылается str2"try"
нить.
Есть ли у вас определенное понимание этого явления? Эй, здесь мы конвертируем это снова:
public class TryCatchFinallyDemo2 { public static void main(String[] args) { // test(); // System.out.println(test2()); // try // System.out.println(test3()); // catch System.out.println(test4()); } public static String test4() { String str = ""; try { str = "try"; return str; }catch(Exception e) { str = "catch"; return str; }finally { str = "finally"; return str; } } }
Вот и догадываемся, каков результат?
Результат работы: наконец
- Мы обнаружили, что оператор return в операторе try был проигнорирован. Возможно, JVM считает, что в методе есть два оператора возврата, и это не имеет особого смысла, поэтому оператор возврата в try игнорируется.
“finally”
нить.
Посмотрите еще раз: знаем ли мы, что оператор finally должен выполняться, но есть ли способ сделать так, чтобы этого не было?
Раз я сказал это, значит, оно должно быть там.
public class TryCatchFinallyDemo3 { public static void main(String[] args) { try{ System.out.println(10 / 0); }catch(Exception e) { e.printStackTrace(); System.exit(0); }finally { System.out.println("finally我有执行到吗"); } } }
Результаты:
java.lang.ArithmeticException: / by zero at com.it.test3.TryCatchFinallyDemo3.main(TryCatchFinallyDemo3.java:6)
Его можно найти:
Когда в try или catch вызываются только соответствующие методы для выхода из JVM, finally не будет выполняться в это время, иначе finally будет выполняться навсегда.
-
🔵3.5.4 Резюме
- блок try: используется для перехвата исключений. За ним может следовать ноль или более блоков catch.Если блока catch нет, за ним должен следовать блок finally.
- блок catch: используется для обработки исключений, перехваченных попыткой.
- блок finally: операторы в блоке finally будут выполняться независимо от того, перехвачено или обработано исключение. Когда оператор return встречается в блоке try или блоке catch, блок операторов finally будет выполнен до возврата из метода. Блок finally не будет выполняться в следующих 4 особых случаях:
- Исключение произошло в блоке finally.
- используется в предыдущем коде
System.exit()
выйти из программы. - Поток, в котором находится программа, умирает.
- Выключите ЦП.
🐍3.6 Как выбрать тип исключения
Вы можете выбрать, следует ли перехватывать исключение, объявлять исключение или генерировать исключение в соответствии со следующим рисунком.
Принципы, которым мы должны следовать в нашей ежедневной обработке исключений кода:
-
Не перехватывайте исключения, такие как Exception, а перехватывайте определенные исключения, чтобы упростить устранение неполадок, и это также уменьшит количество выговоров, когда кто-то другой берет на себя ваш код.
-
Не глотайте исключения в сыром виде. Это то, на что следует обратить особое внимание при обработке исключений. Если мы не сгенерируем исключение или не выведем его в журнал, программа может закончиться неконтролируемым образом позже. Иногда вам нужно отлаживать свой код онлайн.
😛4 новые функции JDK1.7 об исключениях
📤4.1 попробовать с ресурсами
В библиотеке классов Java есть много ресурсов, которые необходимо закрыть с помощью метода close. Например, InputStream, OutputStream и т. д. Как разработчик, метод закрытия ресурсов часто игнорируется, что приводит к утечкам памяти. Конечно не я!
До JDK1.7,try-catch-finally
Операторы — лучший способ гарантировать, что ресурс будет закрыт, даже если произойдет исключение или возврат.
-
Давайте сначала посмотрим, как мы закрыли ресурс раньше:
public static String readFile(String path) { BufferedReader br = null; try { br = new BufferedReader(new FileReader(path)); return br.readLine(); } catch (IOException e) { e.printStackTrace(); } finally {//必须在这里关闭资源 if (br != null) { try { br.close(); } catch (IOException e) { e.printStackTrace(); } } return null; } }
Нужно ли вручную закрывать ресурс в блоке finally, иначе это приведет к утечке ресурсов
-
В JDK1.7 и более поздних версиях:
Представлено в JDK1.7
try-with-resources
утверждение.-
try-with-resources
оператор — это оператор попытки, который объявляет один или несколько ресурсов.try-with-resources
Оператор гарантирует, что каждый ресурс закрывается в конце оператора, если это объект, который реализует интерфейс AutoCloseable или может использоваться интерфейс Closeable.try-with-resources
для реализации обработки исключений и закрытия ресурсов. - Фактически, он также преобразуется во время компиляции в
try-catch-finally
утверждение.
Итак, давайте посмотрим, как его использовать:
Формат:
try (创建流对象语句,如果多个,使用';'隔开) { // 读写数据 } catch (IOException e) { e.printStackTrace(); }
Продемонстрировать:
/** * JDK1.7之后就可以使用try-with-resources,不需要 * 我们在finally块中手动关闭资源 */ public class TryWithResourcesDemo { public static String readLineFormFile(String path) { try (BufferedReader br = new BufferedReader(new FileReader(path))) { return br.readLine(); } catch (IOException e) { e.printStackTrace(); } return null; } }
-
-
Сравнение двух:
-
Код доработан, есть блоки finally до JDK1.7, если используются некоторые фреймворки, то блоки finally могут обрабатываться фреймворком, например
Spring
. JDK1.7 и более поздние версии, если класс ресурсов реализует AutoCloseable или программа Closeable, автоматически выполняет блок try.close()
Независимо от используемых ресурсовbr.readLine()
Выбрасывать ли исключение. -
Код более полный. В программах с утечками ресурсов многие случаи вызваны тем, что разработчик не закрыл ресурс должным образом или разработчик не закрыл ресурс должным образом. Принято после JDK1.7
try-with-resources
Таким образом, работа по закрытию ресурсов, которая не связана напрямую с бизнес-реализацией, может быть передана для завершения JVM. Устраните некоторые риски кода, которые могут возникнуть в процессе разработки. -
от
readLineFormFile
метод, например, если вы вызываетеreadLine()
иclose()
метод выдает исключение, последнее исключение подавляется, чтобы сохранить первое исключение.
-
📥4.2 Перехват нескольких исключений и создание новых исключений
-
Прежде чем JDK1.7 перехватит несколько исключений, например:
try{ 编写可能会出现异常的代码 }catch(异常类型A e){ 当try中出现A类型异常,就用该catch来捕获. 处理异常的代码 }catch(异常类型B e){ 当try中出现B类型异常,就用该catch来捕获. 处理异常的代码 }
-
JDK1.7 и более поздние версии могут сделать это:
try{ 编写可能会出现异常的代码 }catch (异常类型A | 异常类型B e) { 处理异常的代码 }
Однако это тот же тип исключения, который может быть определен таким образом.
😜5 пользовательских исключений
🛳️5.1 Зачем нужен собственный класс исключений:
Мы говорили о разных классах исключений в Java, которые соответственно представляют конкретную нештатную ситуацию, тогда в разработке, когда встроенные исключения Java не могут четко описать нештатную ситуацию, нужно создавать свое исключение. Например, возрастные отрицательные вопросы, тестовые баллы отрицательные вопросы.
Что такое пользовательский класс исключений:
В процессе разработки вы можете определить классы исключений в соответствии с вашими бизнес-исключениями. Например: в системе входа возраст может быть отрицательным числом, если нет, вам нужно определить класс исключений входа самостоятельно.
⛴️5.2 Как определить собственный класс исключений
- Настройте исключение времени компиляции: пользовательский класс и наследование от
java.lang.Exception
. - Настройте класс исключений во время выполнения: настройте класс и наследуйте от него.
java.lang.RuntimeException
.
- Как правило, определение класса исключения должно содержать два конструктора: конструктор без аргументов и конструктор с подробным описанием.
public class MyException extends Exception {
public MyException(){ }
public MyException(String message){
super(message);
}
}
🛥️5.3 Пример пользовательского исключения
Требование: Имитируем операцию входа в систему.Если имя пользователя уже существует, будет выдано исключение и сообщение: Уважаемый, имя пользователя было зарегистрировано. Уверен, вы все это часто видите.
-
Сначала определите класс исключения входа в систему
LoginException
:/** * 登陆异常类 */ public class LoginException extends Exception { public LoginException() { } public LoginException(String message) { super(message); } }
-
Смоделируйте операцию входа в систему, используйте массив для имитации данных, хранящихся в базе данных, и предоставьте метод для определения того, существует ли текущая зарегистрированная учетная запись.
public class LoginTest { // 模拟数据库中已存在账号 private static String[] names = {"hello", "world", "fish"}; public static void main(String[] args) { //调用方法 try{ // 可能出现异常的代码 checkUsername("fish"); System.out.println("注册成功");//如果没有异常就是注册成功 } catch(LoginException e) { //处理异常 e.printStackTrace(); } } //判断当前注册账号是否存在 //因为是编译期异常,又想调用者去处理 所以声明该异常 public static boolean checkUsername(String uname) throws LoginException { for (String name : names) { if(name.equals(uname)){//如果名字在这里面 就抛出登陆异常 throw new LoginException("亲"+name+"已经被注册了!"); } } return true; } }
Результат выполнения: Регистрация прошла успешно.
🌸6. Дорисуйте разбросанные цветы
Я считаю, что все чиновники имеют определенное представление о системе исключений.В нашем практическом приложении мы обычно проводим некоторые эффективные обработки возможных исключений.Например, если есть исключения, мы можем вернуться к дружественному интерфейсу или дружественному интерфейсу , Информация для пользователя, невозможно предоставить какую-либо ненормальную информацию пользователю, что очень плохо для пользователя! Так что обработка исключений совершенно необходима!
Давайте сделаем все возможное вместе! Я не талантливый, если есть упущения или ошибки, тоже милости просим в талантливые людиКомментарийКритика и исправления! Конечно, если эта статья вам точно не поможет, пожалуйста, добрые и милые таланты.Нравится, любимыйСпустись,Одна кнопка три ссылки,Большое спасибо!
Узнал здесь, мир сегодня закрыт, спокойной ночи! Хотя эта статья закончилась, я все еще здесь и никогда не закончу. Я постараюсь продолжать писать статьи. Приезжайте в Японию надолго, не бойтесь быть медленным!
Спасибо за то, что вы здесь! Доживи до молодости и ни о чем не жалей в молодости!