University College of Applied SciencesProgramming 1
العربية
Lecture 7 · 100 min

Conditions: Programs That Choose

How does a program decide what to do based on the values it holds?

By the end of this lecture you will be able to

  1. Write conditions with relational operators and tell = from ==
  2. Use if and if-else to run one part of a program and not another
  3. Explain what braces { } do and spot the semicolon trap after a condition
  4. Combine conditions with &&, || and !, and make use of short-circuiting
  5. Check a range of values the right way and compare strings with equals
In this lecture
  1. Programs choose, just as you do every day
  2. A condition is a question answered true or false
  3. if runs a block only when the condition is true
  4. = stores a value, == asks a question
  5. if-else always runs one of two branches, never both
  6. Braces decide what belongs to the condition, not indentation
  7. A semicolon after the condition makes the block always run
  8. &&, || and ! build one condition out of several
  9. ! comes first, then &&, then ||, and parentheses change that order
  10. Java stops as soon as it knows the answer, which guards us from dividing by zero
  11. Checking a range takes two comparisons joined by &&
  12. Compare strings with equals, not with ==
  13. Largest of two: store an answer in a variable, then correct it if needed
  14. Final exercise: a program that brings it all together
  15. Review questions
Part one: conditions and if

Programs choose, just as you do every day

Until now our programs ran every line from top to bottom, whatever the values were. Real programs look at the values first, then decide.

SituationThe questionIf the answer is yesIf the answer is no
Cash machineIs the balance enough?Hands you the moneyShows a refusal message
Unlocking a phoneIs the code correct?Opens the screenAsks for the code again
Exam resultIs the mark 60 or more?PassFail

A condition is a question answered true or false

Relational operators produce a boolean, a type with only two values: true and false. You can print that value or store it in a variable like any other value.

OperatorMeaningExampleResult
==Equal to5 == 5true
!=Not equal to5 != 5false
>Greater than7 > 3true
<Less than7 < 3false
>=Greater than or equal to3 >= 3true
<=Less than or equal to4 <= 3false

Ask Java six questions

Predict each line before running. Then change age to 18 and predict again.

public class Comparisons {
    public static void main(String[] args) {
        int age = 19;
        System.out.println(age > 18);
        System.out.println(age < 18);
        System.out.println(age >= 19);
        System.out.println(age <= 18);
        System.out.println(age == 19);
        System.out.println(age != 19);

        boolean adult = age >= 18;
        System.out.println(adult);
    }
}
Output
true
false
true
false
true
false
true

Arithmetic comes before comparison. What does this print?

public class MathFirst {
    public static void main(String[] args) {
        int a = 7;
        int b = 10;
        System.out.println(a + 3 == b);
        System.out.println(a % 2 == 0);
        System.out.println(a * 2 > b);
    }
}
Show the output
Output
true
false
true

Why? Java works out both sides of the comparison first: 10 equals 10, the remainder 1 is not 0, and 14 is greater than 10.

How do you write "x is not equal to zero" in Java?

if runs a block only when the condition is true

if (condition) {
    // runs only when the condition is true
}
// the program always continues here
The condition always goes in parentheses, and the lines that belong to it go inside { }.

Watch the program skip a line

Press "Debug line by line" and watch which lines the program stops on. Then change temperature to 36 and step again: which line dropped out of the journey?

public class Temperature {
    public static void main(String[] args) {
        int temperature = 38;
        if (temperature > 37) {
            System.out.println("Fever: see a doctor");
        }
        System.out.println("Check finished");
    }
}
Output
Fever: see a doctor
Check finished

The balance is 40 and the price is 50. What does the program print?

public class Shop {
    public static void main(String[] args) {
        int balance = 40;
        int price = 50;
        if (balance >= price) {
            System.out.println("Bought");
            balance -= price;
        }
        System.out.println("Balance: " + balance);
    }
}
Show the output
Output
Balance: 40

Why? The condition is false, so the program skips the whole block: neither the print nor the subtraction happens. The last line is outside the block, so it always runs.

= stores a value, == asks a question

Assignment

Puts the value 5 in the box x.

