2014-12-22 4 views
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

Как вы заключаете код «неправильно»? Вы получили сообщение об ошибке? Неожиданный результат? – usr2564301

+0

Что вы имеете в виду, что не так? Вы получили сообщение об ошибке? Или это ведет себя иначе, чем вы ожидаете? – fejese

ответ

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 и второй, что может привести к тому, что оба условия будут оцениваться как ложные. Поэтому компилятор не может точно знать, что одно из условий будет выполнено, даже если они были логически дополняющими друг друга.

+0

@LuiggiMendoza Как насчет сейчас? – khelwood

+0

Да, теперь ты совершенно прав. –

+0

Это лучший ответ, потому что на самом деле упоминается случай, когда 'this.power = p' могут быть ложными. –

1

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

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

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

if(x>5){ 
return true; 
} 
else if(x < 5){ 
return false; 
} 
+0

Но почему? Посмотрите на условия. –

+1

@KirkWoll резьба. – Kevin

+4

Да, резьба, или 'NaN'. –

2

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

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

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

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

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

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

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

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

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

Java Language Specification 8.4.7 "Method body" гласит:

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

Итак, компилятор просто проверяет, могут ли эти утверждения нормально работать.

JLS 14.9.1 "The if-then Statement":

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

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

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

С другой стороны, JLS 14.9.2 "The if-then-else Statement":

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

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

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

Смежные вопросы