Питання 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.