x = 5;
Comparison

Asks: is the value of x equal to 5? The answer is true or false.

x == 5

One sign short

Fix the condition so the program prints x is five.

public class CheckFive {
    public static void main(String[] args) {
        int x = 5;
        if (x = 5) {
            System.out.println("x is five");
        }
    }
}
Compiler messageincompatible types: int cannot be converted to boolean
Show the fix
public class CheckFive {
    public static void main(String[] args) {
        int x = 5;
        if (x == 5) {
            System.out.println("x is five");
        }
    }
}
Output
x is five

Why? The result of x = 5 is the value 5, an int, but if needs a boolean. The message talks about types and never mentions the missing sign, so remember this pattern when you see it inside a condition.

Here the compiler stays silent. What does the program print?

public class Finished {
    public static void main(String[] args) {
        boolean finished = false;
        if (finished = true) {
            System.out.println("Done");
        }
        System.out.println(finished);
    }
}
Show the output
Output
Done
true

Why? The condition is an assignment: it puts true in finished, and its result is the boolean true, so the compiler accepts it. That is why you write just if (finished) with boolean variables: then this slip cannot happen.

if-else always runs one of two branches, never both

Pass or fail?

Run it three times, entering 59, then 60, then 61: values at the boundary are the ones that reveal bugs. Then press "Debug line by line" to see which branch runs. Notice that we used a constant for the pass mark.

import java.util.Scanner;

public class PassFail {
    public static void main(String[] args) {
        final int PASS_MARK = 60;
        Scanner input = new Scanner(System.in);
        System.out.print("Mark: ");
        int mark = input.nextInt();

        if (mark >= PASS_MARK) {
            System.out.println("Pass");
        } else {
            System.out.println("Fail");
        }
        System.out.println("Done");
    }
}

The first branch changes x. Does the program go back and check the condition?

public class OneBranch {
    public static void main(String[] args) {
        int x = 10;
        if (x > 5) {
            x = x - 8;
        } else {
            x = x + 8;
        }
        System.out.println(x);
    }
}
Show the output
Output
2

Why? The condition is checked once only, before entering a branch. Yes, x is now 2, but the program does not return to the condition, and it skips the whole else.

Even or odd?

Read one whole number, then print Even if it is even and Odd if it is odd. Do not print a prompt.

import java.util.Scanner;

public class EvenOdd {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        // Read the number, then decide

    }
}
stdin
4
Expected output
Even
Hint 1

An even number leaves no remainder when divided by 2: n % 2 == 0.

Hint 2

Do not write n % 2 == 1: in Java -3 % 2 is -1, so that condition goes wrong for negative numbers.

Solution
import java.util.Scanner;

public class EvenOdd {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        int n = input.nextInt();
        if (n % 2 == 0) {
            System.out.println("Even");
        } else {
            System.out.println("Odd");
        }
    }
}

Braces decide what belongs to the condition, not indentation

Both lines look as if they belong to the condition. Do they?

public class NoBraces {
    public static void main(String[] args) {
        int mark = 40;
        if (mark >= 60)
            System.out.println("Passed");
            System.out.println("Well done");
        System.out.println("End");
    }
}
Show the output
Output
Well done
End

Why? Without braces, only the one statement right after the condition belongs to it. The compiler ignores indentation completely: it is for human readers only. So Well done prints even for a failing mark.

Where did the if go?

The program wants to print two lines on a pass. Add what is missing.

public class TwoLines {
    public static void main(String[] args) {
        int mark = 75;
        if (mark >= 60)
            System.out.println("Passed");
            System.out.println("Well done");
        else
            System.out.println("Failed");
    }
}
Compiler message'else' without 'if'
Show the fix
public class TwoLines {
    public static void main(String[] args) {
        int mark = 75;
        if (mark >= 60) {
            System.out.println("Passed");
            System.out.println("Well done");
        } else {
            System.out.println("Failed");
        }
    }
}
Output
Passed
Well done

Why? The if ended after the first line, so the second line became an ordinary statement and else found no if to follow. The message points at else, although the cause is the missing braces before it.

