Питання 1:
Чому наступний код складається без заяви про повернення?
public int a()
{
while(true);
}
Це стосується JLS§8.4.7 :
Якщо метод оголошено типом повернення (§ 8.4.5), тоді виникає помилка часу компіляції, якщо тіло методу може нормально завершити (§14.1).
Іншими словами, метод з типом повернення повинен повертатися лише за допомогою оператора return, який забезпечує повернення значення; метод не дозволяє "скидати кінець свого тіла". Точні правила щодо операторів повернення в тілі методу див. У § 14.17.
Можливо, що метод має тип повернення, але ще не містить висловлювань повернення. Ось один із прикладів:
class DizzyDean {
int pitch() { throw new RuntimeException("90 mph?!"); }
}
Оскільки компілятор знає, що цикл ніколи не припиняється ( true
звичайно, завжди правда), він знає, що функція не може "повернутися нормально" (випасти з кінця тіла), і тому добре, що немає return
.
Питання 2:
З іншого боку, чому складається наступний код,
public int a()
{
while(0 == 0);
}
навіть якщо наступне не робить.
public int a(int b)
{
while(b == b);
}
У 0 == 0
випадку, компілятор знає, що цикл ніколи не припиняється (це 0 == 0
завжди буде правдою). Але це не знає b == b
.
Чому ні?
Укладач розуміє постійні вирази (§15.28) . Цитуючи §15.2 - Форми виразів (оскільки дивно це речення не в §15.28) :
Деякі вирази мають значення, яке можна визначити під час компіляції. Це постійні вирази (§15.28).
У вашому b == b
прикладі, оскільки існує змінна, вона не є постійним виразом і не визначається для визначення під час компіляції. Ми можемо бачити, що в цьому випадку це завжди буде правдою (хоча якби це b
було double
, як вказував QBrute , ми могли б легко обдурити Double.NaN
, що не==
є самим собою ), але JLS лише вказує, що постійні вирази визначаються під час компіляції , це не дозволяє компілятору спробувати оцінити непостійні вирази. bayou.io підняв хорошу точку, чому ні: Якщо ви починаєте йти по дорозі, намагаючись визначити вирази, що містять змінні, під час компіляції, то де зупиняєтесь? b == b
очевидно (е, для не-NaN
значення), а як бути a + b == b + a
? Або (a + b) * 2 == a * 2 + b * 2
? Малювати лінію на константах має сенс.
Отже, оскільки він не "визначає" вираз, компілятор не знає, що цикл ніколи не припиняється, тому вважає, що метод може повернутися нормально - чого не дозволяється робити, оскільки його потрібно використовувати return
. Тож скаржиться на відсутність а return
.