Is it possible to declare a variable within a Java while conditional?
Asked Answered
B

3

15

In Java it is possible to declare a variable in the initialization part of a for-loop:

for ( int i=0; i < 10; i++) {
  // do something (with i)
}

But with the while statement this seems not to be possible.

Quite often I see code like this, when the conditional for the while loop needs to be updated after every iteration:

List<Object> processables = retrieveProcessableItems(..); // initial fetch
while (processables.size() > 0) {
    // process items
    processables = retrieveProcessableItems(..); // update
}

Here on stackoverflow I found at least a solution to prevent the duplicate code of fetching the processable items:

List<Object> processables;
while ((processables = retrieveProcessableItems(..)).size() > 0) {
    // process items
}

But the variable still has to be declared outside the while-loop.

So, as I want to keep my variable scopes clean, is it possible to declare a variable within the while conditional, or is there some other solution for such cases?

Bloodred answered 4/8, 2016 at 12:7 Comment(5)
There is a do-while loop which sounds like a good candidate in this case. The declaration will have to stay outside of the loop, but at least you will have only one assignment instead of two.Hearsh
@JaroslawPawlak - So, where would be the difference to my final while example above?Bloodred
Cleaner code. It wouldn't have assignment hidden in the boolean expression.Hearsh
@JaroslawPawlak Could you provide an answer with an example? Right now I'm unable to imagine how you mean that.Bloodred
There is no way to do such a thing, but you can try to use stream API to make your code functional styleCanker
D
23

You can write a while loop using a for loop:

while (condition) { ... }

is the same as

for (; condition; ) { ... }

since all three bits in the brackets of the basic for statement declaration are optional:

BasicForStatement:
    for ( [ForInit] ; [Expression] ; [ForUpdate] ) Statement

Similarly, you can just rewrite your while loop as a for loop:

for (List<Object> processables;
     (processables = retrieveProcessableItems(..)).size() > 0;) {
  // ... Process items.
}

Note that some static analysis tools (e.g. eclipse 4.5) might demand that an initial value is assigned to processables, e.g. List<Object> processables = null. This is incorrect, according to JLS; my version of javac does not complain if the variable is left initially unassigned.

Donnell answered 4/8, 2016 at 12:11 Comment(10)
Nicked your last idea. UV for sake of a clear conscience.Flexuous
Sorry, the for-loop reintroduces the duplicate-code problem, since it is necesarry to update the processables in the increment part of the statement: for (List<Object> processables = retrieveProcessableItems(..); processables.size() > 0; processables = retrieveProcessableItems(..))Bloodred
There ought to be no need for the initial assignment to null?Flexuous
@MarkusMitterauer then assign it in the Expression.Donnell
@Flexuous you're right. I've never actually tried that before; had to try it to convince myself!Donnell
I'm very sure, the [Expression] is evaluated at least once (unless an exception is thrown in the [ForInit])Flexuous
@Flexuous sorry, I wasn't meaning to sound like I disbelieved you :) Like I say, I've just never had cause to declare a variable without initialization in the [ForInit]. Tried it, checked the spec; of course, you are right.Donnell
@Flexuous - Yes, that would be possible. Except for the drawback that I now get either an "Null pointer access: The variable processables can only be null at this location" or "The local variable processables may not have been initialized" warning/error depending on initializing of the variable with null or not. (Eclipse 4.5 / Java 8)Bloodred
To me that's a defect in your IDE: it ought to know that something is always assigned to the variable before its contents are read. = null it is then.Flexuous
@Flexuous I've moved it out as a separate point, so it's easier to read the "not in error" answer. Thanks.Donnell
F
12

No it's not possible.

It doesn't really make too much sense either: unlike a for loop where you can set up the initial state of the "looping variable", in a while loop you test the value of an existing variable, akin to the conditional check of the for loop.

Of course, if you're concerned about variables "leaking" into other parts of your code, you could enclose the whole thing in an extra scope block:

{
   /*declare variable here*/
   while(...){...}
}

Alternatively, convert the while loop into a for loop.

Flexuous answered 4/8, 2016 at 12:10 Comment(2)
I think is better & cleaner than the accepted answer. Far more readable.Chapbook
@Chapbook While it might be cleaner, I just see it as workaround for my question. I knew of course that I can artificially restrict the scope of a variable with curly braces, but that was not what I asked for. The other answer dwelled more on the alternative solution with for which actually can substitute a while loop.Bloodred
N
0

Make a do/while:

String value;
do {
    value = getValue();
    ...your processing
} while (value != null && !value.isEmpty());
Narbonne answered 13/1, 2023 at 12:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.