Welcome to Lesson 11!

Learning Objectives
By the end of today's class, you should know...
  • How do you test multiple conditions using logical operators?
  • How do && and || operate when:
    • both test conditions evaluate to true?
    • both test conditions evaluate to false?
    • one test condition evaluates to true and one to false?
  • What are some pitfalls you might encounter when using logical operators and how can you avoid them?
  • What is a switch statement?
  • How does a switch statement compare to an if statement?
  • What is the syntax of a switch statement?
  • What is "fall through"?

Announcements

  • Return Midterms in last 5 minutes of class - excellent results!
  • As: 28 (4 100% scores!)
  • Bs: 6
  • Cs: 3
  • Ds: 2
  • Fs: 4
  • Next quiz on Thursday
    • numbers, operators and precision
    • else if
    • switch statements (today's class)
    • logical operators (today's class)
  • Lab 6 due Friday
  • Come to De Anza Women in CS Club meeting tomorrow at 12:30 in the ATC 202 computer lab!

Wrapping Up Conditionals: Switch Statements

  • The switch statement gives us an alternative to an if-else-if chain
  • Executes a section of code depending on value of a variable
  • The general syntax is:
    switch (expression) {
       case label1:
          statements
          break;
       case label2:
          statements
          break;
       ...
       case labeln:
          statements
          break;
       default:
          statements
    }
    
  • Where:
    • expression: a value you want to match
    • labelx: a numeric constant
    • statements: the statements to execute when the condition is met
  • Any number of case labels can be placed in any order
  • Any value that does not match starts executing with the statement after default
  • Execution continues until the end of the switch statement or a break statement
  • The break statement causes an immediate exit from the switch statement
  • Just as case identifies possible starting points, break determines end points

Example of a switch Statement:

public static void main(String[] args) {
	     Scanner input = new Scanner(System.in);
String typeOfDay="";

System.out.print("Enter a day of the week: ");
String dayOfWeek = input.next();

switch (dayOfWeek) {
case "Monday":
typeOfDay = "Weekday";
break;
case "Tuesday":
typeOfDay = "Weekday";
break;
case "Wednesday":
typeOfDay = "Weekday";
break;
case "Thursday":
typeOfDay = "Weekday";
break;
case "Friday":
typeOfDay = "Hurray! End of work week!";
break;
case "Saturday":
typeOfDay = "Weekend";
break;
case "Sunday":
typeOfDay = "Weekend";
break;
default:
System.out.println("Error: Invalid day of the week");

}
System.out.println(typeOfDay);
input.close();
}
  • Notice that each case other than the last contains a break statement
  • Ensures that the switch statement is exited after a matching case is found

When to Use switch Statements

  • Switch statements work for exact matches ONLY
  • They can be used with any type in Java, including ints, doubles, chars, and Strings.
  • The below example highlights the problem of only being able to look for an exact match
    • For example, we are unable to test for scores using >=
    • Thus, we have to use a clever trick - dividing the score by 10 to retrieve the first digit(s) (1-10)


Another example of switch statements involving ints


public static void main(String[] args) {
        Scanner input  = new Scanner(System.in);

        System.out.print("I show a grade based on a"
            + " score.\nEnter your score: ");
        int score = input.nextInt();

        switch (score / 10) { //integer division to convert score to an int from 1 to 10
            case 10:
            case 9:
                System.out.println("You got an A");
                break;
            case 8:
                System.out.println("You got a B");
                break;
            case 7:
                System.out.println("You got a C");
                break;
            case 6:
                System.out.println("You got a D");
                break;
            default:
                System.out.println("Sorry, an F");
        }
    }



The Case Against Switch Statements
  • Because they can only be used for exact matches (== or .equals()), switch statements are inherently less useful than if-else statements (which can involve test conditions using all 6 comparison operators, including < and >)
  • Also, the syntax is no clearer than if-else statements
  • Note that there is a reason for the limitations of the switch statement
  • Many years ago a compiler could generate more efficient code (using jump tables or binary searches) only within the limitations of the switch statement
  • However, modern compilers are quite capable of optimizing if-else statements to the same degree
  • Thus, we have no reason to ever use a switch statement (depending on your compiler)
  • On the other hand, there are reasons to avoid using a switch statement
  • Every branch of the switch statement must be terminated by a break statement
  • If the break statement is missing, the program falls through and executes the next case without testing
  • There are rare uses for this fall through behavior, such as printing the words for the song, The Twelve Days of Christmas
  • However, according to a study by Peter van der Linden, reported in his book, Expert C Programming, p. 38, the falling through behavior is needed less than 3% of the time
  • Forgetting to type the break statement is a very common error and the source of many bugs
  • Therefore, switch statements are less useful than if statements and potentially more likely to cause bugs in your code.


Example of Fall Through:

    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        String typeOfDay="";
        System.out.print("Enter a day of the week: ");
        String dayOfWeek = input.next();
        switch (dayOfWeek) {
             case "Monday":
                
             case "Tuesday":
                 
             case "Wednesday":
                 
             case "Thursday":
                 typeOfDay = "Weekday";
                 break;
             case "Friday":
                 typeOfDay = "Hurray! End of work week!";
                 break;
             case "Saturday":

             case "Sunday":
                 typeOfDay = "Weekend";
                 break;
             default:
                 System.out.println("Error: Invalid day of the week");
                
         }
         System.out.println(typeOfDay);
         input.close();
    }



Activity 11.1: Letter Grades Again (10 pts)
  • Find a partner for pair programming
  • Open up one partner's Assignment 9.2: Letter Grades from Canvas
  • Revise this program to use switch statements, rather than if statements.
  • Note that you only need to handle the cases of A, B, C, D, and F for this activity (no + or - signs)
  • For example, you will need cases that look like this:

switch(grade) {

    case "A":

        System.out.println("Numeric value: 4.0");

        break;

    //add more cases here

}


When you are finished revising your program, both partners should submit it to Canvas.


Logical Operators

  • In certain situations, we may wish to use more than one test condition inside of an if statement.
  • To do so, we will need to chain the test conditions together using logical operators (either && or ||)
  • For example, recall our guessing game program:
        System.out.println("I'm thinking of a number between 1 and 10.");
    System.out.println("Can you guess it?\n");
    System.out.print("Enter your guess: ");
        
    guess = input.nextInt();
        
    if (guess < 1 || guess > 10) { //if guess is < 1 OR guess > 10
        System.out.println("Invalid entry!");
    } else if (guess < 7) {
        System.out.println("Your guess is too low");
    } else if (guess > 7) {
        System.out.println("Your guess is too high");
    } else {
        System.out.println("*** Correct! ***");
    }

Review of Boolean Variables

  • Sometimes we need to evaluate a logical condition in one part of a program and use it elsewhere
  • To store a condition that can only be true or false, we use a Boolean variable
  • Boolean variables are named after George Boole (1815-1864), a pioneer in the study of logic
  • We specify a Boolean variable using the boolean type, which can hold just one of two values: true or false
    boolean isCool = true;
    boolean lies = false; 


Test Conditions and Boolean Values

  • Remember that test conditions always evaluate to true or false
    if (num > 0)
    
  • Thus we can use a boolean variable as a test condition
    boolean isPositive = (num >= 0);
    if (isPositive)
    
  • Note that we do not need to add a relational expression to a boolean variable, like:
    if (isPositive == true) // avoid!
  • Since the boolean variable already evaluates to true or false, adding the == true is redundant
  • Likewise, we do not need to use:
    if (isPositive != false) // avoid!
  • If we want to reverse the test condition, we can use the not (!) operator
    if (!isPositive)
  • We can see the use of a Boolean variable in the following example


Example Application Using a Boolean Variable

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

public static void main(String[] args)
{

    int num;
    Scanner input = new Scanner(System.in);
    System.out.print("Enter a number: "); num = input.nextInt(); boolean isPositive = (num >= 0); System.out.println("The test evaluated to: " + isPositive); if (isPositive) { System.out.println("The number was 0 or positive"); } else { System.out.println("The number was negative"); } }

Introducing &&, || and !

Logical operators and search engines video


Combining Test Conditions with Logical Operators

  • logical operator, or Boolean operator, is an operator that treats operands as Boolean values (true or false)
  • Java has several logical operators, but we only need to use three to create any possible test condition
  • These three operators are andor and not, which are discussed below
  • These logical operators are traditionally written as && (and), || (or) and ! (not)

Truth Tables for AND, OR and NOT

&& (AND) Operator Truth Table
expr1
expr2
expr1 && expr2
ExampleResult
truetruetrue5 < 10 && 5 > 2true
truefalsefalse5 < 10 && 5 < 2false
falsetruefalse5 > 10 && 5 > 2false
falsefalsefalse5 > 10 && 5 < 2false
|| (OR) Operator Truth Table
expr1
expr2
expr1 || expr2
ExampleResult
truetruetrue5 < 10 || 5 > 2true
truefalsetrue5 < 10 || 5 < 2true
falsetruetrue5 > 10 || 5 > 2true
falsefalsefalse5 > 10 || 5 < 2false
not (!) Operator Truth Table
If expr is...Then ! expr is...ExampleResult
truefalse!truefalse
falsetrue!(5 < 2)true


Testing Multiple Conditions Using Logical Operators

  • Sometimes we need to test for multiple conditions using a single if statement
  • In this case, we will need to chain together the two conditions using a logical operator, either && or ||
  • Note that one either side of the logical operator there must be a stand alone test condition that resolves to true or false

if (age >= 18 && age <= 25) //Correct!!!

if (age >= 18 && <= 25) //No! Incorrect!!

  • For example, we want to test if an age is between 18 and 65
  • We need to test that both parts of are true: is the age >= 18 AND is the age <= 65

int age = 0;
System.out.print("Enter your age: ");
age = input.nextInt();
if (age >= 18 && age <= 65)
{
    System.out.println("Adult!");
} else {
    System.out.println("Child, Teen or Older Adult!");
}


  • Another way to use logical operators to test the age is:
    int age = 0;
    System.out.print("Enter your age: ");
    age = input.nextInt();
    if (age < 18 || age > 65)
    {
        System.out.println("Child, Teen or Older Adult!");
    } else {
        System.out.println("Adult!");
    }
    
  • Many people confuse && and || conditions, especially when learning about logical operators
  • A value lies between 18 and 65 if the value is at least 18 and at most 65
  • A value is outside that range if it is less than (but not equal to) 18 or greater than (but not equal to) 65
  • There is no golden rule; we have to think carefully and test our conditions

Parenthesis

  • Remember that Boolean expressions in an if statement can be enclosed in parenthesis
  • Thus, an if statement with && might look like:
    if ((guess != GUESS1) && (guess != GUESS2))
  • However, relational operators have a higher precedence than logical operators, so the extra parenthesis are not necessary
  • As such, we can remove the inner parenthesis without affecting the logical meaning:
    if (guess != GUESS1 && guess != GUESS2)
  • However, if using parenthesis is easier to understand then use the extra parenthesis


Activity 11.2: What's Your Generation? (10 pts)

  • There are 6 generations living in America, side-by-side, today.
  • Your program will determine to which generation a user belongs.
  • Find a partner for pair programming, then open up a new project and name it Generation.
  • You will need to take as input the year of his or her birth.
  • Then, you will need a series of test conditions (think if - else if - else) to determine the generation of your user.
  • You will also need to use logical operators (&&, ||, !).
  • Below is a chart with the range of birth years for each generation.
  • Note the double quotes around each generation's name. For full credit, you must include the " when you output the generation.
Years of Birth                    Generation
1900-1927                           "The Greatest Generation"
1928-1945                           "The Silents"
1946-1964                           "The Baby Boomers"
1965-1979                           "Generation X"
1980-1999                           "The Millennial Generation"
2000-2018                           "Generation Z"

  • Your goal is to prompt the user for his or her year of birth and then print out a message about which generation he or she belongs to.
  • To start, print the following message to the user:

    What's your generation?
  • Then, you will need a variable to store the user's year of birth:
int year_of_birth;
  • Next, prompt your user to enter his or her year of birth with a statement like the following:
Please enter the year of your birth: _
  • Subsequently, you will need 6 if and if else statements like the following:
if ( year_of_birth >= 1900 && year_of_birth < 1928)
{
    System.out.println("You belong to the \"Greatest Generation\"");
}
else if ( year_of_birth >= 1928 && year_of_birth < 1946)
{
    System.out.println("You belong to the \"The Silents\"");
}
//rest of your else ifs and your else clause go here
  • Important: Why are we using && here and not ||?
  • Finally, you will need to do some error checking of the user input.
  • If the user inputs a date that is either too high or too low, your program must print out the following message:
Invalid entry. Please enter a birth year in the range 1900 - 2018.
  • The above should go in your else clause
  • Make sure your output is identical to the sample output below before you submit.
  • When you are finished, upload Generation.java to Canvas

What's your generation?
Please enter the year of your birth: 1926
You belong to the "Greatest Generation".

Alternately,

What's your generation?
Please enter the year of your birth: 2020
Invalid entry! Please enter a birth year in the range 1900 - 2018.

More Information on Logical Operators

Conditional Pitfalls

  • Below are some common mistakes when using logical operators.
  • Fortunately, Java gives you an error message when you make the below mistakes.

Using = Instead of ==

  • One common mistake is to use = when you meant to use ==
  • For example, look at the test condition in the following code:
    if (guess = 7) {
        System.out.println("*** Correct! ***");
    } else {
        System.out.println("Sorry, that is not correct.");
    }
    
  • Fortunately, if you make this mistake, the Java compiler will not allow your code to run.

  • However, if you correctly use == then your code will compile
    if (7 == guess) {

Strings of Inequalities

  • Do NOT use a string of inequalities like the following:
    int a = 5, b = 1, c = 10;
    if (a < b < c) {
        System.out.println("b is between a and c");
    } else {
        System.out.println("b is NOT between a and c");
    }
    
  • Again, your code will not compile

  • Instead, the correct way is to use && as follows:
    int a = 5, b = 1, c = 10;
    if (a < b && b < c) {
        System.out.println("b is between a and c");
    } else {
        System.out.println("b is NOT between a and c");
    }
    

Strings of Logical Operators

  • Logical expressions often read like "normal" English.
  • However, Java requires more exactness than English
  • For example, the following code will compile and run but give wrong results:
    int guess;
    System.out.print("Enter a guess: ");
    guess = input.nextInt();
    if (guess == 7 || 8) {
        System.out.println("*** Correct! ***");
    } else {
        System.out.println("Sorry, that is not correct.");
    }
    
  • The above produces an error when you try to compile your code.

  • Instead, the correct way is to use || as follows:
int guess;
System.out.print("Enter a guess: ");
guess = input.nextInt();
if (guess == 7 || guess == 8) {
    System.out.println("*** Correct! ***");
} else {
    System.out.println("Sorry, that is not correct.");
}




Wrap Up

  • With your partner, answer the questions from today's learning objectives


Upcoming Assignments

  • Lab 6 due Friday