Основная идея в Java заключается в том,结构不佳的代码不能运行
, идеальное время для поиска ошибок — во время компиляции, потому что вам не нужно запускать программу, вы можете найти проблемы, просто поняв основные концепции Java. Однако не все проблемы можно обнаружить во время компиляции. Некоторые исключения NullPointerException и ClassNotFoundException не могут быть найдены во время компиляции. Эти исключения являются исключениями времени выполнения RuntimeException, и эти исключения часто обнаруживаются во время выполнения.
При написании программ на Java у нас часто возникают проблемы двух типов: java.lang.Exception и java.lang.Error, которые используются для указания того, что произошло исключение. концепции.
Распознать исключение
Exception
родыjava.lang
package, это интерфейс верхнего уровня, который наследуется отThrowable
Класс, класс исключения и его подклассы — все это составляющие условия Throwable, которые являются разумными ситуациями для появления программы.
Прежде чем знать Exception, необходимо понять, что такоеThrowable
.
Что можно бросать
Класс Throwable - это все错误(errors)
и异常(exceptions)
родительский класс. Выбрасывать можно только классы, наследуемые от Throwable или его подклассов, и с Java есть еще один способ.@throw
Аннотированные классы также могут бросать.
существуетСпецификация Java, определения непроверенных исключений и проверенных исключений следующие:
The unchecked exception classes are the run-time exception classes and the error classes.
The checked exception classes are all exception classes other than the unchecked exception classes. That is, the checked exception classes are
Throwable
and all its subclasses other thanRuntimeException
and its subclasses andError
and its subclasses.
То есть кромеRuntimeException
И его подклассы, иerror
и его подклассы, все остальные исключенияcheckedException
.
Затем, в соответствии с этой логической связью, мы можем классифицировать и анализировать Throwable и его подклассы.
Как видите, Throwable находится на верхнем уровне исключений и ошибок.Мы смотрим на класс Throwable и обнаруживаем, что у него много методов и свойств.Мы обсудим лишь некоторые из наиболее часто используемых.
// 返回抛出异常的详细信息
public string getMessage();
public string getLocalizedMessage();
//返回异常发生时的简要描述
public public String toString();
// 打印异常信息到标准输出流上
public void printStackTrace();
public void printStackTrace(PrintStream s);
public void printStackTrace(PrintWriter s)
// 记录栈帧的的当前状态
public synchronized Throwable fillInStackTrace();
Кроме того, поскольку родительский класс Throwable такжеObject
, поэтому часто используемые методы также наследуются от родительского класса.getClass()
иgetName()
метод.
Общее исключение
Вернемся к обсуждению Exception.Теперь вы знаете, что родительским классом Exception является Throwable, а у Exception есть два типа исключений:RuntimeException
; одинCheckedException
, оба исключения должны перейти к捕获
.
Ниже приведен список некоторых распространенных исключений в Java и их классификация. Этот интервьюер также может попросить вас назвать несколько распространенных исключений и классифицировать их.
RuntimeException
серийный номер | имя исключения | описание исключения |
---|---|---|
1 | ArrayIndexOutOfBoundsException | исключение массива за пределами границ |
2 | NullPointerException | исключение нулевого указателя |
3 | IllegalArgumentException | Недопустимое исключение параметра |
4 | NegativeArraySizeException | Длина массива является отрицательным исключением |
5 | IllegalStateException | Исключение недопустимого состояния |
6 | ClassCastException | исключение преобразования типа |
UncheckedException
серийный номер | имя исключения | описание исключения |
---|---|---|
1 | NoSuchFieldException | Указывает на исключение, созданное классом без указанного имени. |
2 | NoSuchMethodException | Указывает, что в классе нет исключения, вызванного указанным методом. |
3 | IllegalAccessException | Исключение, не разрешающее доступ к классу |
4 | ClassNotFoundException | класс не найден выдает исключение |
Ключевые слова Java, связанные с исключением
Так как же обрабатываются эти исключения в Java? В Java есть несколько ключевых словбросает, бросает, старается, наконец, ловитдавайте обсудим отдельно
бросает и бросает
В Java исключение — это объект, который может быть создан программистом или приложением.throws
иthrow
Оператор для определения генерации исключений.
броски и бросок обычно парные, например.
static void cacheException() throws Exception{
throw new Exception();
}
Оператор throw используется в теле метода, чтобы указать, что создается исключение, которое обрабатывается оператором в теле метода. Оператор throws используется после объявления метода, чтобы указать, что исключение генерируется снова, которое обрабатывается вызывающей стороной метода.
throws в основном для того, чтобы объявить, что этот метод будет генерировать исключение этого типа, чтобы вызывающая сторона знала, что нужно перехватить это исключение. Throw — это действие по выбрасыванию исключения, поэтому оно создает экземпляр исключения.
попробуй, наконец, поймай
Эти три ключевых слова в основном имеют следующие комбинациипопробуй... поймай, попробуй... наконец, попробуй... поймай... наконец.
try...catch представляет захват исключения, которое может быть вызвано определенным фрагментом кода, следующим образом
static void cacheException() throws Exception{
try {
System.out.println("1");
}catch (Exception e){
e.printStackTrace();
}
}
try...finally означает, что независимо от того, как выполняется часть кода, код в finally будет выполнен.
static void cacheException() throws Exception{
for (int i = 0; i < 5; i++) {
System.out.println("enter: i=" + i);
try {
System.out.println("execute: i=" + i);
continue;
} finally {
System.out.println("leave: i=" + i);
}
}
}
То же самое верно и для try...catch...finally, что означает, что после перехвата исключения следует логика кода в finally.
JDK1.7 использует try...with...resources для корректного закрытия ресурсов.
В библиотеке классов Java есть много ресурсов, которые необходимо закрыть с помощью метода close. Например, InputStream, OutputStream, объект подключения к базе данных Connection, сеанс SqlSession в MyBatis и т. д. Как разработчик, метод закрытия ресурсов часто игнорируется, что приводит к утечкам памяти.
Основываясь на опыте,try-finally
Операторы — лучший способ гарантировать, что ресурсы будут закрыты даже при возникновении исключений или возвратов. try-catch-finally обычно используется так
static String firstLineOfFile(String path) throws IOException {
BufferedReader br = new BufferedReader(new FileReader(path));
try {
return br.readLine();
}finally {
br.close();
}
}
Это по-прежнему выглядит аккуратнее, но когда мы добавим второй ресурс, который необходимо закрыть, он будет выглядеть следующим образом.
static void copy(String src,String dst) throws Exception{
InputStream is = new FileInputStream(src);
try {
OutputStream os = new FileOutputStream(dst);
try {
byte[] buf = new byte[100];
int n;
while ((n = is.read()) >= 0){
os.write(buf,n,0);
}
}finally {
os.close();
}
}finally {
is.close();
}
}
Такое ощущение, что этот метод раздулся.
И проблем с таким способом написания много: даже если try - finally может правильно закрыть ресурс, он не может предотвратить генерацию исключения, потому что исключения могут возникать как в блоке try, так и в блоке finally.
Например, если жесткий диск поврежден во время чтения, вы не можете прочитать файл и закрыть ресурс в это время, и в это время будут выброшены два исключения. Но в этом случае второе исключение стирает первое. Не удается найти запись о первом исключении в стеке исключений. Что делать? Можно ли перехватывать такие исключения?
static void tryThrowException(String path) throws Exception {
BufferedReader br = new BufferedReader(new FileReader(path));
try {
String s = br.readLine();
System.out.println("s = " + s);
}catch (Exception e){
e.printStackTrace();
}finally {
try {
br.close();
}catch (Exception e){
e.printStackTrace();
}finally {
br.close();
}
}
}
Хотя такой способ написания может решить проблему генерирования исключений, вложенность различных try-cath-finally сделает код очень раздутым.
Представлено в Java7try-with-resources
Все эти проблемы могут быть решены при использовании оператора. Чтобы использовать оператор try-with-resources, сначала реализуйтеAutoCloseable
Интерфейс, этот интерфейс содержит единственный метод закрытия возврата. Многие классы и интерфейсы в библиотеке классов Java и трехсторонней библиотеке классов теперь реализуют или расширяют интерфейс AutoCloseable. Если вы пишете класс, представляющий ресурс, который необходимо закрыть, этот класс должен реализовать интерфейс AutoCloseable.
В java появился оператор try-with-resources, упрощающий try-catch-finally до try-catch, который на самом деле является своего рода语法糖
, который преобразуется в оператор try-catch-finally во время компиляции.
Вот первый пример использования try-with-resources
/**
* 使用try-with-resources 改写示例一
* @param path
* @return
* @throws IOException
*/
static String firstLineOfFileAutoClose(String path) throws IOException {
try(BufferedReader br = new BufferedReader(new FileReader(path))){
return br.readLine();
}
}
Второй пример переписывания программы с использованием try-with-resources
static void copyAutoClose(String src,String dst) throws IOException{
try(InputStream in = new FileInputStream(src);
OutputStream os = new FileOutputStream(dst)){
byte[] buf = new byte[1000];
int n;
while ((n = in.read(buf)) >= 0){
os.write(buf,0,n);
}
}
}
Использование try-with-resources не только упрощает понимание кода, но и облегчает его диагностику. отfirstLineOfFileAutoClose
метод, например, если вы вызываетеreadLine()
иclose()
метод выдает исключение, последнее исключение подавляется, чтобы сохранить первое исключение.
Принципы обработки исключений
Мы должны следовать трем принципам в коде, который ежедневно обрабатывает исключения.
- Не поймать что-то вроде
Exception
исключения, такие какInterruptedException
, это удобно для устранения неполадок, а также может уменьшить количество раз, когда вы ругаете вас, когда вы позволяете другим взять на себя ваш код. - Не глотайте исключения в сыром виде. На это стоит обратить особое внимание при обработке исключений, потому что вполне вероятно, что нормально завершить ситуацию будет очень сложно. Если мы не будем генерировать исключения или не проиграем Logger Logger, программа может в дальнейшем выйти из-под контроля.
- Не использовать в функциональном программировании
checkedException
.
Что такое ошибка
Ошибки — это ошибки, которые программа не может обработать и которые представляют собой более серьезные проблемы в работе приложения. Большинство ошибок не имеют ничего общего с действиями автора кода, а представляют собой проблему с JVM (виртуальная машина Java) во время выполнения кода. Эти ошибки невозможно проверить, потому что они находятся вне возможностей контроля и обработки приложения, и большинство из них являются условиями, которые не разрешены во время работы программы, напримерOutOfMemoryError
иStackOverflowError
Есть несколько ситуаций, в которых возникают исключения.Здесь нам нужно представить модель памяти Java JDK1.7.
Он состоит из двух частей,Область данных, совместно используемая всеми потоками, и область данных, изолированная от потокакомпозиция в приведенной выше модели памяти Java,только программный счетчикне случитсяOutOfMemoryError
Счетчик программ управляет ветвлениями, циклами, переходами, обработкой исключений и восстановлением потоков компьютерных инструкций, а счетчик программ является частным для каждого потока.
Что такое частный поток: это означает, что каждый поток не влияет друг на друга и независимо хранится в области памяти.
Если приложение выполняет метод Java, то этот счетчик записывает虚拟机字节码
адрес инструкции; если выполнениеNative
метод, значение счетчика равно空(Undefined)
.
В дополнение к счетчику программ, другие области:方法区(Method Area)
,虚拟机栈(VM Stack)
,本地方法栈(Native Method Stack)
и堆(Heap)
В обеих областях может возникнуть ошибка OutOfMemoryError.
-
Стек виртуальной машины: если глубина стека, запрошенная потоком, больше, чем глубина, разрешенная стеком виртуальной машины, она появится
StackOverflowError
Исключение; если динамическое расширение виртуальной машины не может применяться для достаточного количества памяти, оно появитсяOutOfMemoryError
. -
Стек собственных методов аналогичен стеку виртуальной машины.
-
Куча: куча Java может быть физически прерывистой и логически непрерывной, как и наше дисковое пространство.Если в куче нет памяти для завершения выделения экземпляра, и куча не может расширяться, будет выброшена ошибка OutOfMemoryError.
-
Область метода: если область метода не может удовлетворить требования к выделению памяти, будет выдано исключение OutOfMemoryError.
Классический вопрос на собеседовании
Очень классический вопрос для интервью.В чем разница между NoClassDefFoundError и ClassNotFoundException?
В процессе загрузки класса, когда JVM или ClassLoader не может найти соответствующий класс, могут быть вызваны эти два исключения/ошибки.Поскольку разные ClassLoaders загружают классы из разных мест, иногда это вызвано неправильным путем к классу PATH.Ошибки класса, иногда вызвано отсутствием пакетов jar для библиотеки. NoClassDefFoundError означает, что класс существует во время компиляции, но класс не найден во время выполнения.Иногда статические блоки инициализации также вызывают ошибки NoClassDefFoundError.
ClassLoader — это загрузчик путей к классам В Java существует три типа загрузчиков путей к классам.
Одним из них является ClassLoader, который поставляется с виртуальной машиной и делится на три типа.
启动类加载器(Bootstrap)
, отвечающий за загрузку $JAVAHOME/jre/lib/rt.jar扩展类加载器(Extension)
, отвечающий за загрузку $JAVAHOME/jre/lib/ext/*.jar应用程序类加载器(AppClassLoader)
, который загружает все классы в текущем примененном пути к классамВторой — определяемый пользователем загрузчик классов.
- Подкласс Java.lang.ClassLoader, пользователи могут настраивать метод загрузки классов.
С другой стороны, ClassNotFoundException не имеет ничего общего со временем компиляции, когда вы пытаетесь загрузить класс во время выполнения с использованием отражения, появится ClassNotFoundException.
В двух словах, и ClassNotFoundException, и NoClassDefFoundError вызваны отсутствием классов в CLASSPATH, обычно из-за отсутствия файлов JAR, но если JVM считает, что среда выполнения приложения не может найти соответствующую ссылку, она выдает ошибку NoClassDefFoundError; когда загруженный класс вы показываете в вашем коде похожеClass.forName()
Если соответствующий класс не найден при вызове, он выдастjava.lang.ClassNotFoundException
.
- NoClassDefFoundError — это ошибка, вызванная JVM, и она не проверяется. Поэтому блоки try-catch или finally не используются, кроме того, ClassNotFoundException является проверяемым исключением, поэтому его нужно окружать блоками try-catch или try-finally, иначе получится ошибка компиляции.
- перечислитьClass.forName(), ClassLoader.findClass() и ClassLoader.loadClass()метод может вызвать
java.lang.ClassNotFoundException
, как показано на рисунке
- NoClassDefFoundError — это ошибка связывания, возникающая на этапе связывания, когда соответствующий класс не может быть найден при разрешении ссылки, а ClassNotFoundException — это исключение, которое возникает во время выполнения.
Ссылка на статью:
Woohoo.java67.com/2012/12/no C…
«Geek Time — 36 лекций по базовой технологии Java»
Глубокое понимание виртуальной машины Java, второе издание
Действующее третье издание Java
блог woo woo woo.cn on.com/xiohhao/afraid/35…
«Идеи программирования на Java»
Блог Woohoo.cn на.com/now816111/afraid/…
docs.Oracle.com/JavaColor/spec…
Комментарии к исходному коду jdk 1.8