Java распознает бесконечные циклы?

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

public class WeirdStuff {

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

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

Это - действительная программа Java, хотя метод doSomething () должен возвратить интервал, но никогда не делает. При выполнении его это закончится в бесконечном цикле. При помещении аргумента цикла с условием продолжения в отдельной переменной (например, булевская переменная bool = верный), компилятор скажет Вам возвращать интервал в этом методе.

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

25
задан leifg 24 December 2009 в 14:45
поделиться

8 ответов

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

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

...

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

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

...

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

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

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

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

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

 class DizzyDean {
int pitch () {выбросить новое исключение RuntimeException ("90 миль в час ?!"); }
}
19
ответ дан 28 November 2019 в 21:13
поделиться

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

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

. ]
0
ответ дан 28 November 2019 в 21:13
поделиться

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

.
1
ответ дан 28 November 2019 в 21:13
поделиться

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

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

Читая немного больше, вы также спрашиваете, почему функция 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); не игнорируется компилятором как недоступный, иначе это приведет к ошибке во время компиляции!

.
7
ответ дан 28 November 2019 в 21:13
поделиться

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

.
13
ответ дан 28 November 2019 в 21:13
поделиться

After rereading the question....

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

boolean moo = true;
while (moo);

Полезно ли это? Сомнительно.

0
ответ дан 28 November 2019 в 21:13
поделиться

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

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

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

Я так не думаю, за исключением, возможно, непонятных юнит-тестов.

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

.
1
ответ дан 28 November 2019 в 21:13
поделиться

Некоторые примечания о недостижимых операторах:

В спецификациях java2 можно найти описание «недостижимого оператора». Особенно интересно следующее предложение:

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

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

0
ответ дан 28 November 2019 в 21:13
поделиться
Другие вопросы по тегам:

Похожие вопросы: