views:

611

answers:

13

My question is about the Java for statement, e.g.

for (int i = 0; i < 10; ++i) {/* stuff */}

What I don't understand is precisely how much code / what kind of code I can put in the parentheses (i.e. where I have int i = 0; i < 10; ++i in my example)- I don't really understand the language used to describe it here:

http://java.sun.com/docs/books/jls/third_edition/html/statements.html#24588

Basically my question boils down to asking for a translation of the bits in the spec that look like:

ForInit: StatementExpressionList LocalVariableDeclaration

EDIT: Wow. I guess the real answer is "learn to read and understand the notation used in the JLS - it's used for a reason". Thank you for all the answers.

+3  A: 

Basically, for a simple FOR loop:

for (startCondition; endCondition; increment)

in startCondition, you set the starting value of the variable being used to run the loop; in many cases you will see it as i

int i = 0

In endCondition, you specify the comparison during which the loop keeps going. So, if you want to stop looping when i = 15, you would put

i <= 15

OR

i != 15

You could also do things like comparisons with booleans, such as

i == true

in increment, you specify by how much the counter variable should increment after each loop. If you want to simply increment by 1, you would put

i++

You can get a lot more complicated with more expressions in both startCondition and endCondition, and multiple counters, but this is a simple FOR loop.

Matthew Jones
But *what* precisely is allowed for each of the three?
I don't think endCondition need be a comparison. Also maybe I don't have a counter variable.
endCondition has to be a boolean test. When it becomes false the loop ends. startCondition and increment can be any statement you like, but generally you should use statements that make sense as loop initialization and increment. If you're doing something that doesn't fit easily into that pattern, use while instead.
Erika
yep endCondition could be 1 and you've an infinite loop :-)...serious answer follows
LB
Another example of a loop you could used is for(Iterator i = l.iterator(); i.hasNext();;) (Assuming you have a List variable called l). This example is mostly for Java 1.4, if using Java 5 a foreach loop is almost always preferred. For example, for(String s : l), assuming you have a list of String objects.
Elliot Vargas
+3  A: 

StatementExpressionList

means you can do:

int x = 0; 
int y = 0;
int z = 0;


for ( x++, y++; x+ y < z; z++) {
// whatever
}

where x++, y++ is the list the list of expressions. Basically statements you want executed at the start of the loop.

LocalVariableDeclaration looks like

int j = 0, i = 0, k = 0;

so

for ( int j = 0, i = 0, k = 0; i+j+k < 10; i++, j++, k++ ){
// whatever
}
Clint
+1  A: 

You can put

for(stmt a,stmt b, stmt,c.... ; stmt 1; alpha, beta, omega,...){}

where stmt : statement;

a, b, c and so on can be

definition of local variables, or other statements

for(int a=0,b=0;;){}

will declare and initlize both a and b to 0;

for(a=i,b=a+1;;){}

will assign a and b to those values

With iterators you could

 for(Iterator it= my_list.iterator();;){}

1, 2, 3 and so on must return boolean values,

so you can't put something like

 for (;a++;)

but you can

for (;a<b;)

or

for(;it.hasNext();)

which are basically a while loop.

or nothing at all :)

 for(int a=0;;a++)

As for the alpha, omega.. part, an assigment operator should be used

for(;;a){}

won't compile, but

for(;;a++){}
for(;;a=b;a++){}

will.

Then you have the foreach construct which is much simpler

for (A a:getAList())

and iterates all over the list, a having the current element. No control variable needed.

Tom
You can have a comma between declared variables in a single statement. However you can't have commas between statement or expressions. In C `a, b` is an expression where a is evaluate then b with the value of b returned. Java does not do that.
Tom Hawtin - tackline
You're right. Thanks.
Tom
A: 
for(startCondition(s); endCondition(s); Action) {}

As long as startCondition(s), and endCondition(s) are evaluated as booleans (true or false, 1 or 0 depending on language), you can have as "long" a list of conditions as needed.

Sev
A: 

you can have a number of statements; then a single condition that gets evaluated on every cycle, and finally another set of statements

BlackTigerX
In the last part you can have multiple statements separated with , (comma), like for(int i=0,j=0;i<10;++i,++j){}
Gábor Hargitai
wasn't sure about the last one, thanks
BlackTigerX
+12  A: 

Both StatementExpressionList and LocalVariableDeclaration are defined elsewhere on the page. I'll copy them here:

StatementExpressionList:
        StatementExpression
        StatementExpressionList , StatementExpression

StatementExpression:
        Assignment
        PreIncrementExpression
        PreDecrementExpression
        PostIncrementExpression
        PostDecrementExpression
        MethodInvocation
        ClassInstanceCreationExpression

and

LocalVariableDeclaration:
        VariableModifiers Type VariableDeclarators

VariableDeclarators:
        VariableDeclarator
        VariableDeclarators , VariableDeclarator

VariableDeclarator:
        VariableDeclaratorId
        VariableDeclaratorId = VariableInitializer

VariableDeclaratorId:
        Identifier
        VariableDeclaratorId [ ]

VariableInitializer:
        Expression
        ArrayInitializer

There's not much point in following the grammar any further; I hope it's easy enough to read as it is.

What it means is that you can have either any number of StatementExpressions, separated by commas, or a LocalVariableDeclaration in the ForInit section. And a LocalVariableDeclaration can consist of any number of "variable = value" pairs, comma-separated, preceded by their type.

