Почему метод, который вызывает другой метод, который вызывает исключение RuntimeException, требует оператора return? - PullRequest
1 голос
/ 31 мая 2019

Почему недоступное утверждение не идентифицируется javac?

public int directThrow(){
     throw new RuntimeException();
    //Compiles fine
}

public int indirectThrow(){
    directThrow();
    // Missing Return Statement error
}

Ответы [ 2 ]

6 голосов
/ 31 мая 2019

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

Для directThrow компилятор смотрит на него и говорит: «Я вижу, что у вас есть оператор throw, поэтому метод здесь внезапно завершится, тогда нет необходимости в выражении return!»

Для indirectThrow компилятор смотрит на него и говорит: «Я вижу только вызов метода. Привет, программист! Вам нужен оператор возврата!»

Компилятор не смотрит на то, что на самом деле делает directThrow. Я думаю, что это вполне разумно, потому что преимущество анализа того, что делает каждый вызываемый вами метод, действительно мало по сравнению с затратами на увеличение времени компиляции. Подумайте, что нужно проверить компилятору, чтобы directThrow всегда выдавал исключение. Самое главное, что это что-то отменяет? Вы можете даже проверить это? Можете ли вы даже убедиться, что ни один класс в будущем не будет наследовать ваш класс и переопределит этот метод (укажите, что ваш класс и directThrow оба не являются final)?

Если у вас есть какая-то сложная логика вызова исключений, которую вы хотите извлечь в метод, вы можете извлечь ее в метод, который возвращает Exception:

private Exception someComplicatedLogicThatGivesAnException() { ... }

public void foo() {
    if (...) {
        throw someComplicatedLogicThatGivesAnException();
    }
}
5 голосов
/ 31 мая 2019

Встречный вопрос: Что , если directThrow() был каким-то образом изменен, чтобы не вызывать исключение? Как должен код обрабатывать это?

Чтобы проиллюстрировать эту проблему, вот пример:

class Foo {
    int throwSomething() {
        throw new RuntimeException();
    }
}

class Bar extends Foo{
    int throwSomething() {
        return 1; // hahaaa, we don't throw but return normally
    }
}

См? Подкласс переопределяет базовый метод и возвращает что-то, как теперь должен обрабатывать код:

int indirectThrowing(Foo foo) {
    foo.throwSomething();
}

Если мы передадим new Foo(), он сгенерирует ожидаемый результат, но если мы передадим new Bar(), он просто вернет 1. И таким образом это не подведет.

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

return directThrow();

Потому что directThrow() имеет тип возврата int, и поэтому вы просто передаете аргумент вверх.

Обратите внимание, что некоторые языки, такие как Kotlin, обрабатывают это с помощью Nothing (иногда называемого также Never) возвращаемого типа. Чтобы указать компилятору, что метод никогда не сможет нормально возвращаться.

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