Исключения в Java


Классификация исключений

  • java.lang.Throwable - базовый класс для всех исключений;
  • Исключительные ситуации в пользовательском коде:
    • java.lang.Exception - базовый класс для проверяемых (checked) исключений, соответствующих ошибкам программной логики;
    • java.lang.RuntimeException - базовый класс для непроверяемых (unchecked) исключений, соответствующих ошибкам программной логики:
      • java.lang.NullPointerException;
      • java.lang.ArrayIndexOutOfBoundsException;
      • java.lang.ArithmeticException;
      • ...
  • Исключительные ситуации в JVM:
    • java.lang.Error - базовый класс для исключений, соответствующих ошибкам виртуальной машины:
      • java.lang.OutOfMemoryError;
      • java.lang.NoClassDefFoundError;
      • java.lang.VerifyError;
      • ...



Собственное исключение

public class CalculatorException extends RuntimeException {
 public CalculatorException(String message) {
  super(message);
 }
 public CalculatorException(String message, Throwable cause) {
  super(message, cause);
 }
}

public class CalculatorImpl implements Calculator {
 @Override
 public double calculate(String expr) {
  // ...
  throw new CalculatorException(
   "Unsupported operator found");
  // ...
 }
}

Перехват исключения: try-catch

for (;;) {
 System.out.print("Enter expression: ");
 String expr = readUserInput();
 if (expr == null || " exit ".equalsIgnoreCase(expr)) {
  break;
 }
 try {
  double result = calculator.calculate(expr);
  System.out.println("Result: " + result);
 } catch (CalculatorException e) {
  System.out.print("Bad expression: " + e.getMessage());
  System.out.print("Please try again: ");
 }
}

Перехват нескольких исключений

try {
 // ...
} catch (FirstException e) {
 e.printStackTrace();
} catch (SecondException e) {
 e.printStackTrace();
}
// since Java 7 can be replaced with :
try {
 // ...
} catch (FirstException | SecondException e) {
 e.printStackTrace();
}

finally

finally не является обработчиком исключения, т.е. если из блока try вылетело исключение, то после отработки блока finally это исключение полетит дальше.

InputStream is = new FileInputStream("a.txt");
try {
 readFromInputStream(is);
} finally {
 try {
  is.close();
 } catch (IOException e) {
  // ignore
 }
}

Исключение из close() здесь явно отлавливается и игнорируется, чтобы не перебивать исходную ошибку.

try с ресурсами (вместо исключений в finally)

try (InputStream is = new FileInputStream("a.txt")) {
 readFromInputSteam(is);
}

В круглых скобках выделяются ресурсы с которыми будет работать этот блок. Их может быть несколько, в таком случае они перечисляются через точку с запятой. Гарантируется, что при выходе из блока все ресурсы будут освобождены, точнее, что на каждом из ресурсов будет вызван метод close(). Ресурс это любой объект реализующий интерфейс java.lang.AutoCloseable

package java.lang;
public interface AutoCloseable {
 void close() throws Exception;
}

Аналогично блоку finally это случится при любом раскладе, было исключение или не было. Здесь исключение из close() не перебьет собой исходное исключение, а будет добавлено в него в качестве заглушенного. То что происходит в блоке try с ресурсами можно иллюстрировать следующим фрагментом кода, который не передает все нюансы, но демонстрирует идею.

InputStream is = new FileInputStream("a.txt");
try {
 readFromInputStream(is);
} catch (Throwable t) {
 try {
  is.close();
 } catch (Throwable t2) {
  t.addSuppressed(t2);
 }
 throw t;
}
is.close();


Комментариев нет:

Отправить комментарий