[java] Are "while(true)" loops so bad?

I've been programming in Java for several years now, but I just recently returned to school to get a formal degree. I was quite surprised to learn that, on my last assignment, I lost points for using a loop like the one below.

do{
     //get some input.
     //if the input meets my conditions, break;
     //Otherwise ask again.
} while(true)

Now for my test I'm just scanning for some console input, but I was told that this kind of loop is discouraged because using break is akin to goto, we just don't do it.

I understand fully the pitfalls of goto and its Java cousin break:label, and I have the good sense not to use them. I also realize that a more complete program would provide some other means of escape, say for instance to just end the program, but that wasn't a reason my professor cited, so...

What's wrong with do-while(true)?

This question is related to java while-loop do-while

The answer is


AFAIK nothing, really. Teachers are just allergic to goto, because they heard somewhere it's really bad. Otherwise you would just write:

bool guard = true;
do
{
   getInput();
   if (something)
     guard = false;
} while (guard)

Which is almost the same thing.

Maybe this is cleaner (because all the looping info is contained at the top of the block):

for (bool endLoop = false; !endLoop;)
{

}

I guess using break to your teacher is like breaking a branch of tree to get the fruit,use some other tricks (bow the branch) so that you get the fruit and the branch is still alive.:)


To me, the problem is readability.

A while statement with a true condition tells you nothing about the loop. It makes the job of understanding it much more difficult.

What would be easier to understand out of these two snippets?

do {
  // Imagine a nice chunk of code here
} while(true);

do {
  // Imagine a nice chunk of code here
} while(price < priceAllowedForDiscount);

Back in 1967, Edgar Dijkstra wrote an article in a trade magazine about why goto should be eliminated from high level languages to improve code quality. A whole programming paradigm called "structured programming" came out of this, though certainly not everyone agrees that goto automatically means bad code.

The crux of structured programming is essentially that the structure of the code should determine its flow rather than having gotos or breaks or continues to determine flow, wherever possible. Similiarly, having multiple entry and exit points to a loop or function are also discouraged in that paradigm.

Obviously this is not the only programming paradigm, but often it can be easily applied to other paradigms like object oriented programming (ala Java).

Your teachers has probably been taught, and is trying to teach your class that we would best avoid "spaghetti code" by making sure our code is structured, and following the implied rules of structured programming.

While there is nothing inherently "wrong" with an implementation that uses break, some consider it significantly easier to read code where the condition for the loop is explicitly specified within the while() condition, and eliminates some possibilities of being overly tricky. There are definitely pitfalls to using a while(true) condition that seem to pop up frequently in code by novice programmers, such as the risk of accidentally creating an infinite loop, or making code that is hard to read or unnecessarily confusing.

Ironically, exception handling is an area where deviation from structured programming will certainly come up and be expected as you get further into programming in Java.

It is also possible your instructor may have expected you to demonstrate your ability to use a particular loop structure or syntax being taught in that chapter or lesson of your text, and while the code you wrote is functionally equivalent, you may not have been demonstrating the particular skill you were supposed to be learning in that lesson.


I would say that generally the reason it's not considered a good idea is that you are not using the construct to it's full potential. Also, I tend to think that a lot of programming instructors don't like it when their students come in with "baggage". By that I mean I think they like to be the primary influence on their students programming style. So perhaps that's just a pet peeve of the instructor's.


It's more of an aesthetics thing, much easier to read code where you explicitly know why the loop will stop right in the declaration of the loop.


It's bad in the sense that structured programming constructs are preferred to (the somewhat unstructured) break and continue statements. They are, by comparison, preferred to "goto" according to this principle.

I'd always recommend making your code as structured as possible... although, as Jon Skeet points out, don't make it more structured than that!


You might just use a Boolean flag to indicate when to end the while loop. Break and go to were reasons for software being to hard to maintain - the software-crisis(tm) - and should be avoided, and easily can be too.

It's a question if you are pragmatic or not. Pragmatic coders might just use break in that simple situation.

But it's good to get the habbit of not using them, else you might use them out of habbit in unsuitable situations, like in complicated nested loops where readability and maintainability of your code becomes harder by using break.


