I'm reading a Java book and I came across an interesting for loop. It looks like this:
for(; (j>0) && (tmp < a[j-1]); j--)
I understand that (j>0) && (tmp < a[j-1]) is the condition check and j-- is the decrease of the variable. However, I don't get where's the initialization statement.
There is no initialization statement in your example. It's optional.
j is probably declared and initialized before the loop.
Normally, you would initialize j in the first statement in the for loop (which is empty here) since it is a looping index and is usually only used inside the loop. Also the standard syntax for Java for loops is for( initialization; termination condition; increment), but the language only enforces that there be three statements (with the middle one being a boolean expression) , so you can have three empty statements for(;;) which creates an infinite loop or you could put some other statement in there (except for the middle expression where a boolean expression is expected) like for(System.out.println("I was supposed to initialize here"); false && true; logger.log("Nope.")). OF course, you shouldn't do that, but it is legal.
Note: Some statements would be illegal if put in place of the third statement as well, like variable declarations, since it is executed at the end of each iteration (see this for more on legal for loop syntax)
I like to think of for loops as a shorthand for a common form of the while loop, where you want to loop a number of times:
int i= 0; // Initialization
while (i< max){ // termination
// Do stuff
i++; // increment
}
which is helpful for understanding what it does with these statements.
for(initialization; condition; increment)
None of them are a must to declare a for loop. You can have a for loop like for(;;) if you want. It will compile without any errors.
According to your question j have been already initialized some where. Therefore it is perfectly fine.
Related
I've started to learn java, and in some examples I've seen special for loop (not very familiar to me). It's not enhanced for loop, but it looks like this
for(;;i++){ do something..}
I don't know what it means, when I just have these semicolons o.O If someone could explain it to me, would be grateful.
I would read through this: https://docs.oracle.com/javase/tutorial/java/nutsandbolts/for.html
As you might notice,
The general form of the for statement can be expressed as follows:
for (initialization; termination;
increment) {
statement(s)
}
...
The three expressions of the for loop are optional; an infinite loop can be created as follows:
// infinite loop
for ( ; ; ) {
// your code goes here
}
(emphasis mine)
In your example, I would expect the variable i would have been declared and initialized before the for loop. If there is no termination condition, the loop will run infinitely.
You can also have a termination condition inside a loop, something like :
if(i = some number) {break;} //this will break the loop
Similarly, the increment statement can also be declared inside a loop.
I was about to post a query but I solved it by reworking the code avoiding the issue but not answering it.
So below is an example of what I was wanting to do.
I had a for loop inside a do-while loop and wanted the do-while loop to run until a condition relating to the nested for loop was reached. The error I was getting was that i wasn't initialised so the while condition could not be run, which makes sense.
I was hoping to create a local variable outside the do-while loop and initialize it in the nested for loop. This obviously wasn't possible in the way I was trying to execute it but is there another way to 'post initialise' a variable in Java?
Also just out of curiosity what languages allow such post initialisation?
case 2:
int i;
do{
try{
for(i=0; i<array.length;i++){
if(...
}
}
catch(Exception e)
{
System.out.println(e.getMessage());
}
} while(!array[i].state.equals("X"));
break;
You can easily solve it by giving i an initial value when you declare it :
int i = 0;
You have to initialize de variable i before the do-while.
Inside the do-while loop you can reset the variable. Now you've already made it in the for condition.
On the other hand, I don't know what your code inside for made it and the logic of your algorithm, but I think that it's possible you have a infinite loop if there aren't any element with the state "X". I think that it is very posible indeed (of course depends of your algorithm) to remove the for loop and add the code in the do-while with a i++ and an end condition like this: while(!array[i].state.equals("X") && i < array.lengh);
1.
for (int i = 0; (boolean)true; i++) {
}
2.
for (int i = 0; (boolean)false; i++) {
}
3.
boolean t=false;
for (int i = 0; t; i++) {
}
The first for loop compiles & runs, but the second for loop compilation fails with error. It says Unreachable Statement. And the third for loop compiles & runs.
The first loop is infinite loop. Since the condition is always true, and will always be satisfied.
It's like writing:
int i=0;
while(true)
i++;
As you can see, the condition is always true and nothing changes this true.
The second loop is Unreachable code since the piece of code below this loop will never be reached (false is always false and you never change it). So it's redundant.
See Chapter 14.21. Unreachable Statements
Since Java knows that the programmer is human :) it notifies you about this to prevent mistakes.
Note that while(false) or the second loop you have differ from if(false)... since while(false) (or the loop you have) doesn't make sense because the code below it will no be execute. Not like if(false) that might have else, so the compiler doesn't complain about it in this case.
Regarding the OP update:
In the third case there will be no compilation error since the false value is assigned to the variable and in this case, the variable can be re-assigned to have true value in it. So the compiler doesn't arise an error.
Note that if the variable is declared as final then the compiler will arise an error since this variable can be never assigned to a new value, thus the code below the for loop will be unreachable.
for (int i = 0; <This_has_to_be_true>; i++)
The second part of the for loop has to be true for the loop to execute. Since you're manually setting it to be always fase, the loop will never run, hence the code inside it is unreachable.
The compiler is telling you the code inside the second loop (even if empty) will never be reached and executed, because the condition is always false.
BTW, why are you trying to do this anyway?
In the second for loop, the condition is always false so the for block (even if is empty) will never be executed (it is unreacheable).
Like in this case :
if (false) {
}
Say I have a simple PHP loop like this one
// Bad example
$array = array('apple','banana','cucumber');
for ($i = 1; $i < count($array); $i++) {
echo $array[$i];
}
I know this is a bad practice. It's better not using count() inside a loop.
// Nice example
$array = array('apple','banana','cucumber');
$limit = count($array);
for ($i = 1; $i < $limit; $i++) {
// do something...
}
In Java, I would do it this way
// Bad example?
String[] array = {"apple","banana","cucumber"};
for(int i = 0; i < array.length; i++){
System.out.println(array[i]);
}
Question: Isn't this above a bad practice too? Or it is just the same as the example below?
// Nice example?
String[] array = {"apple","banana","cucumber"};
int limit = array.length;
for(int i = 0; i < limit; i++){
System.out.println(array[i]);
}
Any decent compiler/interpreter should automatically optimise the first example to match the second (semantically speaking anyway, if not exactly literally), and probably the third to match the fourth. It's known as a loop invariant optimisation, where the compiler recognises that an entity (variable, expression, etc) does not vary within the loop (i.e. is invariant) and removes it to outside the loop (loosely speaking).
It's not bad practice at all anymore, if it ever was.
The "bad" examples you use are not equivalent, and thus are not comparable - even if they seem so on the surface. Using this description:
for (initialization; termination; increment) {
statement(s)
}
(which is descriptive of both PHP and java loops), the initialization statement is executed once, at the start of the loop. The termination statement and the increment are executed for each iteration of the loop.
The reason it is bad practice to use PHP's count in the termination statement is that, for each iteration, the count function call occurs. In your Java example, array.length is not a function call but a reference to a public member. Therefore, the termination statements used in your examples are not equivalent behavior. We expect a function call to be more costly than a property reference.
It is bad practice to place a function call (or call a property that masks a function) in the termination statement of a for loop in any language which has the described loop mechanics. That's what makes the PHP example "bad", and it would be equally bad if you used a count-type function in Java for loop's termination statement. The real question, then, is whether Java's Array.length does indeed mask a function call - the answer to that is "no" (see the potential duplicate question, and/or check out http://leepoint.net/notes-java/data/arrays/arrays.html)
The main difference is that count() is a function whereas array.length is a property and therefore not different from a limit variable.
They are not the same, in the Java "nice example" you are not calculating the length of the array every time. Instead, you are storing that in the limit variable and using that to stop the calculation instead of the result of calling the length function on the array every iteration through the for loop.
EDIT: Both of the things that you thought were "bad practice" are bad practice and the "nice examples" are the more efficient ways (at least in theory). But it is true that in implementation there will not be any noticeable difference.
In java this doesn't matter an array has this attribute as a constant (public final int).
The difference is in java arrays have a fixed size and can not grow so there would be no need to count the elements every time to access length.
In the following code, does the break statement break out of the if statement only or out of the for loop too?
I need it to break out of the loop too.
for (int i = 0; i < 5; i++) {
if (i == temp)
// do something
else {
temp = i;
break;
}
}
That would break out of the for loop. In fact break only makes sense when talking about loops, since they break from the loop entirely, while continue only goes to the next iteration.
An unlabelled break only breaks out of the enclosing switch, for, while or do-while construct. It does not take if statements into account.
See http://download.oracle.com/javase/tutorial/java/nutsandbolts/branch.html for more details.
It also goes out of the loop.
You can also use labeled breaks that can break out of outer loops (and arbitrary code blocks).
looplbl: for(int i=;i<;i++){
if (i == temp)
// do something
else {
temp = i;
break looplbl;
}
}
It breaks the loop, but why not explicitly put the condition in the for itself? It would be more readable and you would not have to write the if statement at all
(if i==temp then temp = i is totally pointless)
It will break out of the loop always.
Break never refers to if/else statements. It only refers to loops (if/while) and switch statements.
break is to break out of any loop.
Generally break statement breaks out of loops (for, while, and do...while) and switch statements.
In Java there are 2 variant of break.
1. Labeled break
It break outs of the outer loop where you put the lable.
breakThis: for(...){
for(...){
...
break breakThis; // breaks the outer for loop
}
}
2. Unlabeled break
It is the statement you used in your question.
It breaks the loop in which it is written. Generally inner loop.
It would break you out of the for loop. Generally break statement is used to optimise the running time of your program. Means when the given condition is met, use break statement so that it will take you out of the loop and ignores the remaining iterations.