We have seen that you can structure code through classes, linking them by object instantiation.
However, the code still reads like a shopping list of commands to do one after another.
This is inflexible, and also results in very long code.
We need some way of:
Repeating useful code without copying it out again.
Branching our code based on processing and user decisions.
Separating off useful code into the classes that contain the data the code acts on.
Responding to user interactions.
Flow control
Here we'll look at the first of these, repeating useful code, especially with slight variations.
Future parts will look at:
Branching
Separating code into procedures
And then, a bit later in the course:
Responding to user events.
Loops
Let's imagine we wanted to run a piece of code until some condition was true. To do this, we can use the while construction. For example,
int i = 0;
while (i < 3) {
i++;
}
Remember 'i++' increments i by one, and is the same as i = i + 1.
How does i change as this code runs?
Loops
Let's throw in some printlns to see how i changes (always useful):
int i = 0;
while (i < 3) {
System.out.println(i);
i++;
}
System.out.println("Finished");
The code in the block is repeated all the time a is less than 3, so prints "0", "1", "2".
The code then continues with the next line and prints "finished".
Note that at this point, i is 3.
Conditions
The '(i < 3)' bit is known as the condition.
The loop runs all the time it is true.
Along with the mathematical operators, there are also comparison operators:
> : greater than >= : greater than or equal to < : less than <= : less than or equal to == : equal to (used because "=" is for assigning variables) != : not equal to
String comparisons
Because Strings are objects, you can't do this:
String a = "hi";
String b = "hi";
while (a == b) {
Because the answer is, no, they're not the same object.
There's a special way of comparing Strings, which is:
while (a.equals(b)) {
while (a.equals("hi")) {
this compares the value of the text in the String.
Boolean operators
There are also Boolean operators, used for putting several conditions together:
& : Boolean AND && : Shortcut Boolean AND | : Boolean OR || : Shortcut Boolean OR ! : Not
Note that if you are going to use multiple conditions, each condition, and the overall condition need to be in parentheses:
while ( (a != b) & (b > 10) ) {
Some examples:
while ((a != b) & (b > 10)) {
Means do this while it is true that a is not equal to b, AND b is greater than 10.
while ((a != b) | (b > 10)) {
Means do this while it is true that a is not equal to b, OR b is greater than 10.
while (booleanVariable == true){
while (booleanVariable){
Means do it while a boolean variable is true.
while (booleanVariable == false) {
while (!booleanVariable)
Means do it while it is true that a boolean variable is false.
Shortcuts
The checking of conditions is quite complicated, and takes the computer a relatively long time, so we want to minimise checking. The shortcut operators don't bother to assess the second condition, if the first is unfavourable, for example, in:
while ((a != b) && (b > 10)){
the '(b > 10)' isn't assessed if '(a != b)' is untrue, because there isn't any point - the overall condition is false.
Equally, in:
while ((a != b) || (b > 10)){
the '(b > 10)' isn't assessed if '(a != b)' is true, because there isn't any point - the overall condition is true.
While-loops continued
With:
while (i < 3) {
i++;
}
the 'i++' only happens if the condition is true.
If you want the while loop to run once whether it is true or not, use:
do {
i++;
} while (i < 3) ;
Counting loops
This code is works ok:
int i = 0;
while (i < 3) {
i++;
}
but as a coder it is a bit issue-prone. The variable declaration for 'i', the condition, and the incrementing of 'i' are all in different places.
There are various problems with this, not least that the scope of 'i' is larger than it needs to be, and that, with cutting and pasting, all kinds of problems could creep in.
While-loops are good for some things (like looping until you find a file) but bad for counting.
For loops
There is a special construction for counting, which is much cleaner:
for (int i = 0; i < 3; i++) {
System.out.println(i);
}
System.out.println("Finished");
Here we see all the familiar parts: the variable declaration, the condition, and the increment, but all are in the same place, and the scope of i is just the loop block.
Again, this prints '0', '1', '2', but at the end, i is destroyed, rather than hanging around causing potential problems.
Variations
There is nothing to stop you dropping, one, two, or all of the parts of the for loop, as long as you have the semi-colons; so this loops forever:
for ( ; ; ) {
System.out.println
("All work and no play makes Jack a dull boy.");
}
Hint: to get out of infinitely looping or unresponsive ('hung') programs at the command prompt, push the CTRL and C keys together.
Variations
Note also, that the increment can be replaced with expanded maths, so:
for (int i = 0; i < 3; i = i + 1) {
Or any other kind of maths to do each loop.
The increment doesn't have to be plus one:
for (int i = 0; i < 3; i = i + 2) {
for (int i = 3; i > 0; i--) {
What do you think 'i--' does?
For-each
Introduced in Java 1.5
Allows iteration through variable collections:
int [] arr = {10,50,30};
for (int a: arr) {
System.out.println(a);
}
will print "10", "50", "30".
Reference vs. Value
Remember, however, that primitives are copied, while objects are linked to, so:
int [] arr = {10,50,30};
for (int a: arr) {
a = 2;
}
won't change the data in the array.
Whereas:
Point [] arr =
{new Point(),new Point(),new Point()};
for (Point a: arr) {
a.x = 2;
}
will change the Points, as 'a' is a link to them.
More about loops
With all loops, if there is just one statement to do, you can forget the brackets, e.g.
for (int i = 0; i < intArray.length; i++)
System.out.println(i);
do System.out.println(i++); while (i < 10);
won't change the data in the array.
Don't. Always put in brackets. That way, if you decide to put more in the loops, the brackets are there already.
Infact, generally, with all blocks, put in both the brackets before you write any code in them.
Evil control statements
goto : Darkness encoded, goto is Satan's only friend in this realm of joy and light.
break (end loop) and continue (go to beginning line): Used to end blocks and temporarily skip loops respectively. Not as bad as goto was, but still to be used very sparingly.
When to break/continue
Use only when you need to escape a loop in the middle of something that would be very complex to write avoiding it.
while (file == wrongFile) {
// code to get a file;
// if we find the right file,
continue;
// code to destroy file for space
}
Review
for (int i = 0; i < 3; i++) {
System.out.println(i);
}