Java Flow Control: if and if-else Statements

Java Flow Control: if and if-else Statements

Introduction

Conditional statements and loops are a very important tool in programming. There aren't many things we could do with code that can only execute line-by-line.

That's what "flow control" means - guiding the execution of our program, instead of letting it execute line-by-line regardless of any internal or external factors. Every programming language supports some form of flow control, if not explicitly via ifs and fors or similar statements - then it implicitly gives us the tools to create such constructs, i.e. low-level programming languages usually achieve that affect with a lot of go-to commands.

Loops were a concept used long before computer programming was even a thing, but the first person to use a software loop was Ada Lovelace, commonly known by her maiden name - Byron, while calculating Bernoulli numbers, back in the 19th century.

go-to commands are to be avoided in most situations, whenever we're using a programming language that gives us the tools to avoid it, like Java and all remotely similar languages do (there's a slight exception to this rule when breaking nested loops).

In Java, there are several ways to control the flow of the code:

The if Statement

The if statement is probably the most common form of flow control, regardless of the language. It's very simple and intuitive:

if(true) {
    //execute this code block if the argument/expression is true
    //some more code
}

Since in a lot of cases, only a single line needs to be executed, you can skip using the curly brackets and a block of code and simply indent the next line, though this only works for a single line:

if(true) 
    System.out.println("Inside the if block");
	System.out.println("I have nothing to do with the if block!");
System.out.println("Neither do I!");

Typically, we don't input boolean values like in these examples, but rather, we use an expression:

if(username != null)
    System.out.println(username);
if(argument >= 10) 
    System.out.println("The input is higher or equal than 10");

If the expression is false, the code belonging to the if statement is simply skipped:

if(1 > 5)
    System.out.println("Hello");
System.out.println(" World!");

And the output is:

 World!

The if-else Statement

We rarely wish to simply skip a piece of code if the expression is evaluated to be false. Typically, we want to do something else in that case:

if(expression) {    
    //code that executes only if the expression is true
}
else {// optional
    //code that executes only if the expression is false
}

Of course, you can use the else statement in conjunction with the shortened if statement:

if(expression) 
    //code that executes only if the expression is true
else
    //code that executes only if the expression is false    

However this is unrecommended to if you're not dealing with simple statements, especially with nested ifs since it's hard to figure out "which if does a particular else belong to". Using brackets will take ambiguity out of the problem if you find this approach unreadable.

The else statement statement is optional, so there's no need to write an empty else {} block if we don't want anything to happen if is the expression is false.

The else statement is intrinsically tied to the if statement and can't exist without it. It must appear right after the if statement otherwise an "else without if" compiler error will appear.

In most cases, we want to compare something for equality - whether one variable has the same value as another or whether it's smaller/larger than another:

String s = "smol";

if (s.length() > 8)
    System.out.println("s has too many characters!");
else 
    System.out.println("Ok, so basically, s is very " + s);

The > operator here has the usual "greater than" meaning, and Java supports the usual group of relational operators. These include <, >, <=, =>, == checks for equality and != checks for inequality.

Note: Make sure to use == in if statements instead of =, or else you may assign a value instead of compare it.

2 < 5   //true
2 < 2   //false
2 <= 2  //true
2 == 3  //false
2 != 3  //true

Note: Most of the time, we don't compare String variables using == but with the .equals() method. == checks for object reference equality. For primitive types (int, char, etc.) it's the same as checking whether they have the same value, but with Strings it most commonly isn't.

if(string1.equals(string2))
    //code to be executed if the strings are equal by value

Nested if Statements

We can have more than one if statement connected, either by nesting (putting one if statement inside another) or adding an else if at the end of our previous if:

Free eBook: Git Essentials

Check out our hands-on, practical guide to learning Git, with best-practices, industry-accepted standards, and included cheat sheet. Stop Googling Git commands and actually learn it!

int ourNumber = 10;

if(ourNumber > 8){ 
    if(ourNumber % 2 == 0){
       System.out.println("The number is larger than 8 and even");
    }
}
else if (ourNumber == 1) {
    System.out.println("1 is less than 8, so the previous if block isn't executed");
}
else {
    System.out.println("ourNumber is less than 8 and different than 1");
}

else blocks always "belong" to the if of the same level, so the else if (ourNumber == 1) in our code belongs to the if(ourNumber > 8) and not the nested if that checks whether the number is even.

You can have as many else if blocks as you'd like, but only one else block, which comes last. Each if, else if and else block that evaluates to true will execute:


Multiple Expressions in a Single if Statement

Another very useful thing is the ability to check multiple conditions in a single if:

int ourNumber = 10;

if(ourNumber > 5 && (ourNumber % 2 == 0)){
    System.out.println("The number is larger than 8 and even");
}

