Является ли Java признаком бесконечных циклов?

Учитывая следующий пример кода:

public class WeirdStuff {

    public static int doSomething() {
        while(true);
    }

    public static void main(String[] args) {
        doSomething();
    }
}

Это допустимая программа Java, хотя метод doSomething() должен возвращать int, но никогда не делает этого. Если вы запустите его, он закончится бесконечным циклом. Если вы поместите аргумент цикла while в отдельную переменную (например, boolean bool = true), компилятор скажет вам вернуть int в этот метод.

Итак, мой вопрос: это где-то в спецификации Java и есть ли ситуация, когда это поведение может быть полезно?

Ответ 1

Я просто процитирую Специфика языка Java, так как это довольно ясно:

Этот раздел посвящен точному объяснению слова "достижимый". Идея состоит в том, что должен быть некоторый возможный путь выполнения от начала конструктора, метода, инициализатора экземпляра или статического инициализатора, который содержит инструкцию к самому утверждению. Анализ учитывает структуру утверждений. За исключением специальной обработки while, do и для операторов, выражение условия которых имеет постоянное значение true, значения выражений не учитываются при анализе потока.

...

Оператор while может завершиться нормально, если хотя бы одно из следующего верно:

  • Оператор while доступен и выражение условия не является постоянным выражением со значением true.
  • Существует допустимый оператор break, который завершает оператор while.

...

Каждая другая инструкция S в непустом блоке, которая не является блоком коммутатора, достижима, если утверждение, предшествующее S, может завершиться нормально.

Затем примените приведенные выше определения к this:

Если у метода объявлен тип возвращаемого значения, то каждый оператор возврата (§14.17) в своем теле должен иметь выражение. Ошибка времени компиляции возникает, если тело метода может нормально функционировать (§14.1).

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

Обратите внимание, что метод может иметь объявленный тип возврата и не содержать операторов возврата. Вот один пример:

class DizzyDean {
  int pitch() { throw new RuntimeException("90 mph?!"); }
}

Ответ 2

Спецификация Java определяет концепцию Недопустимые утверждения. Вам не разрешено иметь недопустимый оператор в вашем коде (это ошибка времени компиляции). Оператор while(true); делает следующие инструкции недоступными по определению. Вам даже не разрешено иметь оператор return после инструкции while(true); в Java. Обратите внимание, что в то время как проблема с остановкой неразрешима в общем случае, определение Unreachable Statement более строгое, чем просто остановка. Он решает очень конкретные случаи, где программа определенно не останавливается. Компилятор теоретически не в состоянии обнаружить все бесконечные циклы и недостижимые операторы, но он должен обнаруживать конкретные случаи, определенные в спецификации.

Ответ 3

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

Что касается вашего вопроса: "Может ли java распознать, когда цикл будет бесконечным?" Ответ заключается в том, что компьютер не может иметь алгоритм для определения того, будет ли программа работать вечно или нет. Читайте о: Проблема с остановкой

Читая немного больше, ваш вопрос также спрашивает, почему функция doSomething() не жалуется, что она не возвращает int.

Интересно, что следующий источник НЕ компилируется.

public class test {
  public static int doSomething() {                
   //while(true);
   boolean test=true;
   while(test){


   }
  }  
  public static void main(String[] args) {               
   doSomething();    
  }
}

Это указывает мне, что, как предполагает страница вики на проблеме остановки, невозможно, чтобы там был алгоритм, чтобы определить, прекратится ли каждая проблема, но это не означает, что кто-то не добавил простой случай:

while(true);

для спецификации java. Мой пример выше немного сложнее, поэтому Java не может запомнить его как бесконечный цикл. Поистине, это странный краевой случай, но он просто должен скомпилировать вещи. Может быть, кто-то попробует другие комбинации.

EDIT: не проблема с недостижимым кодом.

import java.util.*;

public class test {
  public static int doSomething() {                
   //while(true);
   while(true){
    System.out.println("Hello"); 
   }
  }  
  public static void main(String[] args) {               
   doSomething();    
  }
}

Вышеприведенные работы, поэтому while (true); не игнорируется компилятором как недостижимый, иначе он выдаст ошибку времени компиляции!

Ответ 4

Да, вы можете видеть эти "бесконечные" петли в некоторых потоках, например потоки серверов, которые прослушивают определенный порт для входящих сообщений.

Ответ 5

Итак, мой вопрос: это где-то в спецификации Java

Программа является юридической Java в соответствии со спецификацией. JLS (и компилятор Java) признают, что метод не может вернуться, и поэтому не требуется инструкция return. Действительно, если вы добавили инструкцию return после цикла, компилятор Java даст вам ошибку компиляции, потому что оператор return будет недостижимым.

и существует ли ситуация, когда это поведение может быть полезно?

Я так не думаю, кроме, возможно, в неясных модульных тестах.

Я иногда пишу методы, которые никогда не вернутся (обычно), но включение текущего потока в непрерывный бесконечный цикл занятости редко имеет смысл.

Ответ 6

После перечитывания вопроса....

Java понимает while (true); никогда не может завершиться полностью, он не полностью отслеживает следующий код.

boolean moo = true;
while (moo);

Это полезно? Сомнительно.

Ответ 7

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

Кроме того, что касается кода типа boolean x = true; while (x);, это скомпилируется с модификатором final на x. Я не знаю извинения, но я бы предположил, что это выбор Java разумного прямого анализа постоянных выражений (который должен быть определен прямо, поскольку из-за этого отказа от программ, зависящих от него, он является частью определения языка).

Ответ 8

Некоторые заметки о недостижимых утверждениях:

В java2 specs описание "недостижимого оператора" можно найти. Особенно интересно следующее предложение:

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

Таким образом, невозможно выйти из бесконечного цикла while (true);. Тем не менее, было еще два варианта: изменить кешированные значения или взломать непосредственно в файл класса или операционную память JVM.