Обработка фатальных исключений, сгенерированных в конструкторе - PullRequest
2 голосов
/ 11 марта 2011

Допустим, у меня есть класс, который должен выполнить некоторую работу по инициализации в своем конструкторе.Нет оснований полагать, что это не удастся, но если это произойдет, экземпляр (и, возможно, приложение; давайте рассмотрим их как два отдельных случая) останется в непригодном для использования состоянии без реальной надежды на восстановление в этой области (экземпляр или глобальный).

Каков рекомендуемый способ решения этой ситуации в Java?Восстановление исключения, заключенного в исключение времени выполнения, кажется естественным подходом, но есть ли какие-либо рекомендации или консенсус относительно того, какой тип исключения использовать для такой цели?

Ответы [ 4 ]

1 голос
/ 11 марта 2011

Если что-то в вашем конструкторе генерирует исключение, вы можете либо объявить его, чтобы оно генерировало сами исключения, либо заключить их в более общее исключение (например, свое собственное исключение InstantiateXxxxException).

Как правило, у вас есть несколько типов Throwable, которые имеют различное значение.
Я бы классифицировал их следующим образом:

  • Исключение (проверено): генерируется, когда состояние восстановимо или требуется дополнительная обработка
  • RuntimeException (не проверено): генерируется при возникновении непредвиденных исключений (например, NPE), приложение может по-прежнему находиться в стабильном состоянии, в зависимости от обработки и ситуации. Некоторые фреймворки (например, EJB) оборачивают каждое исключение в RuntimeException (или чаще его подклассы), чтобы сделать «более чистый» интерфейс.
  • Ошибка (не проверяется): это в основном генерируется, когда происходит что-то чрезвычайно плохое, что дестабилизирует приложение или даже JVM (например, OutOfMemoryError). В этом случае приложение, как правило, завершает работу, хотя вы, возможно, захотите их перехватить и по возможности выполнить некоторую специальную обработку (например, запись журнала и т. Д.).
0 голосов
/ 11 марта 2011

Если в конструкторе объекта выдается исключение, оно мало чем отличается от поиска исключения в вызове метода, за исключением того, что вы можете гарантировать, что ваш объект не был создан

NewObject obj = null;
try {
   obj = new NewObject() {
} catch (Throwable t) {
   // obj is null.
}

Возможность восстановления после такого исключения сильно зависит от выданного исключения. Проверенные исключения ожидаются, но встречаются нечасто; как правило, они легче всего оправиться от. Непроверенные исключения имеют дело с такими вещами, как деление на ноль (где ловить каждый возможный бросок было бы громоздким). Ошибки - это ситуации, когда программа может дать сбой из-за стандартных предположений о том, что обычная работа JVM не выполняется (например, возможность выделить больше памяти).

Возможно восстановление после определенных ошибок JVM; однако, ошибки, которые вы хотите устранить, и способы их восстановления должны быть тщательно спланированы. Обычно можно увидеть попытки восстановления после ошибок JVM при работе с нехваткой памяти (псевдо-Java-код следует)

Runtime runtime = Runtime.getRuntime();
while (true) {
  Cache myCache = new SomeCache();
  try {
    Message message = messages.getMessage();
    if (!(cache.hasKey(message))) {
      Result result = messageProcessor.getResult(message);
      cache.put(message, result);
    }
    message.getReplyChannel().send(cache.get(message));
  } catch (OutOfMemoryException e) {
    myCache.clear();
    runtime.gc();
    messages.putBack(message);
  }
}

Ценность такого решения сильно зависит от остальной части конструкции системы. Предполагая, что «кэш» имеет ограниченный максимальный размер, это все равно может быть полезно, если другой раздел программы начнет загружать память. Главное, чтобы ваши операции по освобождению памяти зависели от уже выделенных объектов, что не приведет к увеличению потребности системы в памяти, поскольку она пытается освободить память.

0 голосов
/ 11 марта 2011

Если все приложение остается в нестабильном состоянии, я предлагаю выйти из приложения напрямую, чтобы избежать дополнительных проблем.Просто выведите что-нибудь на system.err раньше.

Если только экземпляр будет в нестабильном состоянии, вы можете вызвать исключение во время выполнения, но я думаю, что это опасный способ, так как их не нужно будет ловитьисключение, и это может привести к некоторым проблемам позже.

Я предлагаю просто перебросить исключение или, может быть, обернуть его в другое с другой соответствующей информацией.Точный тип исключения будет сильно зависеть от регистра (нулевой указатель, недопустимое состояние, ошибка ввода-вывода и т. Д.)

0 голосов
/ 11 марта 2011

Это зависит от того, что идет не так.Я имею в виду, что если произойдет сбой из-за нулевых значений, тогда NullPointerexception и если вы встретите состояние, которое не ожидалось, то, вероятно, IllegalStateException.

Но я бы предложил вместо предоставления конструктора просто иметь статические фабричные методы, которые вы можете назватьи может справиться с такими сценариями изящно.Например,

public class A{
  private A() {}

  private init() { .. }

   public static A getNewInstance() { //  may be parameters if you want
      A a = new A();
      a.init();
  }
}

Я только что привел пример init, но у вас могут быть и другие альтернативы. Дело в том, что у вас может быть статический метод для работы с такими вещами, чем конструктор, если конструктор обрабатывает сложную логику.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...