So this is legal:

for (int i = 0, j = 0, k = 0;;) { }

because "int i = 0, j = 0, k = 0" is a valid LocalVariableDeclaration. And this is legal:

int i = 0;
String str = "Hello";
for (str = "hi", i++, ++i, sayHello(), new MyClass();;) { }

because all of those random things in the initializer qualify as StatementExpressions.

And since StatementExpressionList is permitted in the update part of the for loop, this is valid too:

int i = 0;
String str = "Hello";
for (;;str = "hi", i++, ++i, sayHello(), new MyClass()) { }

Are you starting to get the picture?

Michael Myers
Ah ha. Okay, but you *can't* have (String s = "hello", int i =0;;)?
That is correct. Only one type is allowed in a LocalVariableDeclaration, but you can have as many of that type as you want.
Michael Myers
Interesting. This has been upvoted, un-upvoted, and then upvoted again.
Michael Myers
Some people just cant make up their minds.
Matthew Jones
+6  A: 

A word of caution: we expect to see very simple, very familiar contents in the parentheses. Going beyond

for (int i = 0; i < n; i++)

is likely to confuse future readers of your code. Sometimes you need to iterate in reverse order - even the starting and ending conditions cause trouble for many programmers (is it n, n-1, n+1? is it >0, >=0, ...?)

There are circumstances where it's appropriate to get elaborate. I'm just saying - be careful before you go there, consider simpler representations.

Carl Manaster
can I vote for this twice! ;)
Peter Lawrey
A: 

To translate the specs with a loop

for (initFor; endCondition; update)

startCondition is a list of statements whose values are discarded (including no statements). They specify LocalVariableDeclaration to note that if a local variable declaration is in the statements (e.g. int x = 0) then the local variable is "scoped" to the block of the for statement (that is the value will not be available outside the block or the for statement).

endCondition is a boolean expression. Again it is optional (if not there the loop goes on forever)

update is a list of statements, typically handling updates needed after each loop.

Kathy Van Stone
+2  A: 

The second statement in the for loop (the conditional) can be anything that evaluates to a boolean or Boolean. Normally, this is something like i < max, but it could also be hasMore(), (x > y) == bool, or something like myclient.getMapOfIntsToBools().get(i). So long as the result of the expression is a boolean, it doesn't matter how long it is.

The other two parts can essentially be any single statement: whatever it's final return type is, it is ignored (just as though it were on an empty line). The first statement is always executed precisely once, at the beginning of the first loop, while the other is executed at the end of every loop.

An alternative way of thinking about it is that this:

if (A; B; C){
  ...
}

turns into this:

A
while (B){
  ...
  C
}

A and C can be whatever single statement you want them to be (including nothing). B must be something that evaluates to a boolean.

James
A: 

You are getting a lot of responses that aren't really answering your question. The correct answer is you can put absolutely anything you want. You don't even need a valid end condition if you for loop has a break statement in it. You also don't need three statements as in the case of using an Iterator loop.

EDIT: OK, not quite right. You can't initialize a new variable after the first semi-colon.

jiggy
A: 

All three clauses of the for loop are optional, but the semicolon must be there.

In the first clause of the for loop, you can put any number of statements separated by commas. Or, in the alternative (but you can't mix) you can declare new variables of a single type available for the for loop (e.g. int i = 1, j= 2). Any variables declared here are available to the statement after the for loop (or statements if you use curly braces).

The second clause of the for loop is a single statement that returns a boolean value. This will be evaluated to consider if the for loop should continue.

The third clause of the for loop can contain any number of statements separated by a comma, but cannot declare any variables.

Yishai
+1  A: 

BasicForStatement: for ( ForInitopt ; Expressionopt ; ForUpdateopt ) Statement

a for statement is composed of a ForInit, an Expression and an ForUpdate, each of them being optional

ForInit: StatementExpressionList LocalVariableDeclaration A forInit is a list of Statements and Expressions separated with commas (see below) or a declaration of a local variable

ForUpdate: StatementExpressionList

A forUpdate is a list of Statements and Expressions separated with commas... Basically, you could put: Assignment
PreIncrementExpression PreDecrementExpression PostIncrementExpression PostDecrementExpression MethodInvocation ClassInstanceCreationExpression

StatementExpressionList: StatementExpression StatementExpressionList , StatementExpression

What is a Statement :

The sequence of execution of a program is controlled by statements, which are executed for their effect and do not have values.

Some statements contain other statements as part of their structure; such other statements are substatements of the statement. We say that statement S immediately contains statement U if there is no statement T different from S and U such that S contains T and T contains U. In the same manner, some statements contain expressions as part of their structure.

And an expression is

Much of the work in a program is done by evaluating expressions, either for their side effects, such as assignments to variables, or for their values, which can be used as arguments or operands in larger expressions, or to affect the execution sequence in statements, or both.

So basically you can have any valid java expression in the middle (you don't need a comparison) but still this expression must return a boolean...

LB
A: 

You may find that the for each notation is often simpler and clearer. I would suggest using the for each loop whenever this is appropriate. e.g.

for(Element element: arrayOfElement) { /* stuff */ }
// or
for(Element element: iterableOfElement) { /* stuff */ }

Collection, Set and List are Iterable, but you can make your own.

Peter Lawrey