A variable that vanishes when the block ends

Declare result somewhere it stays known down to the print line.

public class BlockScope {
    public static void main(String[] args) {
        int mark = 75;
        if (mark >= 60) {
            String result = "Pass";
        } else {
            String result = "Fail";
        }
        System.out.println(result);
    }
}
Compiler messagecannot find symbol
Show the fix
public class BlockScope {
    public static void main(String[] args) {
        int mark = 75;
        String result;
        if (mark >= 60) {
            result = "Pass";
        } else {
            result = "Fail";
        }
        System.out.println(result);
    }
}
Output
Pass

Why? A variable declared inside { } lives only inside them. Declare it before the block if you need it afterwards.

A semicolon after the condition makes the block always run

x is 3, so what is the output? Look closely at the end of the if line.

public class Semicolon {
    public static void main(String[] args) {
        int x = 3;
        if (x > 5);
        {
            System.out.println("x is big");
        }
        System.out.println("End");
    }
}
Show the output
Output
x is big
End

Why? A lone semicolon is an empty statement that does nothing, and that empty statement is what the condition controls. The block after it stands on its own and always runs. The compiler does not object, because all of this is valid syntax.

See the trap with your own eyes

Press "Debug line by line": the condition is false, yet the program enters the block anyway. Then delete the semicolon after the condition and step through again.

public class VotingAge {
    public static void main(String[] args) {
        int age = 15;
        if (age >= 18); {
            System.out.println("You may vote");
        }
    }
}
Output
You may vote

The same slip, but now the compiler sees it

Having an else exposes the trap. Fix the line so the program prints Small.

public class BigSmall {
    public static void main(String[] args) {
        int x = 3;
        if (x > 5); {
            System.out.println("Big");
        } else {
            System.out.println("Small");
        }
    }
}
Compiler message'else' without 'if'
Show the fix
public class BigSmall {
    public static void main(String[] args) {
        int x = 3;
        if (x > 5) {
            System.out.println("Big");
        } else {
            System.out.println("Small");
        }
    }
}
Output
Small

Why? The if ended at the semicolon, then a separate block followed, so else found no if to attach to. When you see this message, check the end of the if line first.

Part two: combining conditions

&&, || and ! build one condition out of several

&& (and)

True only when both sides are true.

hasId && paidFees
|| (or)

True when at least one side is true.

isHoliday || isWeekend
! (not)

Flips the value: true becomes false, and the reverse.

!paidFees
aba && ba || b!a
truetruetruetruefalse
truefalsefalsetruefalse
falsetruefalsetruetrue
falsefalsefalsefalsetrue

The truth table in your own hands

Change hasId and paidFees through all four cases, predict the three results before each run, then compare with the table.

public class LogicTable {
    public static void main(String[] args) {
        boolean hasId = true;
        boolean paidFees = false;
        System.out.println(hasId && paidFees);
        System.out.println(hasId || paidFees);
        System.out.println(!paidFees);
    }
}
Output
false
true
true

Two conditions in one if

A student enters the library if they have a card and have no late books. Change lateBooks to 2 and predict the output. Then use "Debug line by line" to see which branch runs.

public class Library {
    public static void main(String[] args) {
        boolean hasCard = true;
        int lateBooks = 0;
        if (hasCard && lateBooks == 0) {
            System.out.println("Welcome");
        } else {
            System.out.println("Please see the librarian");
        }
    }
}
Output
Welcome

! comes first, then &&, then ||, and parentheses change that order

The first two lines differ only in their parentheses. What does the program print?

public class LogicOrder {
    public static void main(String[] args) {
        boolean a = true;
        boolean b = false;
        boolean c = false;
        System.out.println(a || b && c);
        System.out.println((a || b) && c);
        System.out.println(!a || b);
    }
}
Show the output
Output
true
false
false

Why? In the first, && goes before ||, so b && c gives false, then true || false gives true. The parentheses in the second force || first, giving true && false. In the third, a is flipped first: false || false.

"Equals 6 or 7", the way we say it

We say it this way out loud, but Java wants a complete condition on each side of ||.

