Полезно ли использовать дженерики для исключений?

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

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

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

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

Ответ 1

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

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

является

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

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

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

Ответ 2

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

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

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

Ответ 3

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

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

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

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

Даже если вы определяете тип исключения 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 и введите объекты (и любые другие типы).

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

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

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

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

Ответ 4

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

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;
    }

    . . .
}

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

throw new EntityNotFoundException(Customer.class);

Компилятор будет проверять, что клиент расширяет EntityBaseClass.

Ответ 5

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