Исключение против использования собственного исключения - PullRequest
26 голосов
/ 26 октября 2008

В какой момент вы создадите свой собственный класс исключений по сравнению с использованием java.lang.Exception? (Все время? Только если он будет использоваться вне пакета? Только если он должен содержать продвинутую логику? И т.д ...)

Ответы [ 10 ]

25 голосов
/ 26 октября 2008

Я думаю, вам нужно задать себе немного другой вопрос: «Какое преимущество дает мне или разработчикам, использующим мой код, создание нового исключения?» На самом деле единственное преимущество, которое он дает вам или другим людям, - это способность обрабатывать исключения. Это кажется очевидным ответом, но на самом деле это не так. Вы должны обрабатывать только те исключения, которые вы можете восстановить. Если исключение, которое вы выбрасываете, является поистине фатальной ошибкой, зачем давать разработчикам шанс неправильно с этим справиться?

Более подробное обсуждение: Пользовательские исключения: Когда их следует создавать?

11 голосов
/ 26 октября 2008

Причина первая:

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

В принципе, если кто-то должен написать:

catch(ExistingException e) {
  if({condition}) {
    { some stuff here}
  }
  else {
    { different stuff here}
  }
}

Вы, вероятно, хотите написать конкретное расширение; catch Exception match более понятен, чем условные выражения, ИМХО.

Помните: ваше новое исключение может быть подклассом RuntimeException

Причина вторая:

Консолидация API. Если вы пишете интерфейс и у вас есть несколько реализаций, возможно, что они будут вызывать разные API с целой кучей разных не-RuntimeExceptions:

interface MyInterface {
  void methodA();
}

class MyImplA {
  void methodA() throws SQLException { ... }
}

class MyImplB {
  void methodA() throws IOException { ... }
}

Вы действительно хотите, чтобы MyInterface.methodA генерировал SQLException и IOException? Может быть, тогда имеет смысл обернуть возможные исключения в пользовательское исключение. Который снова может быть RuntimeException. Или даже само RuntimeException ...

8 голосов
/ 26 октября 2008

Я считаю, что:

catch (Exception e) {
   ...
}

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

Почему:

try {
   if(myShape.isHidden()) {
      throw new Exception();
   }
   // More logic
} catch (Exception e) {
   MyApp.notify("Can't munge a hidden shape");
}

Итак, вы попробуете это, и из-за ошибки кодирования myShape имеет значение null. NullPointerException генерируется, когда среда выполнения пытается разыменовать myShape. Этот код сообщает о скрытой фигуре, когда он должен сообщать о нулевом указателе.

Либо создайте собственное исключение, либо найдите подходящее специализированное исключение в API. Это не так, как будто расширение Exception или RuntimeException обременительно.

7 голосов
/ 26 октября 2008

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

6 голосов
/ 26 октября 2008

ЕСЛИ существует исключение с языковой средой выполнения или библиотеками, используйте его, иначе создайте свое собственное, хорошо документируйте, и это должно работать в 99% случаев.

4 голосов
/ 26 октября 2008

Программное обеспечение фиксирует значение.

Почти нет причин для исключения существующего исключения: JVM уже сделает это за вас. Ваша версия их исключения не совсем точна, и выкинуть «Исключение» тоже не имеет смысла.

Возможно, у вас DataFormatException из-за написанного вами алгоритма синтаксического анализа. Это, однако, редко.

Когда ваша программа сталкивается с исключительной ситуацией, она почти всегда уникальна для вашей программы. Зачем принудительно вписывать вашу исключительную ситуацию в существующее исключение? Если это уникально для вашей программы, тогда ... ну ... это уникально. Назовите это так.

Однако не указывайте уникальный класс исключений для каждого уникального сообщения. Одно исключение class может иметь много вариантов сообщений и вспомогательных деталей.

Практическое правило Python, переведенное на Java, должно определять любые уникальные исключения на уровне пакета. [В Python они предлагают исключения на уровне «модуля», что точно не переводится на Java.]

2 голосов
/ 26 октября 2008

Всегда начинайте с использования общих классов исключений, а затем, когда возникает необходимость специально обработать его, измените его.

  1. При первом создании метода просто разрешите исключения.

  2. Если есть исключения, которые должны быть обработаны, они могут быть либо просто определены в бросках, либо перенесены в какое-то исключение времени выполнения, либо заключены в исключение собственных бросков. Я предпочитаю исключения во время выполнения во многих случаях. Следует избегать определения определения бросков до тех пор, пока оно не понадобится с точки зрения API.

  3. Позже, когда появляется необходимость выполнить определенную обработку для исключения в каком-либо вызывающем объекте, вернитесь и создайте для него новое исключение.

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

1 голос
/ 26 октября 2008

Я не могу себе представить, как можно вызвать исключение java.lang.Exception, если у какого-либо объекта / класса / метода возникла проблема Это слишком универсально - если вы не собираетесь создавать свой собственный класс Exception, мне кажется, что в API должен быть хотя бы более конкретный тип Exception.

0 голосов
/ 26 октября 2008

Я бы использовал исключения из API Java, когда исключение относится к API. Но если возникает исключительная ситуация, которая уникальна для моего собственного API, я создам для нее исключение. Например, если у меня есть объект Range с двумя свойствами min и max и инвариантом min <= max, я создам исключение InvalidRangeException. </p>

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

0 голосов
/ 26 октября 2008

В большинстве случаев не имеет смысла создавать собственный класс исключений.

У начинающих программистов существует тенденция создавать свои собственные классы исключений просто для того, чтобы они могли использовать имя, которое больше указывает на тип ошибки. Таким образом, вы найдете классы, такие как FTPInitializationException, DAOFactoryException и т. Д., Даже если такие исключения не обрабатываются иначе, чем стандартные исключения. Это явно анти паттерн, которого следует избегать.

...