It's your gun, your bullet and your foot...

It's bad because you are asking for trouble. It won't be you or any of the other posters on this page who have examples of short/simple while loops.

The trouble will start at some very random time in the future. It might be caused by another programmer. It might be the person installing the software. It might be the end user.

Why? I had to find out why a 700K LOC app would gradually start burning 100% of the CPU time until every CPU was saturated. It was an amazing while (true) loop. It was big and nasty but it boiled down to:

x = read_value_from_database()
while (true) 
 if (x == 1)
  ...
  break;
 else if (x ==2)
  ...
  break;
and lots more else if conditions
}

There was no final else branch. If the value did not match an if condition the loop kept running until the end of time.

Of course, the programmer blamed the end users for not picking a value the programmer expected. (I then eliminated all instances of while(true) in the code.)

IMHO it is not good defensive programming to use constructs like while(true). It will come back to haunt you.

(But I do recall professors grading down if we did not comment every line, even for i++;)


1) Nothing is wrong with a do -while(true)

2) Your teacher is wrong.

NSFS!!:

3) Most teachers are teachers and not programmers.


I think that yes it is pretty bad... or at least, for many developers. It is symptomatic of developers that don't think about their loop conditions. Consequently there is error prone.


While not necessarily an answer as to why not to use while (true), I've always found this comic and accompanying author's statement a succinct explanation as to why to do while instead of do-while.

With regards to your question: There is no inherent problem with

while(true) {
   do_stuff();
   if(exit_time) {
      break;
   }
}

... if you know what you're doing and making sure that exit_time will at some point evaluate to true.

Teachers discourage you from using while(true) because until and unless you're at the point that you know exactly what you're doing, it's an easy way to make a critical mistake.


It might be bad if your loop runs on a background thread, so when you close your application by terminating a UI thread, that piece of code will continue to execute. As others already said, you should always use some kind of check to provide a way for cancellation.


It's not such a terrible thing, but you need to take into consideration other developers when coding. Even in school.

Your fellow developers should be able to see the exit clause for your loop, at the loop declaration. You didn't do that. You hid the exit clause in the middle of the loop, making more work for someone else who comes along and tries to understand your code. This is the same reason that things like "break" are avoided.

That being said, you'll still see things like this in a LOT of code out there in the real world.


The ususal Java convention for reading input is:

import java.io.*;
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String strLine;

while ((strLine = br.readLine()) != null) {
  // do something with the line
}

And the usual C++ convention for reading input is:

#include <iostream>
#include <string>
std::string data;
while(std::readline(std::cin, data)) {
  // do something with the line
}

And in C, it's

#include <stdio.h>
char* buffer = NULL;
size_t buffer_size;
size_t size_read;
while( (size_read = getline(&buffer, &buffer_size, stdin)) != -1 ){
  // do something with the line
}
free(buffer);

or if you're convinced you know how long the longest line of text in your file is, you can do

#include <stdio.h>
char buffer[BUF_SIZE];
while (fgets(buffer, BUF_SIZE, stdin)) {
  //do something with the line
}

If you're testing to see whether your user entered a quit command, it's easy to extend any of these 3 loop structures. I'll do it in Java for you:

import java.io.*;
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String line;

while ((line = br.readLine()) != null  && !line.equals("quit") ) {
  // do something with the line
}

So, while there certainly are cases where break or goto is justified, if all you're doing is reading from a file or the console line by line, then you shouldn't need a while (true) loop to accomplish it -- your programming language has already supplied you with an appropriate idiom for using the input command as the loop condition.


I use something similar, but with opposite logic, in a lot of my functions.

DWORD dwError = ERROR_SUCCESS;

do
{
    if ( (dwError = SomeFunction()) != ERROR_SUCCESS )
    {
         /* handle error */
         continue;
    }

    if ( (dwError = SomeOtherFunction()) != ERROR_SUCCESS )
    {
         /* handle error */
         continue;
    }
}
while ( 0 );

if ( dwError != ERROR_SUCCESS )
{
    /* resource cleanup */
}