public class Weekend {
    public static void main(String[] args) {
        int day = 7;
        if (day == 6 || 7) {
            System.out.println("Weekend");
        }
    }
}
Compiler messagebad operand types for binary operator '||'
Show the fix
public class Weekend {
    public static void main(String[] args) {
        int day = 7;
        if (day == 6 || day == 7) {
            System.out.println("Weekend");
        }
    }
}
Output
Weekend

Why? The right side here is the number 7 alone, which is not a boolean, and || accepts only logical values. That is why the message mentions the types of the two sides.

Which condition means the same as !(x > 5)?

Java stops as soon as it knows the answer, which guards us from dividing by zero

ExpressionLeft sideIs the right side evaluated?Why
a && bfalseNoThe result is false whatever the right side is
a && btrueYesThe result depends on it
a || btrueNoThe result is true whatever the right side is
a || bfalseYesThe result depends on it

The guard before the division

Run the program and see it work safely. Then swap the two sides of && so the condition reads total / students > 10 && students != 0 and run again: the program crashes with ArithmeticException: / by zero, because the division happened before the check.

public class GuardDivision {
    public static void main(String[] args) {
        int total = 90;
        int students = 0;
        if (students != 0 && total / students > 10) {
            System.out.println("High average");
        } else {
            System.out.println("No high average");
        }
    }
}
Output
No high average

count is zero and the condition divides by it. What happens?

public class OrGuard {
    public static void main(String[] args) {
        int count = 0;
        if (count == 0 || 10 / count > 1) {
            System.out.println("Safe");
        }
        System.out.println("End");
    }
}
Show the output
Output
Safe
End

Why? The left side is true, which is enough to make || give true, so the division is never evaluated.

Which condition is safe when n is zero?

Checking a range takes two comparisons joined by &&

Mathematics is not Java

In mathematics we write 60 ≤ x ≤ 100. Fix the condition the Java way.

public class RangeCheck {
    public static void main(String[] args) {
        int mark = 75;
        if (60 <= mark <= 100) {
            System.out.println("Passing mark");
        }
    }
}
Compiler messagebad operand types for binary operator '<='
Show the fix
public class RangeCheck {
    public static void main(String[] args) {
        int mark = 75;
        if (mark >= 60 && mark <= 100) {
            System.out.println("Passing mark");
        }
    }
}
Output
Passing mark

Why? Java works from the left: 60 <= mark gives true, then it tries true <= 100, and comparing a boolean with a number means nothing. That is why the message names the types boolean and int.

The mark is 150, and the programmer used || instead of &&. What does it print?

public class WrongRange {
    public static void main(String[] args) {
        int mark = 150;
        if (mark >= 0 || mark <= 100) {
            System.out.println("Valid");
        } else {
            System.out.println("Invalid");
        }
    }
}
Show the output
Output
Valid

Why? Every number is either at least 0 or at most 100, so this condition is always true. Try values on and beyond the limits whenever you write a range condition.

A valid age

Read a whole-number age. Print Valid age if it is from 0 to 120, both included, otherwise print Invalid age. Do not print a prompt.

import java.util.Scanner;

public class ValidAge {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        // Read the age, then check the range

    }
}
stdin
19
Expected output
Valid age
Hint 1

"Both included" means >= and <=, not > and <.

Hint 2

Use &&: both limits must hold together.

Solution
import java.util.Scanner;

public class ValidAge {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        int age = input.nextInt();
        if (age >= 0 && age <= 120) {
            System.out.println("Valid age");
        } else {
            System.out.println("Invalid age");
        }
    }
}
Part three: strings and complete programs

Compare strings with equals, not with ==

== with strings

Asks: do these two variables refer to the very same object in memory?

answer == "yes"
equals

Asks: are the characters in the two strings the same? That is almost always what you want.

answer.equals("yes")

A string from the keyboard

We gave the program the word yes as input. == prints false even though the characters match, because Scanner made a new string in another place in memory.

import java.util.Scanner;

public class CompareInput {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        String answer = input.next();
        System.out.println(answer == "yes");
        System.out.println(answer.equals("yes"));
    }
}
Output
false
true

