Что не так с моим ответом?

1

Почему этот код неправильный? Когда я изменяю "else if(this.power >= p)" только в "else", это правильно. Может ли кто-нибудь дать мне подсказку?

public boolean useBattery(double p) {
    if(this.power < p) {
        this.power = 0.0;
        return false;
    } else if(this.power >= p) {
        this.power = this.power - p;
        return true;
    }
}
  • 0
    Похоже, не все пути покрыты. Обязательно всегда используйте return как последний оператор в вашем методе, избегайте использования нескольких операторов return каждой ветви.
  • 0
    Как вы решили, что код «неправильный»? Вы получаете ошибку? Неожиданный вывод?
Показать ещё 4 комментария
Теги:
if-statement

4 ответа

5
Лучший ответ

Для читателя-человека, смотрящего на код, кажется, что либо первое return будет удалено, либо второе, но компилятор не может быть уверен. Для компилятора это выглядит так:

 if (condition1) {
     ...
     return false;
 } else if (condition2) {
     ...
     return true;
 }

и он должен знать, что будет возвращать метод, если ни condition1 ни condition2 являются истинными?

Если вы измените его на else,

if (condition1) {
    ...
    return false;
} else {
    ...
    return true;
}

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

Фактически в вашем методе есть вероятность, что ни одно условие не будет выполнено: если один из чисел, которые вы сравниваете, - NaN (специальное значение с плавающей запятой, представляющее "не число"), тогда оба ваших условия if будут ложными, и метод не будет иметь возвращаемого значения.

Существует также теоретически возможность того, что некоторый код, запущенный в другом потоке, может изменить значение this.power между первым, if проверить, и вторым, что может привести к тому, что оба условия оцениваются как false. Поэтому компилятор не может точно знать, что одно из условий будет выполнено, даже если они логически дополняют друг друга.

  • 0
    @LuiggiMendoza Как насчет сейчас?
  • 0
    Да, теперь ты совершенно прав.
Показать ещё 2 комментария
2

Что произойдет, если мы не войдем в ваши условные ветки? Java не может определить, что вы сможете, потому что else if подразумевается, что не может быть другой условной ветки для проверки.

Выписано другим способом, есть неявный блок else, который ничего не делает. Поскольку вы объявляете тип возврата, наличие этого неявного блока else ничего не представляет собой ошибку.

Блок else всегда гарантированно исполняется, поэтому вы не столкнетесь с той же ситуацией с else, что, вероятно, является тем, что вы намеревались использовать в первую очередь.

Подумайте в случае блок-схемы.

  • Если (this.power < p), то
    • Установите power на 0
    • Вернуть false
  • this.power >= p если (this.power >= p), то
    • Вычесть p из power
    • Вернуть true
  • Другие (подразумеваемые)
    • Ничего не делать <- это ошибка
1

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

Рассмотрим этот простой пример:

Рассмотрим x = 5; ниже код не будет соответствовать запросу return, потому что он не удовлетворяет никакому условию.

if(x>5){
 return true;
}
else if(x < 5){
 return false;
}
  • 0
    Но почему? Посмотри на условия.
  • 1
    @KirkWoll Threading.
Показать ещё 4 комментария
1

Вы можете воспроизвести эту ошибку с еще более коротким кодом:

 public int doSomething() {
    if(true) {
        return 0;
    }
 }

Этот метод генерирует ошибку компилятора missing return statement

Компилятор не выполняет интеллектуальный статический анализ вашего кода. Он просто проверяет утверждения в соответствии со спецификацией.

Спецификация языка Java 8.4.7 "Тело метода" гласит, что:

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

Таким образом, компилятор просто проверяет, могут ли эти операторы нормально работать.

JLS 14.9.1 "Заявление if-then":

Если значение истинно, то выполняется исполняемый оператор; инструкция if-then выполняется нормально тогда и только тогда, когда выполнение Statement завершается нормально.

Если значение равно false, никаких дальнейших действий не предпринимается, и инструкция if-then выполняется нормально.

Как вы можете видеть по спецификации, если оператор может завершиться нормально. Вот почему возникает ошибка времени компиляции.

С другой стороны, JLS 14.9.2 "Заявление if-then-else":

Если значение истинно, тогда выполняется первый содержащийся оператор (один до ключевого слова else); оператор if-then-else обычно заканчивается тогда и только тогда, когда выполнение этого оператора завершается нормально.

Если значение равно false, тогда выполняется второй оператор (один после ключевого слова else); оператор if-then-else обычно заканчивается тогда и только тогда, когда выполнение этого оператора завершается нормально.

Как вы можете видеть, если-then-else завершается тогда и только тогда, когда один из его блоков завершается нормально. В вашем примере оба из них содержат операторы return.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню