Разумно ли использовать дженерики для исключений? - PullRequest
12 голосов
/ 25 июля 2011

Моя команда занимается очисткой нашего использования throws Exception и удаляет или заменяет их с конкретными исключениями.

Обычные броски происходят потому, что объект не был найден.Должны ли мы генерировать общий NotFoundException или конкретный SomeClassNotFoundException для каждого класса сущностей?

Если мы должны генерировать конкретное исключение, должны ли мы создавать определенный класс исключений для каждого типа сущности?Можем ли мы безопасно использовать дженерики?Например, class NotFoundException<T extends EntityBaseClass> extends Exception, и тогда конструктор позаботится о том, чтобы объявить, с каким типом сущности мы имеем дело?

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

Ответы [ 5 ]

23 голосов
/ 25 июля 2011

Не разрешается делать общие исключения - они не компилируются ( JLS §8.1.2 ):

Ошибка времени компиляции, если универсальный класс является прямым или косвенным подклассом Throwable

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

11 голосов
/ 25 июля 2011

Простой лакмусовый тест для вопроса

Должны ли мы создавать определенный класс исключений для каждого типа сущности?

равен

Есть ли какие-либо обстоятельства, когда нам нужно было бы написать предложение catch, которое будет перехватывать исключение "не найдено", генерируемое некоторым классом X , а не любым другим классом ?

Если ответ «да», то отдельный ClassXNotFoundException оправдан;в противном случае это, вероятно, не так.

Что касается второй половины вашего вопроса, язык не разрешает использование обобщений для типов исключений.

5 голосов
/ 25 июля 2011

Вместо использования:

public Class EntityNotFoundException<T extends EntityBaseClass> extends Exception {

}

Вы должны использовать:

public Class EntityNotFoundException extends Exception {
    private Class<? extends EntityBaseClass> clazz;

    public EntityNotFoundException(Class<? extends EntityBaseClass> clazz) {
        this.clazz = clazz;
    }

    . . .
}

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

throw new EntityNotFoundException(Customer.class);

Компилятор подтвердит, что Customer расширяет EntityBaseClass.

5 голосов
/ 25 июля 2011

Должны ли мы создавать определенный класс Exception для каждого типа сущности?

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

Можем ли мы безопасно использовать дженерики?Как и этот класс, NotFoundException расширяет Exception, а затем конструктор заботится о том, чтобы объявить, с каким типом сущности мы имеем дело?

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

Даже если вы определите тип исключения MyParameterizedException<T>, то из-за стирания типа вызывающая сторона не сможет выполнить

 try {
   callYourCode();
 } catch (MyParameterizedException<TypeA> ex) {
   // some handling code
 } catch (MyParameterizedException<TypeB> ex) { 
   // some different handling code for type b
 }

, поскольку при стирании типа это выглядит как

 try {
   callYourCode();
 } catch (MyParameterizedException ex) {
   // some handling code
 } catch (MyParameterizedException ex) { 
   // some different handling code for type b
 }

и второй блок catch будет недоступным кодом и будет отклонен во время компиляции на javac.Первый блок catch будет введен для типа b и типа a (а также для любых других типов).

Если мы должны генерировать конкретное исключение и не использовать обобщенные значения, если эти исключения будут расширяться илиреализовать NotFoundException абстрактный класс или интерфейс?

Если вызывающие ваш код будут удивлены, если они этого не сделают, то да.

Если получатели вашего кода получат выгоду отобработка сбоев объектов с помощью кода, который обрабатывает другие NotFoundException s, тогда да.

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

0 голосов
/ 25 июля 2011

Я думаю, что каждый ответ говорит, что вам не нужно конкретное исключение.Я смотрел на то, как Hibernate определяет не найденное исключение.Я обнаружил EntityNotFoundException Я бы добавил, что вы НЕ должны даже создавать свое собственное исключение, просто используйте это повторно.Это расширяет RuntimeException, что означает, что вы не заставляете людей ловить его.Но если вы хотите, то можете повторно использовать существующий класс в J2EE.Что всегда лучше, чем писать новый код.

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