переопределенный метод не создает исключение


У меня есть проблема при компиляции моего кода, я пытаюсь сделать метод класса throw персонализированным исключением, учитывая некоторые условия. Но в момент компиляции я получаю сообщение:

Переопределенный метод не вызывает исключения

Вот объявление класса и исключения:

public class UNGraph implements Graph

Graph является интерфейсом со всеми методами UNGraph в нем (метод getId() не имеет объявления throws на этом скрипте)

После конструктора I создайте исключение (внутри класса UNGraph):

public class NoSuchElementException extends Exception {
    public NoSuchElementException(String message){
        super(message);
    }
}

Вот метод с исключением

public int getId(....) throws NoSuchElementException {
    if (condition is met) {
        //Do method
        return variable;
    }
    else{
       throw new NoSuchElementException (message);
    }
}
Очевидно, я не хочу, чтобы метод создавал исключение каждый раз, когда условие не выполняется; и когда оно выполняется, я хочу вернуть переменную.
3 7

3 ответа:

Компилятор выдает ошибку, так как Java не позволяет переопределить метод и добавить проверяемое исключение (любое пользовательское пользовательское исключение, расширяющее класс Exception). Поскольку ясно, что вы хотите обработать сценарий, в котором некоторое условие не встречается как неожиданное событие (ошибка), ваш лучший вариант-бросить RuntimeException. A RuntimeException, такие как: IllegalArgumentException или NullPointerException, не обязательно должны быть включены в сигнатуру метода, поэтому вы облегчите компилятор ошибка.

Я предлагаю внести следующие изменения в ваш код:

//First: Change the base class exception to RuntimeException:
public class NoSuchElementException extends RuntimeException {
    public NoSuchElementException(String message){
        super(message);
    }
}

//Second: Remove the exception clause of the getId signature
//(and remove the unnecessary else structure):
public int getId(....) {
    if ( condition is met) { return variable; }
    //Exception will only be thrown if condition is not met:
    throw new NoSuchElementException (message);
}

Проблема становится ясной, когда у вас есть такой код, как этот, используя ваш класс и интерфейс:

Graph g = new UNGraph();
int id = g.getId(...);

Интерфейс Graph не объявляет, что он вызывает проверяемое исключение NoSuchElementException, поэтому компилятор разрешил бы этот код без блока try или предложения throws на любом методе, в котором находится этот код. Но переопределяющий метод явно может бросить проверенное исключение; он объявил столько же. Это является причиной того, что переопределяющий метод не может выдавать больше проверенных исключений, чем переопределенный или абстрактный метод. Существует разница в том, как вызывающий код должен обрабатывать проверенные исключения, в зависимости от фактического типа объекта.

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

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

Вы можете прочитать больше в спецификация языка Java:

11.2. Проверка исключений во время компиляции

Язык программирования Java требует, чтобы программа содержала обработчики для проверяемых исключений, которые могут возникнуть в результате выполнения метода или конструктора. Для каждого проверенного исключение, которое является возможным результатом, предложение throws для метода (§8.4.6) или конструктор (§8.8.5) необходимо указать класс этого исключения или один из суперклассов класса этого исключения.(§11.2.3). Эта проверка во время компиляции на наличие обработчиков исключений предназначена для уменьшения числа исключений, которые не обрабатываются должным образом. Проверенные классы исключений (§11.1.1) названные в предложении throws являются частью контракт между исполнителем и пользователем метода или конструктора. Предложение throws переопределяющего метода не может указывать, что этот метод приведет к созданию любого проверяемого исключения, которое переопределенный метод не может создать своим предложением throws (§8.4.8.3).

Пока я этим занимаюсь, вам, вероятно, не следует использовать NoSuchElementException, поскольку это используется в JRE... используйте другое имя.