Maybe I am unlucky. Or maybe I just lack an experience. But every time I recall dealing with while(true) having break inside, it was possible to improve the code applying Extract Method to while-block, which kept the while(true) but (by coincidence?) transformed all the breaks into returns.

In my experience while(true) without breaks (ie with returns or throws) are quite comfortable and easy to understand.


  void handleInput() {
      while (true) {
          final Input input = getSomeInput();
          if (input == null) {
              throw new BadInputException("can't handle null input");
          }
          if (input.isPoisonPill()) {
              return;
          }
          doSomething(input);
      }
  }

There's no major problem with while(true) with break statements, however some may think its slightly lowers the code readability. Try to give variables meaningful names, evaluate expressions in the proper place.

For your example, it seems much clearer to do something like:

do {
   input = get_input();
   valid = check_input_validity(input);    
} while(! valid)

This is especially true if the do while loop gets long -- you know exactly where the check to see if there's an extra iteration is occurring. All variables/functions have appropriate names at the level of abstraction. The while(true) statement does is tell you that processing isn't in the place you thought.

Maybe you want different output on the second time through the loop. Something like

input = get_input();
while(input_is_not_valid(input)) {
    disp_msg_invalid_input();
    input = get_input();
}

seems more readable to me then

do {
    input = get_input();
    if (input_is_valid(input)) {
        break;
    }
    disp_msg_invalid_input();
} while(true);

Again, with a trivial example both are quite readable; but if the loop became very large or deeply nested (which means you probably should already have refactored), the first style may be a bit clearer.


Douglas Crockford had a remark about how he wished JavaScript contained a loop structure:

loop
{
  ...code...
}

And I don't think Java would be any worse for having a loop structure either.

There's nothing inherently wrong with while(true) loops, but there is a tendency for teachers to discourage them. From the teaching perspective, it's very easy to have students create endless loops and not understand why the loop isn't ever escaped.

But what they rarely mention is that all looping mechanisms can be replicated with while(true) loops.

while( a() )
{
  fn();
}

is the same as

loop
{
  if ( !a() ) break;
  fn();
}

and

do
{
  fn();
} while( a() );

is the same as:

loop
{
  fn();
  if ( !a() ) break;
}

and

for ( a(); b(); c() )
{
  fn();
}

is the same as:

a();
loop
{
  if ( !b() ) break;
  fn();
  c();
}

As long as you can set up your loops in a way that works the construct that you choose to use is unimportant. If it happens to fit in a for loop, use a for loop.

One last part: keep your loops simple. If there's a lot of functionality that needs to happen on every iteration, put it in a function. You can always optimize it after you've got it working.


According to my experience in most cases loops have the "main" condition to continue. This is the condition that should be written into while() operator itself. All other conditions that may break the loop are secondary, not so important etc. They can be written as additional if() {break} statements.

while(true) is often confusing and is less readable.

I think that these rules do not cover 100% of cases but probably only 98% of them.


Examples related to java

Under what circumstances can I call findViewById with an Options Menu / Action Bar item? How much should a function trust another function How to implement a simple scenario the OO way Two constructors How do I get some variable from another class in Java? this in equals method How to split a string in two and store it in a field How to do perspective fixing? String index out of range: 4 My eclipse won't open, i download the bundle pack it keeps saying error log

Examples related to while-loop

While, Do While, For loops in Assembly Language (emu8086) MySQL Insert with While Loop Python loop to run for certain amount of seconds How to break a while loop from an if condition inside the while loop? How to find sum of several integers input by user using do/while, While statement or For statement Python: How to keep repeating a program until a specific input is obtained? Creating multiple objects with different names in a loop to store in an array list ORA-06502: PL/SQL: numeric or value error: character string buffer too small How to break out of a loop in Bash? for or while loop to do something n times

Examples related to do-while

How to find sum of several integers input by user using do/while, While statement or For statement WHILE LOOP with IF STATEMENT MYSQL Emulating a do-while loop in Bash JAVA - using FOR, WHILE and DO WHILE loops to sum 1 through 100 Are "while(true)" loops so bad? Do while loop in SQL Server 2008 do-while loop in R 'do...while' vs. 'while' How to emulate a do-while loop in Python?