Why doesn't this method throw an ArrayIndexOutOfBoundsException? - java

I'm learning Java and I don't understand the following code.
public static void main(String[] args) {
try {
int numbers[] = new int[5];
int total = 0;
for(int i = 0; i < 5; i++) {
System.out.println(i);
total += numbers[i];
}
}
catch(Exception e) {
System.out.println("First Exception");
}
finally {
System.out.println("Yes");
}
}
Why doesn't Java throw an ArrayIndexOutOfBoundsException, since numbers[5] is not an existing element of the array? It has only indexes 0-4, right?

In for loop the increment happens after the iteration ends and only then the condition is done.
So in your case when i is 4 the condition will be true and the loop continues, when the iteration ends i will be incremented to 5 and the condition will be false so the loop will stop and the loop will never work when i=5

I think it helps if we rewrite the for loop to a while loop.
The for statement of the form
for (int i = 0; i < 5; i++) {
statements;
}
is equivalent1 to
int i = 0;
while (i < 5) {
statements;
i++;
}
As you can see, the update part of the for loop behaves as if it were the last statement of the loop body. So at the end of the iteration, i = 5 (right after i++ has been executed). Then the while condition is evaluated, which results in false and the loop is immediately ended.
So, yes, one could say that i has reached 5 (otherwise the loop condition would never be false), but i can never be accessed while it has the value 5.
The Java Language Specification, ยง 14.14.1 describes exactly how the basic for loop works.
1 The difference here is that if we rewrite it to a while statement, the i variable is in scope even when the loop has terminated. With a for statement, i is only in scope within the for clauses (ForInit, the for condition and ForUpdate) and the loop body.

Related

Making ArrayList Size equal to other Array Lists Available in Java

I have 2 ArrayLists of varying sizes. Example -
Array1.size() = 10
Array2.size() = 5
I want at all times these arrays to have same size. Thus, I have another class to ensure this. But obviously, it isn't working for me. Please help!
Below is that Class code -
for (int i = Array2.size(); i == Array1.size(); i++) {
Array2.add(i, "Test");
}
The above loop for just doesn't add 'Test' to the Array2 so it matches the size of Array1. Any ideas guys? Please help!
Your loop uses the wrong condition.
for (int i = Array2.size(); i == Array1.size(); i++) {
Array2.add(i, "Test");
}
This would mean the loop runs while i == Array1.size(), which is of course nonsense.
try
for (int i = Array2.size(); i < Array1.size(); i++) {
Array2.add(i, "Test");
}
As per the doc for loop is:
for (initialization; termination; increment) {
statement(s) }
When using this version of the for statement, keep in mind that:
The initialization expression initializes the loop; it's executed once, as the loop begins.
When the termination expression evaluates to false, the loop terminates.
The increment expression is invoked after each iteration through the loop; it is perfectly acceptable for this expression to increment
or decrement a value.
In your case the loop is:
for (int i = Array2.size(); i == Array1.size(); i++) {
Array2.add(i, "Test");
}
It starts from 5 (Arrays2.size()) and checks whether i==10 which is not true (read false) and so it terminates without doing anything. It does not get into the loop at all.
Since i is never equal to Array1.size(), this loop never adds anything
for (int i = Array2.size(); i == Array1.size(); i++) {
Array2.add(i, "Test");
}

Unnecessary label on continue/break

I have confuse of execution the next code :
label:
for (int i = 0; i < 100; i++) {
if (i % 2 == 0) continue;
if (i == 99) {
continue label;
}
System.out.println("i = " + i);
}
I was hope that this cycle is infinite. But no. When value is 99 - programm was exit. I try to play with continue and break operators but still haven't expected result.
I just try understand why this cycle is not infinite and what i gonna do to make it?
Output :
i = 1
i = 3
......
i = 93
i = 95
i = 97
Process finished with exit code 0
continue continues the labelled loop, which does not involve resetting i to its initial value; so nothing you're doing prevents i from increasing, until it reaches 100 and the loop terminates. And yes, you're correct that the label is unnecessary.
To make it infinite, just reset i within the loop, no need for a label or continue:
for (int i = 0; i < 100; i++) {
if (i == 99) {
i = 0;
}
System.out.println("i = " + i);
}
or perhaps this, which outputs 99 then 0 again and keeps going:
for (int i = 0; i < 100; i++) {
System.out.println("i = " + i);
if (i == 99) {
i = -1;
}
}
Or if for some reason you really, really wanted to do this with continue, you'd want a second outer loop: http://ideone.com/ofgpK3
label:
while (true) {
for (int i = 0; i < 100; i++) {
System.out.println("i = " + i);
if (i == 99) {
continue label;
}
}
}
A label is nothing like a goto instruction with what you seem to confuse it with. When you continue a program flow to a labeled loop instruction, you only continue its execution by executing its next loop. When you continue at i = 99, you only execute the for loop with the next iteration value i = 100 what renders the loop's condition i < 100 to be false such that the loop terminates.
What you are trying to achieve would require an outer loop such that:
label: while (true) {
for (int i = 0; ; i++) {
if (i % 2 == 0) continue;
if (i == 99) {
continue label;
}
System.out.println("i = " + i);
}
}
}
Note that I removed the condition within the for loop which is now redundant because the explicit jump back into the outer while loop what implicitly causes the inner loop to terminate. This jump restarts the inner loop and therefore causes the counter to reset to i = 0. In general, such explicit program flow is however difficult to read and easy to confuse such that one should avoid it whenever possible for the same reason as one would want to avoid a goto statement of which labels are very lightweight versions of.
You are continuing with your for loop (And not printing out the number) every time (i % 2 == 0) or if (i == 99) are true. But when i reaches 99, your condition i < 100 is reached and the loop exits.
For an easier infinite loop, use
while(true) {
//Your code
}
or
for(;;) {
//Your code
}
i initialized only once. continue doesn't reset i to 0, so when you reach continue label, the condition in the for loop will be evaluated to false, and you'll skip it.
See the docs:
When using this version of the for statement, keep in mind that:
The initialization expression initializes the loop; it's executed
once, as the loop begins.
When the termination expression evaluates to
false, the loop terminates.
The increment expression is invoked after
each iteration through the loop; it is perfectly acceptable for this
expression to increment or decrement a value.

Translate for loop to a while and do while loop in Java

I created a couple for loops that print lines as such (each new number starts a new line, it doesn't show here):
1
22
333
4444
etc. until it reaches 9 then goes back down to 1.
I am supposed to translate it into both a while and do while loop and have been trying for the past hour and can't seem to do it.
public static void main(String[] args) {
for (int x=1; x <= 9; x++) {
for (int y = 1; y <=x ; y++){
System.out.print( x + "");
}
System.out.println();
}
// TODO code application logic here
for (int x=9; x >=1; x--) {
for (int y = 1; y <=x ; y++){
System.out.print( x + "");
}
System.out.println();
} int y =1;
int x = 1;
while (x <9){
while (y <=x){
y++;
System.out.print(x +"");{
}
System.out.println();
}
x++;
}
A for loop statement has three parts in the for (init; condition; post). These parts are separated by semicolons. The init part specifies an initial statement, the condition is what determines if the loop body is executed or not and the post specifies a post loop statement.
You can do the same thing with a while loop except that instead of a single statement, it is actually several statements. However a while loop is not exactly like a for loop since the continue statement and how it behaves is a concern. More about that later.
A hint is that the various parts of the for statement are separated by semicolons which are also used to separate statements in Java.
Consider the following for loop source example.
int i;
for (i = 0; i < 5; i++) {
// for loop body
}
So you would have an init statement before the loop statement, i = 0 then the loop statement itself containing the condition, i < 5, and as the last line in the loop before the closing curly brace, you would put the post loop condition, i++.
The do while is a bit more complicated because of when the while condition is evaluated. In both the for loop and the while loop, the condition is evaluated and if the expression is not true then the loop body is not executed at all, it is skipped. In the case of the for loop, the init statement is executed and then the condition is evaluated to determine if the for loop body should be executed. Since a while loop does not have an init statement as part of the while statement, the condition is evaluated and if not true, the while loop body is not executed.
A do while loop has a condition that is not evaluated until after the first time through the do while loop body. So the statements within the do while loop are always executed at least once. Then the do while condition is evaluated and if true, execution returns to the top where the do is and the do while loop body is executed again.
Some code of several variations of loops where the init is i = 0 and where the condition is i < 5 and the post is i++. In all cases I have the variable i defined out side of the loop body. In the case of a for loop, defining the variable i within the for statement causes the scope of the variable i, its visibility, to be restricted to the for loop body which would not be the case for the other types of loops.
int i;
for (i = 0; i < 5; i++) {
// for loop body
}
int i = 0;
while (i < 5) {
// while loop body
i++;
}
int i = 0;
do {
// do while loop body
i++;
} while (i < 5);
I mentioned that what happens when the continue statement is executed can make a difference when comparing these forms of loops. The way to think of it is that when a continue statement is executed then there is a jump to the closing brace of the loop statement enclosing the continue statement. So this introduces something to consider.
Look at the above examples but with a continue statement. In all of the examples below there is a continue statement which causes execution to skip to the end of the loop body when the variable i has a value of 3.
With this change the for loop will continue incrementing the variable i because it's post, the third part of the for statement, is executed at the end of the loop. However with the while loop and the do while loop, the incrementing of the variable i is part of the loop body so when the continue is executed skipping to the end of the loop, the increment of the variable i is also skipped.
int i;
// first time init variable i to zero then evaluate condition
for (i = 0; i < 5; i++) { // evaluate condition and execute loop body if true
// for loop body
if (i == 3)
continue; // when i == 3 continue is executed to skip to end of loop
} // at point of braces, post executed, condition evaluated
int i = 0;
while (i < 5) { // evaluate condition and execute loop body if true
// while loop body
if (i == 3)
continue; // when i == 3 continue is executed to skip to end of loop
i++; // variable i only incremented when this statement is executed
} // braces indicate end of loop so jump back to top of loop
int i = 0;
do {
// do while loop body
if (i == 3)
continue; // when i == 3 continue is executed to skip to end of loop
// more statements which may be skipped by the continue
i++; // variable i only incremented when this statement is executed
} while (i < 5); // evaluate condition and jump to top of loop if true
You could make a change to the do while loop while condition to move the incrementing of the variable i into the while condition evaluation by using a pre-increment operator, the ++ operator, on the variable as in the following. We use the pre-increment operator because we want to increment the variable i before we check its value.
int i = -1; // need to start at -1 since the while will increment at beginning of the loop
while (++i < 5) { // increment variable i, evaluate condition and body of loop if true
// while loop body
if (i == 3)
continue; // when i == 3 continue is executed to skip to end of loop
} // braces indicate end of loop so jump back to top of loop
int i = 0;
do {
// do while loop body
if (i == 3)
continue; // when i == 3 continue is executed to skip to end of loop
// more statements which may be skipped by the continue
} while (++i < 5); // increment variable i, evaluate condition and jump to top of loop if true
Try this as your while loop:
int y = 1;
int x = 1;
while (x < 9) {
y = 1;
while (y <= x) {
y++;
System.out.print(x + "");
}
System.out.println();
x++;
}
A for loop is a construct that is extremely similar to a while loop, except that it provides some extra niceties that reduce boilerplate code.
The beginning of a for loop sets your initial variable (in your case, x), your condition clause (x <= 9) and your incrementor (x++). A while loop does not do these things for, it simply runs a block of code while the condition clause in the () is met.
Converting a for loop to a while is simple-
for(int x = 0; x < 10; x++) {
int x = 0;
while(x < 10) {
x++;
}
The while loop has all the same features as the for loop, but without the syntactic sugar. This should help you convert the loops in your question, and in general.

Compiler error: "not a statement"

This is the code snippet:
boolean nodesFiltered = false;
filterSet = newNodeSet;
int filterSize;
int i;
for (; predIter.hasNext(); i < filterSize)
{
eachPred = (Predicate)predIter.next();
filterSize = filterSet.size();
i = 0; continue;
contextNode = filterSet.get(i);
if (contextNode != null)
{
List list = new ArrayList(1);
list.add(contextNode);
predContext.setNodeSet(list);
predContext.setPosition(i + 1);
predContext.setSize(filterSize);
predResult = eachPred.evaluate(predContext);
Where it says i < filterSize) the compiler says I have an error... It says that it isn't a statement...
Indeed, this line is incorrect:
for (; predIter.hasNext(); i < filterSize)
In Java (and all other C-syntax languages) for statement has the following structure:
for(initialization; termination; increment) {
statements...
}
where:
initialization statement is called once, when the loop starts
termination boolean expression is evaluated before each iteration. If it yields false, loop terminates
increment statement is called after every iteration.
Effectively every for loop can be expressed as while loop:
initialization;
while(termination) {
statements;
increment;
}
As you can see in your code snippet increment block is a boolean expression (returns boolean) while it should be a statement (it should "do" something, like incrementing some variable). This is what the compiler is trying to say.
The last part of the for loop should be a statement -- it's what will be executed when control hits the bottom of the loop.
Remember, for a for loop for(int i = 0; i < foo; i++), control goes like this:
int i = 0; (perform initializer statement)
i < foo; (perform conditional check)
if yes, execute the body of the loop.
i++ (perform increment step)
Back to 2.
As you can see, 4. needs something to happen, rather than just getting the value of an expression.
What you did wrong was that in a for loop the code sequence is:
for(i=0; i<10; i++) {
//Code goes here
}
The problem is:
//You did *no* initialization, the order was wrong, and no increment.
for (; predIter.hasNext(); i < filterSize) //wrong
for (i=0; i < filterSize; i++) //Right
Hope this helps!

Does a for loop's while section execute each pass or only once in java?

for example would this be constant or change with each pass?
for(int i = 0; i < InputStream.readInt(); i++)
for(int i = 0; // executed once
i < InputStream.readInt(); // executed before each loop iteration
i++ // executed after each loop iteration
) {
....
}
The first section is executed once before the looping starts. The second section is checked before every loop and if it is true, the loop gets executed, if false the loop breaks. The last part is executed after every iteration.
It executes every time. The for syntax is sugar for
int i = 0
while(true)
{
if(!(i < InputStream.readInt()))
{
break;
}
// for body
i++
}
For times when a control-flow diagram is actually the best graphical representation of a concept.
http://upload.wikimedia.org/wikipedia/commons/0/06/For-loop-diagram.png
I think the main issue is the question: does
i < InputStream.readInt();
get executed each loop iteration? Yes, it does.
In this case it's not changing any sensitive variable, the only variable actually changing in your code is i, but InputStream.readInt() will be run each iteration to make the comparison and will therefore run readInt() again on InputStream.
What about something like:
for (int i=0; i < xObj.addOne().parseInt(); i++)
(given the method addOne returns a string representation of an integer one greater)
Is my "check" incrementing the value that would be incremented if I called xObj.addOne() like normal? Yes. and does it stay incremented to the next loop iteration? Yes.
It's just like doing
int x = 0;
for (int i=0; i < ++x; i++);
This will never terminate, as ++x is always greater than x (which is also i)
What about a nontrivial example?
int x = 6;
for (int i=0; i < x--; i++) {
System.out.print(i+" ");
}
outputs
0 1 2

Categories