Keven M
Keven M

Reputation: 992

While loop with no purpose?

While working through a Java tutorial book, I came across this piece of code:

while(getImage().getWidth(frame) <= 0);

I at first thought this was a typo, but it is repeated several times throughout the book, in multiple places. There is unfortunately no explanation as to what it does, so I was wondering what the purpose is. At face value, I know it basically does nothing, as even though it can return either true or false, there is no body to the while statement. Is this a special syntax case where it does, in fact, do something? Or is this just pointless code that happens to not negatively affect the flow of the code (it doesn't return any errors, and everything runs as expected).

Here is the full method which this comes from, in case it helps:

public void load(String filename)
{
    Toolkit tk = Toolkit.getDefaultToolkit();
    image = tk.getImage(getURL(filename));
    while(getImage().getWidth(frame) <= 0);
    double x = frame.getSize().width / 2 - width() / 2;
    double y = frame.getSize().height / 2 - height() / 2;
    at = AffineTransform.getTranslateInstance(x, y);
}

Upvotes: 2

Views: 104

Answers (3)

ajb
ajb

Reputation: 31689

The while loop will reevaluate the expression every time the program cycles through the loop. If the same expression involves a method call that could change value depending on the state of something else, then the while loop could make sense; there's nothing special about the syntax.

We're apparently dealing with a function that will return 0 or a negative number until something else happens. In Android, for instance, there's a getWidth() that will return 0 until a layout is rendered on the screen, by some other thread, and the width won't be computed until that happens. But using a busy loop to wait for things to happen is definitely the wrong approach on Android, and it's probably wrong in other contexts as well. And using a busy loop that doesn't pause for breath between checks is just terrible and could freeze an app.

But the other point is that although a loop like this is legal and sometimes useful, this is an awful way to write it. Much better would be

while (getImage().getWidth(frame) <= 0)
    ;

or

while (getImage().getWidth(frame) <= 0)
    /* nothing */ ;

or

while (getImage().getWidth(frame) <= 0) {
}

all of which make it clear to the reader that this isn't a typo (although the last makes it look like they were planning to add a body later but forgot to).

But, going past the readability issue, what you really want is probably more like

  while (getImage().getWidth(frame) <= 0) {
      try {
          Thread.sleep(100);
      } catch (InterruptedException e) {
          break;
      }

or if possible, use wait and notify, or various other synchronization methods.

Upvotes: 2

Peter Walser
Peter Walser

Reputation: 15706

Images obtained from the AWT Toolkit are loaded asynchronously, meaning that you get your Image instance before the image has finished loading. As long as the image is not fully loaded, its dimensions may not yet be known, and when you check the width and height of the Image, it returns negative values (-1,-1). The loop implementation polls the image dimension (or here: the width) until the image is loaded.

This is, of course, not the recommended approach (as it keeps a thread busy for nothing). Instead, the MediaTracker class can be used to wait until the image is fully loaded:

MediaTracker tracker = new MediaTracker(new Canvas());
tracker.addImage(image, 0);
try {
    tracker.waitForAll();
}
catch (InterruptedException ex) {}

Upvotes: 6

tmanion
tmanion

Reputation: 401

It is doing something called busy waiting. It's generally frowned upon and only should be used if there is no other way to determine when another task is completed.

Upvotes: 2

Related Questions