Reputation: 992
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
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
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
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