Short-Circuiting

Java has short circuiting for the && and || operators.

Keep this in mind in exercises that have a runtime error on the right side of this operator.

This means that p || q and p && q is not commutative. This also means that side-effects of the symbols might not get executed if evaluation is short-circuited:

a != 0 && b / a does not error out since the check for zero makes the expression short-circuit.

Prefix and Postfix increment and decrement

The result of

int a = 1;
int b = ++a; (b = 2, a = 2)

is different from the result of

int a = 1;
int b = a++; (b = 1, a = 2)

Because the ++ and -- operators either run before the assignment or after depending on position.

Extra mean example:

int x = 2;
++x + x++; // = 6

First x is set to three by the pre-increment, then added to the x = 3 and then x is post-incremented.

For-Loop

For things where the for-condition is not simply i < x.size() or something similar, keep in mind that the for-condition is evaluated at every loop, just like in the while loop.

If we shrink x in the body for example, then the new size will be considered for x.size().

Note that we can omit everything except the semicolons in a for-loop:

// Omit initialization (variable declared elsewhere)
int i = 0;
for (; i < 10; i++) { }
 
// Omit increment (done inside the loop)
for (int i = 0; i < 10;) {
    i++;
}
 
// Omit condition (creates an infinite loop, like while(true))
for (int i = 0; ; i++) {
    if (i >= 10) break;
}
 
// Omit everything (infinite loop)
for (;;) {
    // equivalent to while(true)
}
int i = 0;
for (; i < 10; i++) { }
 
for (int i = 0; i < 10;) {
    i++;
}
 
for (int i = 0; ; i++) {
    if (i >= 10) break;
}
 
for (;;) {
}

Do-While Loops

do {
	// body
} while (test);
 
statement;

First the body is executed a single time at least!, then the test is performed. If the test fails, we continue at statement, otherwise we loop the body once more.

Methods

Method Overloading

Defining multiple methods with the same signature is not allowed:

  • same types just different names
  • different return types (this doesn’t allow for choosing the correct one)

If you do overload a function name, the one with the most-matching signature will be called.

Pass by Reference

All variables are passed as copies. This means that for primitive types, we get an actual copy of the value, which can then not change the caller’s copy.

For Objects, we receive a copy of the reference. This means that we:

  • cannot override the caller’s reference (by setting x = null for example)
  • we can change the object itself (x[0] = 5 will also mutate the caller’s object)