Прочитав это Исключение и Ошибка, можно без проблем поспорить с интервьюером.

Java задняя часть

Основная идея в Java заключается в том,结构不佳的代码不能运行, идеальное время для поиска ошибок — во время компиляции, потому что вам не нужно запускать программу, вы можете найти проблемы, просто поняв основные концепции Java. Однако не все проблемы можно обнаружить во время компиляции. Некоторые исключения NullPointerException и ClassNotFoundException не могут быть найдены во время компиляции. Эти исключения являются исключениями времени выполнения RuntimeException, и эти исключения часто обнаруживаются во время выполнения.

При написании программ на Java у нас часто возникают проблемы двух типов: java.lang.Exception и java.lang.Error, которые используются для указания того, что произошло исключение. концепции.

Распознать исключение

Exceptionродыjava.langpackage, это интерфейс верхнего уровня, который наследуется от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 than RuntimeException and its subclasses and Errorand 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…

blog.CSDN.net/QQ_29229567…

blog.CSDN.net/Riemann_/AR…

«Идеи программирования на Java»

Блог Woohoo.cn на.com/now816111/afraid/…

docs.Oracle.com/JavaColor/spec…

Комментарии к исходному коду jdk 1.8