Three comparisons of strings with the same characters. What does the program print?

public class StringCompare {
    public static void main(String[] args) {
        String a = "java";
        String b = "java";
        String c = new String("java");
        System.out.println(a == b);
        System.out.println(a == c);
        System.out.println(a.equals(c));
    }
}
Show the output
Output
true
false
true

Why? Java makes identical string literals one shared object, so a == b gives true, while new makes a new object. That is why == seems right in small tests, then fails when the text comes from the user. So always use equals.

Letter case matters

The user typed YES. Notice the difference between equals and equalsIgnoreCase, then use ! to print Not yes when the strings do not match.

import java.util.Scanner;

public class IgnoreCase {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        String answer = input.next();
        System.out.println(answer.equals("yes"));
        System.out.println(answer.equalsIgnoreCase("yes"));
    }
}
Output
false
true

The password

Read one word using next. Print Welcome if it is exactly java123, otherwise print Wrong password. Do not print a prompt.

import java.util.Scanner;

public class SecretWord {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        // Read the word, then compare it

    }
}
stdin
java123
Expected output
Welcome
Hint 1

If only the first test fails, you are probably using ==.

Hint 2

password.equals("java123") gives a boolean you can put directly inside if.

Solution
import java.util.Scanner;

public class SecretWord {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        String password = input.next();
        if (password.equals("java123")) {
            System.out.println("Welcome");
        } else {
            System.out.println("Wrong password");
        }
    }
}

Largest of two: store an answer in a variable, then correct it if needed

Trace the variable max

Press "Debug line by line" and watch the box max. Then swap the values of a and b: is the result still right? Does the branch run this time?

public class Largest {
    public static void main(String[] args) {
        int a = 12;
        int b = 30;
        int max = a;
        if (b > max) {
            max = b;
        }
        System.out.println("Largest: " + max);
    }
}
Output
Largest: 30

Largest of two

Read two whole numbers, then print only the larger one. If they are equal, print either. Do not print a prompt.

import java.util.Scanner;

public class LargestOfTwo {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        // Read two numbers and print the larger

    }
}
stdin
3
8
Expected output
8
Hint 1

Do not start with max = 0, or your program fails with negative numbers.

Hint 2

Start with int max = a;, then use one if.

Solution
import java.util.Scanner;

public class LargestOfTwo {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        int a = input.nextInt();
        int b = input.nextInt();
        int max = a;
        if (b > max) {
            max = b;
        }
        System.out.println(max);
    }
}

Final exercise: a program that brings it all together

May the student sit the exam?

Read the attendance percentage as a whole number, then the word yes or no saying whether the student paid the fees. Print Allowed if attendance is 75 or more and the word is yes, otherwise print Not allowed. Do not print a prompt.

import java.util.Scanner;

public class ExamEntry {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        // Read the attendance with nextInt and the word with next

    }
}
stdin
90
yes
Expected output
Allowed
Hint 1

You need && joining a number comparison and equals.

Hint 2

The full condition: attendance >= 75 && paid.equals("yes").

Solution
import java.util.Scanner;

public class ExamEntry {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        int attendance = input.nextInt();
        String paid = input.next();
        if (attendance >= 75 && paid.equals("yes")) {
            System.out.println("Allowed");
        } else {
            System.out.println("Not allowed");
        }
    }
}

Review questions

What is the difference between x = 5 and x == 5?

How do you check that x is between 1 and 10, both included?

Which condition checks that the string name is not Ali?

Trace the conditions carefully: what does the program print?

public class ReviewCombo {
    public static void main(String[] args) {
        int x = 8;
        if (x > 5 && x % 2 == 1) {
            System.out.println("A");
        } else {
            System.out.println("B");
        }
        if (x > 10 || !(x == 3)) {
            System.out.println("C");
        }
        System.out.println("D");
    }
}
Show the output
Output
B
C
D

Why? 8 is even, so the first condition is false and B prints. In the second, x > 10 is false, but x is not 3, which is enough for ||, so C prints. D is outside every block.