Conditional statements

Normal flow of control

The normal flow of control within a function is each statement (roughly speaking, a line) executing in order.

System.out.println("Hello.");
System.out.println("How are you doing?");

When this code runs, the first line runs first, printing ‘Hello.’ and then the second line runs, printing ‘How are you doing?’.

There are three fundamental kinds of control constructs

Calling and returning from a method.

Conditional execution: either run some code or don’t based on some condition.

Looping: run some code repeatedly, while some condition holds.

Todays topic: Conditional execution

if

The main way to conditionally execute some code is with an if statement.

if (x > 10) {
  System.out.println("x is really big!");
}

The code inside the {}s only runs if the expression inside the ()s evaluates to true.

Structure of an if

if (condition) {body}

The condition has to evaluate to a boolean.

The body can consist of any code.

Statements vs expressions

An if statement is not an expression.

It does not produce a value.

Things that occur in a method that aren’t expressions are called statements.

One-way choice.

Using just an if gives us a one-way choice.

if (x > 10) {
  System.out.println("x is really big!");
  System.out.println("Here's another line of code!");
}

We either execute the body or we don’t.

Two-way choice with else

Sometimes we want to choose between two options:

if (x > 10) {
  System.out.println("x is really big!");
} else {
  System.out.println("x is small.");
}

The code in the {}s after the else is called the else clause or else branch and it runs if the condition is false.

Multi-way choices

If we wanted to make a three-way choice, we could write this:

if (x > 10) {
  System.out.println("x is really big!");
} else {
  // In here we know x is <= 10
  if (x > 5) {
    System.out.println("x is kinda medium");
  } else {
    System.out.println("x is small.");
  }
}

The outer if has two branches: one where x is greater than 10 and one for when it’s not, i.e. when it’s less than or equal to 10.

The second if, inside the else branch of the first if, branches into an x > 5 path and an everything else path.

So there are actually three possible branches

Normally we’d write that like this

if (x > 10) {
  System.out.println("x is really big!");
} else if (x > 5) {
  System.out.println("x is kinda medium");
} else {
  System.out.println("x is small.");
}

Same logic, just formatted slightly differently.

What does this print?

Assume x is 20.

if (x > 10) {
  System.out.println("x is really big!");
}
if (x > 5) {
  System.out.println("x is kinda medium");
} else {
  System.out.println("x is small.");
}

The else if in the previous version was important.

Also don’t do this

if (x > 10) {
  System.out.println("x is really big!");
} else if (x <= 10) {
  System.out.println("x is small.");
}

This is really a two-way choice since either x > 10 or x <= 10.

I.e. the two conditions are mutually exclusive.

So make it obvious by just using an if/else.

A note on the body of an if statement

Java actually allows either a single statement or a block contained in {}s after the condition of an if or after an else in an if/else.

So this is legal:

if (x > 10)
  System.out.println("x is really big!");

and is equivalent to this version with curly braces:

if (x > 10) {
  System.out.println("x is really big!");
}

However …

We should always use braces.

Here’s why.

Suppose we have this:

if (x > 10)
  x = 10;

Perfectly legal. Clamps x to be no greater than 10.

Then suppose we want to add some output, so we add a line like this:

if (x > 10)
  System.out.println("Clamping x to 10");
  x = 10;

Do you see the problem?

Despite the indentation, that code is equivalent to this:

if (x > 10) {
  System.out.println("Clamping x to 10");
}
x = 10;

I.e. Now x always gets set to 10 because the assignment isn’t in the body of the if any more.

If we had written it like this from the beginning

if (x > 10) {
  x = 10;
}

Then when we added the line it would turn into this:

if (x > 10) {
  System.out.println("Clamping x to 10");
  x = 10;
}

And would work the way we intended.

Programming is hard enough

Don’t make it harder.

But!

If you were really, really paying attention you might notice that there is a place where I advised leaving out the braces.

if (x > 10) {
  System.out.println("x is really big!");
} else if (x > 5) {
  System.out.println("x is kinda medium");
} else {
  System.out.println("x is small.");
}

That could also be formatted like this

if (x > 10) {
  System.out.println("x is really big!");
} else
  if (x > 5) {
    System.out.println("x is kinda medium");
  } else {
    System.out.println("x is small.");
  }

The second if/else counts as a single statement and thus the whole body of the first else branch.

A few other style points

Never compare to boolean literals

Suppose hungry is a boolean.

Don’t write: hungry == true

hungry is already either true or false

Otherwise, why not write:

hungry == true == true

🤔

What you should write

Instead of Write
hungry == true hungry
hungry != true !hungry
hungry == false !hungry

You don’t need an if to return a boolean value

Remember that booleans are perfectly cromulent values.

And statements are about control flow, not values.

I.e. don’t do this

if (condition) {
  return true;
} else {
  return false;
}

Just write:

return condition;

It’s already a boolean!

Or if it’s reversed

if (condition) {
  return false;
} else {
  return true;
}

Write:

return !condition;