Skip to content

Control Flows and Operators

Control flows are a method of controlling the flow of our execution in our program’s the next few sections will cover

  • Comparison Operators
  • Logical Operators
  • Conditional Statements
  • Loops
  • Error Handling

Comparison operators are used to compare values

Equal to Operator

int x = 1;
int y = 1;
System.out.println(x == y);
// This will return true as the value's are equal

Does not equal operator

int x = 1;
in y = 1;
System.out.println(x != y);
// This will return false as the value's are equal
// != represent's "Does not equal"

Greater Than Operator

int x = 1;
in y = 1;
System.out.println(x > y);
// False as not greater than;
System.out.println(x >= y);
// True as "Greater than OR equal to" values are equal

Less Than Operator

int x = 1;
in y = 1;
System.out.println(x < y);
// False as not less than;
System.out.println(x <= y);
// True as "Less than OR equal to" values are equal

Logical operators are used to create and combine multiple expressions to create a set of values to compare against.

As an example we are given a task to evaluate if a temperature is within a range that is considered warm.

int temperature = 22;
boolean isWarm = temperature > 20 && temperature <30;
System.out.println("Is it warm? " + isWarm);

Java evaluates the above statements from left to right here we are using the && (and) operator to evaluate our value against two conditions providing an upper and lower limit.

boolean hasHighIncome = true;
boolean hasGoodCredit = true;
boolean isEligibleForLoan = hasHighIncome || hasGoodCredit;
System.out.println("Are you eligible for credit? " isEligibleForLoan);

Here we are using the || (OR) Logical Operator to evaluate our conditions from left to right returning loan eligibility, should hasHighIncome be set to false and hasGoodCredit true, the program would return true as it would continue evaluating and return the last statement accordingly.

boolean hasHighIncome = true;
boolean hasGoodCredit = true;
boolean hasExternalRisks = false;
boolean isEligibleForLoan = (hasHighIncome || hasGoodCredit) && !hasExternalRisks;
System.out.println("Are you eligible for credit? " + isEligibleForLoan);

We have now added another condition to check for loan eligibility by using the ! (NOT) operator. The ! (NOT) operator reverses the boolean value. If the original condition is true, ! will turn it into false, and vice versa..

Our final eligibility criteria to provide a loan now becomes:

  • Has a high income.
  • Has good credit
  • Does NOT have external risks

We have also wrapped our original two conditionals in brackets reverting to a single truthy being required as the first parameter of isEligibleForLoan

if statements allow you to build programs that can make decisions based on certain conditions.

Let’s take our previous temperature scenario:

  • If temperature is greater than 30
    • Print “It’s a hot day”, “Drink plenty of water!”
  • Otherwise if it’s between 20 and 30
    • Print “It’s a nice day”
  • Otherwise
    • Print “It’s cold (brr)”
int temp = 32;
if (temp > 30) {
System.out.println("It's a hot day");
System.out.println("Drink plenty of water!");
}
else if (temp > 20)
/*Note the lack of braces here - for single line
returns, braces are optional and down to preference.*/
System.out.println("It's a nice day");
else
System.out.println("It's cold (brr)");

A few things to note:

  • Single line returns do not require a curly brace wrapper, this is down to personal preference.
  • Using proper indentation is a great way to make your code easier to read.
  • The conditions are evaluated top to bottom, so ensuring the correct order is important for reducing redundancy in your code.

Braces are optional for single line returns, I tend to lean on the side of using braces and here’s why.

  • Chances of you coming back to clean up code or add functionality in a scope is high therefore preparing for this early means less likely hood of having errors.
  • I find it visually easier to follow what’s in the scope of the condition (where it starts and ends) - Most IDE’s and markup language’s also make it easy to see this.
  • If you are dealing with a group that might not know the nuances of Java specifically they might be confused by a mismatch in standards used in your code base.

Moving forward I will provide snippets with bracers but again. It comes down to personal preference!

Let’s have a look at some code:

int income = 120_000;
if (income > 100_000) {
boolean hasHighIncome = true;
}

This will return an error as Java only allows declarations within code blocks defined by curly braces

int income = 120_000;
if (income > 100_000) {
boolean hasHighIncome = true;
}

Now we have a new problem in Java variables are scoped from parent block down, as our variable has been defined in the if statements code block accessing that variable will only be available and scoped to the if statement and it’s child blocks.

int income = 120_000;
boolean hasHighIncome;
if (income > 100_000) {
hasHighIncome = true;
} else {
hasHighIncome = false;
}

Although this works, there is some redundancy in the else clause. Specifically, we’re setting hasHighIncome to false in the else block, but we can simplify this by directly initialising the variable with a default value before the if statement. This removes the need for the else block entirely, making the code more compact and easier to read.

int income = 120_000;
boolean hasHighIncome = false;
if (income > 100_000) {
hasHighIncome = true;
}

Now we no longer need the else clause making the code more compact and easier to read. Java does have a way to further optimise situations like this, lets have a look:

int income = 120_000;
boolean hasHighIncome = (income > 100_000);

And here we have implemented a simple, elegant professional way to represent a boolean representation of income being above 100,000.

A ternary operator allows our program to return results based on a condition being true or false in a single line reducing the number of lines required to execute this function. Below is an example of a ternary operator:

int income = 120_000;
String className = income > 100_000 ? "First" : "Economy";

Here we are setting the return value of className a String by evaluating if our income value is greater than 100,000. A ternary is structured as:

condition ? (Question mark to denote the ternary operation) Truth Value : (Colon to represent the split to a false value) False Value

String returnedValue = initialValue < benchmarkValue ? "Truth" : "False";

We use switch statements to execute different parts of code dependant on our observed value. Switch statements are a great way to make multiple choice conditionals easier to read, the same effect can be achieved by an if statement however good quality code needs to be readable as well as functional.

String role = "admin";
switch (role){
case "admin":
System.out.println("Congrats, you are an admin!");
break;
case "moderator":
System.out.println("Moderate away!");
break;
default:
System.out.println("You're a guest");
}

A case in a switch statement is similar to an if statement, but it functions by comparing a variable (or expression) against a set of predefined constant values. We use the switch statement to evaluate a variable that may have multiple possible values, and then the case checks for specific values that are important to execute the corresponding code. Each case represents a fixed, static value that the expression is compared against. The case labels themselves are rigid in that they can only be set to constant values and cannot be variables, expressions, or dynamic values (such as the result of a function call). This means the values within the case statements must be constant literals or enumerated types.

In Java once a case is matched the preceding code block will execute, It is important to note that each code block will require a break; in order for the program to exit the switch statement. Without a break; the program will continue executing the next case blocks code - this practice is called a fall-through and may be intentional in some cases.

Providing a default case in a switch statement is considered good practice. It ensures that the program will execute a code block when none of the case labels match the value of the switch expression. This provides a fallback action, which is particularly useful for handling unexpected or invalid values.

The default case is typically placed at the bottom of the switch block, as it serves as the “catch-all” for any unmatched values.