The && operator is one of the logical operators Java supports. boolExpr is used as shorthand for boolean expression. Reminder: a boolean expression is an expression that can be evaluated as true or false, i.e. it can also be an expression containing a logical operator, as we can see here:

  • !boolExpr - ! is negation, it evaluates a true expression to false and vice versa.
  • boolExpr1 & boolExpr2 - the AND operator evaluates to true if both expressions are true.
  • boolExpr1 | boolExpr2 - the OR operator evaluates to true if at least one of the expressions is true.
  • boolExpr1 && boolExpr2 - the short-circuit AND operator evaluates to true only if boolExpr1 and boolExpr2 are both true. It's called a short-circuit operator because if the first expression is false, it won't even evaluate the second expression as the basic condition that both need to be true can never occur. With simple expressions, this doesn't affect the code in a meaningful way, but in production code, both expressions can be costly operations and this approach can significantly optimize code.
  • boolExpr1 || boolExpr2 - the short-circuit OR operator evaluates to true if at least one of boolExpr1 and boolExpr2 is true. A short-circuit version of the | operator.
  • boolExpr1 ^ boolExpr2 - the XOR operator evaluates to true only if boolExpr1 and boolExpr2 are evaluate as differently, i.e. if only one of them is true and the other one is false.
true && false //false
(2 < 5) && (2 != 3) //true
false || true //true
true && ((false || false) ^ true) //true
(true && false) || false // false

It's highly recommended to use parentheses whenever it makes sense to use them. The last example works the same without parentheses but relying on operator precedence is extremely risky and leads to unreadable code.

Ternary Constructs

The only ternary operator (an operator that takes three operands) in Java is the ?: operator. It works like a very compact if-else statement.

int max = 0;
if (a > b)
    max = a;
else max = b;

//can be written as
int max = (a > b) ? a : b; 

Here's how a ternary construct generally looks like:

(expression) ? returnValueIfTrue : returnValueIfFalse

Ternary constructs can work without parentheses as well, though it's generally more readable to use parentheses:

int max = a > b ? a : b;

You can also use ternary constructs to modify variables:

System.out.println("10% discount for orders above $50!");
double orderPrice = 55;
double finalPrice = orderPrice > 50 ? orderPrice*09 : orderPrice;
System.out.println("Your final price is $" + finalPrice);

And the output is:

Your final price is $49.5

Using the construct, we can also call methods:

public void someMethod() {
    String userRole = "Admin";
    String result = userRole.equals("Admin") ? greetAdmin() : greetUser();
    System.out.println(result);
}

static String greetAdmin() {
    return "Hello Admin!";
}
static String greetUser() {
    return "Hello User!";
}

Logically, this would result in:

Hello Admin!

Nested Ternary Constructs

System.out.println("10% discount for all orders above $50 and additional $5 off if your order exceedes 2 items!");
double orderPrice = 140;
int quantity = 5;
double finalPrice = (orderPrice > 50) ? (quantity > 2) ? (orderPrice*0.9)-5 : orderPrice*0.9 : orderPrice;
System.out.println("Your final price is: $" + finalPrice);

Since both conditions are true, the output is:

10% discount for all orders above $50 and additional $5 off if your order exceedes 2 items!
Your final price is: $121.0

However, this approach is horribly unreadable. If possible, avoid nesting ternary constructs, though if you must, break it down into simpler blocks. For an example, this example can be made a bit more readable:

System.out.println("10% discount for all orders above $50 and additional $5 off if your order exceedes 2 items!");
double orderPrice = 140;
int quantity = 5;
double finalPrice = (orderPrice > 50) ?
                        (quantity > 2) ?
                                (orderPrice*0.9)-5 : orderPrice*0.9
                    : orderPrice;
System.out.println("Your final price is: $" + finalPrice);

Conclusion

Flow control in code is essential for absolutely every application. Statements such as if and if-else are fundamental building blocks and every aspiring developer should be completely in control/aware of how they work.

Last Updated: May 6th, 2021
Was this article helpful?

Improve your dev skills!

Get tutorials, guides, and dev jobs in your inbox.

No spam ever. Unsubscribe at any time. Read our Privacy Policy.

Olivera PopovićAuthor

LinkedIn: https://rs.linkedin.com/in/227503161
If you need any help - post it in the comments :) That way someone else can reply if I'm busy.

Want a remote job?

    Prepping for an interview?

    • Improve your skills by solving one coding problem every day
    • Get the solutions the next morning via email
    • Practice on actual problems asked by top companies, like:
     
     
     

    Better understand your data with visualizations

    With over 330+ pages, you'll learn the ins and outs of visualizing data in Python with popular libraries like Matplotlib, Seaborn, Bokeh, and more.

    © 2013-2021 Stack Abuse. All rights reserved.