Java 11 Developer Certification - Java Decision Constructs

October 18, 2020

What we are covering in this lesson

  1. What are Java Decision Constructs
  2. If-Else
  3. Switch

What are Java Decision Constructs

The decision constructs or selection constructs are statements that are to be executed only under certain conditions. We have if/else statements and switch statements

If Else

The if statement allows conditional execution of a statement, or block of statements, or a choice of two statements or statement blocks. If there are no brackets after the if condition, only the next one line of code will be considered for the conditional block. You can have an empty statement block after the if or else as long as a semi-colon follows. Dangling else is assumed to go with the inner most if statement. Lets look at an example with dangling else scenario and also some precendence example with if-else.

package maxCode.online.Constructs;

public class IfElse {
	public static void main(String[] args) {
		boolean flag = false;
        boolean subflag = true;
        if (flag); // empty statement is valid, note the semi-colon at the end
        else System.out.println("1. flag is false");

        //Nested if else
        if (flag)
            if (subflag) System.out.println("2. subflag is true");
            else
                System.out.println("2. subflag is false"); // Dangling else
        else System.out.println("2. flag is false");

        // Dangling else
        if (flag)
            if (subflag) System.out.println("3. subflag is true");
        else System.out.println("3. flag is false"); // Dangling else

        // Formatted to confuse
        subflag = false;
        if (flag)
            if (subflag) System.out.println("4. subflag is true");
        else System.out.println("4. subflag is false");
        else System.out.println("4. flag is false"); // Is this an extra else?

        // Very common mistake, it is assignment and not comparison
        flag = false;
        if (flag = true) {
            System.out.println("5. flag is true");
        } else System.out.println("5. flag is false");

        //The following code tests precedence/assignment inside an if/else statement
        boolean a = false;
        boolean b = false;
        boolean c = false;

        if ((a = true) || (b = true) && (c = true)) ;
        System.out.println(a + " " + b + " " + c);

        //First set variables back to false
        a = false;
        b = false;
        c = false;
        if ((a = true) && (b = true) || (c = true)) ;
        System.out.println(a + " " + b + " " + c);
	}
}

Output

1. flag is false
2. flag is false
4. flag is false
5. flag is true
true false false
true true false

As you can see, nothing is printed for the outputs starting with 3. That is because flag value is false and there is no corresponding else for the same. The else that is there corresponds to the inner if. Also, dont get confused with how the lines are formatted as we can see two else together, but there is no error in it and both else correspond to their respective if. Another thing to note is the expression in the if condition. In the 5. flag is true output, the condition is not a comparison operation, rather it is an assignment operaration which returns true, and hence the output.

The last two outputs show how the precedence play a role in the if-else conditions. The line if ((a = true) || (b = true) && (c = true)) ; already has a semi-colon, so the line below it will not depend on the outcome of this line. Plus, the expression will be evaluated from left to right, and first part a = true will return true, and since we have logical OR operator, the next two expressions will be ignored. Same applies to the last output which is different due to logical AND.

Switch

The switch statement transfers the control to one of the several statements, based on the value of the expression.

  • A switch statement can only work with byte, short, char, and int primitive data types.
  • It also works with enumerated types, the String class, and the classes that wrap certain primitive types: Character, Byte, Short, and Integer.
  • The switch variable CANNOT be a long, double, float, or boolean, or any object other than the specified wrappers. If anything else is used, it will result in compiler error.
  • The default case label and block are optional. It only matches an argument if all the other labels do not regardless of its position.
  • The default label doesn’t have to be the last label in the case label list.
  • You can only have one default case label and block.
  • You don’t need any case labels in the switch block.
  • The break statement is optional. However, if it’s omitted, you are creating a fall-through situation, and all the cases below the selected case will also get executed.
  • Case labels must be the same data type as the result of the switch expression.
  • Paranthesis around the case labels are optional, so you can write case ("A") or case A, both are perfectly valid
package maxCode.online.Constructs;

public class Switch {
	// Set up an enumeration of week days
    enum Day {
        SUNDAY, MONDAY, TUESDAY, WEDNESDAY,
        THURSDAY, FRIDAY, SATURDAY
    }
    
	public static void main(String[] args) {
		String[] strs = {"A", "B", "C", "D"};
        
		int iteration = 0;
        for (String s : strs) {
            System.out.println("iteration " + (++iteration) + ", s=" + s);
            switch (s) {
                case "A":
                    System.out.println("In Case A");
                default:
                    System.out.println("In Default Case");
                case ("B"):
                    System.out.println("In Case B");
                case "C":
                    System.out.println("In Case C");
                case ("1" + "2"):  // concatenation operator in expression
                    System.out.println("Output is 12");
                    break;
            }
        }
        
        for (Day d : Day.values()) {
            switch (d) {
                case MONDAY:
                case TUESDAY:
                case WEDNESDAY:
                case THURSDAY:
                    System.out.println(d + ": Workday");
                    break;
 
                case FRIDAY:
                    System.out.println(d + ": It's Friday!");
                    break;
 
                case SATURDAY:
                case SUNDAY:
                    System.out.println(d + ": Weekends!");
                    break;
 
                default:
                    System.out.println("This will never get executed");
                    break;
            }
        }
	}
}

Output

iteration 1, s=A
In Case A
In Default Case
In Case B
In Case C
Output is 12
iteration 2, s=B
In Case B
In Case C
Output is 12
iteration 3, s=C
In Case C
Output is 12
iteration 4, s=D
In Default Case
In Case B
In Case C
Output is 12
SUNDAY: Weekends!
MONDAY: Workday
TUESDAY: Workday
WEDNESDAY: Workday
THURSDAY: Workday
FRIDAY: It's Friday!
SATURDAY: Weekends!

Note that everything gets printed for case "A" since none of the case statements have break. Same applies to the cases below. In case of label “D”, we do not have any case statement specified, so the default case gets executed, and since we do not have any break statement, the ones below default also get executed.

Expressions are allowed in case labels only if the compiler can evaluate them at compile time. In our case, "1" + "2" is evaluated to "12".

Lastly we have also used enum in the case label and have also used break statement which is resulting in only the correct case being executed.

If you use a byte variable in switch, the case labels must also be byte. If case has int for example, it will throw compiler error.

To break out of a loop from a switch conditional block, we would need to create a label for the loop and this label name in front of break. On using break label, we cannot use break again for the same case as it will case compiler error for unreachable code. We will cover the for loop and labels in the next tutorials.

When you see a switch statement on an exam,

  • Examine its location, check if it is participating in a loop?
  • Don’t let the breaks and continue statements mislead you.
  • Examine the switch expression, can you determine the type?
  • Does the type match the case labels?
  • Is the type valid?
  • double, float, long, boolean are all not valid.
  • Objects that are not strings or wrappers are also not valid, remembering enums are valid.
  • If the switch expression is a local variable, has it been initialised?

    • If it hasn’t, does the switch statement have a default block?

      • If not, then the answer is compiler error.
  • Examine the case labels, are they all compiler constants?
  • Variables are not permitted.
  • If case blocks do not have breaks, the code falls through, so multiple blocks could be executed.
  • And finally, remember that a default label doesn’t have to be the last one and it is not compulsory to include default label.