JBay Solutions Development Blog on Java, Android, Play2 and others
RSS RSS RSS RSS

Java Tutorial 7 - Starting Flow Control

  1. Introduction
  2. If Statement
  3. Switch Statement
  4. Wrapping up
  5. References

Introduction

This is where the fun part begins! With the previous tutorials we have and idea of the core building blocks, now we start looking at the implementation of flow control, or logic if you will. The most important statement for implementing logic, in my personal experience is the If statement.



If Statement

Lets jump right into an example! The If statement works like this:

if ( true )
    System.out.println("Evaluation was true");

We have the keywork if followed by a boolean expression that, as the name states, must evaluate to a boolean. In our particular example it will always evaluate to true.

If the expression evaluates to true (which is our example, it always does) , the next statement is executed. If the expression evaluates to false, then next statement is NOT executed , and the execution flow continues after the next statement.

Now lets look at the following modification we made:

if ( false )
    System.out.println("Evaluation was true");
    System.out.println("Evaluation was true, part 2");

The if boolean evaluation is always false now, so the first statement after the if is not executed. But the second print statement will be executed, because the if statement only conditions one statement. If we only wanted to have the two println statements execute if the previous condition was true, then we need to user a block, like so:

if ( false )  {
    System.out.println("Evaluation was true");
    System.out.println("Evaluation was true, part 2");
}

This would make the two println statements execute if the evaluation is true. Because in our previous example it is false, then the two println statement would not be executed.

Until now we have been using a boolean directly to define the behavior of the if statement, which makes this code execute always in the same way and no decision be actually made.

But, like it was said because, we can place any statement inside that if condition as long as it evaluates to a boolean.



Equality Operators

For comparing primitive variables, we have these Equality Operators:

  • == : Equal to
  • != : Not equal to
  • > : Greater than
  • >= : Greater than or equal to
  • < : Less than
  • <= : Less than or equal to

Look at the following code snippet:

int age = 10;

if ( age < 18 ) {
    System.out.println("Price of ticket : 50" );
}

if ( age == 18 ) {
    System.out.println("Price of ticket : 100" );
}

if ( age > 18 ) {
    System.out.println("Price of ticket : 120" );
}

Very easy to understand, yes?

  • If the variable age is smaller than ( < ) 18, the code will print : Price of ticket : 50
  • If the variable age is equal to ( == ) 18, the code will print : Price of ticket : 100
  • If the variable age is greater than ( > ) 18, the code will print : Price of ticket : 120

Nothing special, but now, lets try something else:

public static void main(String[] args) {

    String value1 = new String("good");
    String value2 = new String("good");

    if (value1 == value2) {
        System.out.println(" They are equal ");
    }

}

When we run this main method, we expected to see the program write They are equal to the console, but it produces nothing. The reason for this is that , like we said before, these operators are only to be used with Primitive Variables, and as we know, String is not a primitive type, it is an Object.

Objects are compared differently, but to fully understand the deal with Object, we must first talk about Reference Variables, which will happen in one or two tutorials. For now, lets focus on primitives and see what can be achieved with If statements .

Equality Operators are to be used with Primitive Variables. Comparing Objects with == might produce unexpected results.

Equality Operators can also be combined with boolean operators to create more complex boolean expressions.



Conditional Operators

These are some the available Conditional Operators:

  • & - AND
  • | - OR
  • && - Conditional AND
  • || - Conditional OR

Lets see them in use and understand the difference between an AND and a Conditional AND . We'll create a class for that purpose, and call it TestOperators. It will look like this:

package tutorial7;

public class TestOperators {

public void compareUsingAnd( int value1 , int value2) {

    if (  value1 >= 10 & value2 < 100 ) {
        System.out.println(" Condition is true ");
    }

}

}

What it means is, if :

  • value1 >= 10 : value1 variable is Greater or Equal than 10
  • & : AND
  • value2 < 100: value2 variable is Less than 100

Then :

  • System.out.println(" Condition is true ");

Now, on our Starter class, we create an instance of the TestOperators class and call that method like this:

public static void main(String[] args) {

    TestOperators test = new TestOperators();
    test.compareUsingAnd( 10, 50 );

}

When we run the code it produces:

 Condition is true 

Lets modify the code on the compareUsingAnd method like this :

package tutorial7;

public class TestOperators {

    public void compareUsingAnd( int value1 , int value2) {

        if (  firstComparison(value1) &   value2 < 100 ) {
            System.out.println(" Condition is true ");
        }

    }

    private boolean firstComparison(int value) {
        if ( value >= 10)
            return true;
        return false;
    }

}

It does exactly the same thing, but instead of doing the two individual comparisons inside the boolean expression, we create one method called firstComparison that performs exactly the same comparison and call that method instead. Lets just look at that method for a second :

private boolean firstComparison(int value) {
System.out.println("- Running firstComparison");

    if ( value >= 10)
        return true;

    return false;
}

From the signature of the method we know :

  • It is a private method, because it just needs to be accessible from inside the TestOperators class,
  • it returns a `boolean* value,
  • it receives an int parameter that we simply call value.

First it prints "- Running firstComparison", just so we know the method was called.

Then, if the value provided is Greater or Equal to 10, it returns true and the method finishs (a method finishes after the return statement).

If the value is NOT Greater or Equal to 10, then it does not return true;, so it continues executing, and returns false.

We run our program and it produces:

- Running firstComparison
 Condition is true 

So firstComparison evaluated to true, and value2 < 100 also evaluated to true.



Now, as an exercise and because we need it to continue the rest of the tutorial, create a method called secondComparison and do the same thing we did with firstComparison.

The end result should look like this :

package tutorial7;

public class TestOperators {

    public void compareUsingAnd( int value1 , int value2) {

        if (  firstComparison(value1)  &  secondComparision(value2) ) {
            System.out.println(" Condition is true ");
        }

    }

    private boolean firstComparison(int value) {
        System.out.println("- Running firstComparison");

        if ( value >= 10)
            return true;
        return false;
    }

    private boolean secondComparision(int value) {
        System.out.println("- Running secondComparision");

        if ( value < 100)
            return true;
        return false;
    }
}

Running the previous main method will produce:

- Running firstComparison
- Running secondComparision
 Condition is true 

With these two methods we can see when the evaluations are made, and it is easier to explain concepts.

Lets modify the main method to call the compareUsingAnd method with values 1 and 50:

public static void main(String[] args) {

    TestOperators test = new TestOperators();
    test.compareUsingAnd( 1, 50 );

}

We compile and run this code and get:

- Running firstComparison
- Running secondComparision

As you can see, this time around there was no "Condition is true" being printed, and the reason is, if you follow the code, method firstComparison evaluates to false even tho secondComparision evaluates to true, and because :

false AND true = false

which is essencially what this mean :

if (  false  &  true ) {
    System.out.println(" Condition is true ");
}

The condition of the if is not meet, and the println statement is not executed.

If you have any doubts why false AND true = false then please check Wikipedia - Truth Tables. It is essential to have an understanding of logic operations of this kind.

Notice that because the first evaluation ( the firstComparison method) evaluates to false! Because we are using an AND, the if condition could never be satisfied, no matter what secondComparision evaluates to.

In an AND boolean operation , both arguments must be true for the result to be true

So :

  • false AND false = false
  • true AND false = false
  • false AND true = false

Only:

  • true AND true = true

Lets modify the compareUsingAnd method on the TestOperators class to this :

public void compareUsingAnd( int value1 , int value2) {

    if (  firstComparison(value1) && secondComparision(value2) ) {
        System.out.println(" Condition is true ");
    }

}

The only difference was changing & to && , so using Conditional AND instead of AND .

Compiling and running this new version produces the following:

- Running firstComparison

So, as you can see, secondComparision was never called.

This is the difference between AND and Conditional AND . The AND operator ( & ) evaluates both side of the AND before doing the boolean operation . The Conditional AND ( && ) first evaluates the first part , and only if the second part is necessary for the boolean operation, does it ever gets evaluated.

In our last example, because the first part evaluated to false , it is unnecessary to evaluate the second part.

Now, using && is not more or less correct that & . They are different , have different behaviors, and a programmer needs to be aware of this. Most of the time && is used, but there could be particular use-cases that require & instead of && .

OR and Conditional OR work exactly in the same way. OR ( | ) will evaluate both side of the boolean operation before evaluating the OR expression, while the Conditional OR ( || ) evaluates the first side, and only evaluates the second if necessary.



Else

Again, we'll modify the compareUsingAnd method like this :

public void compareUsingAnd( int value1 , int value2) {

    if (  firstComparison(value1) && secondComparision(value2) ) {
        System.out.println(" Condition is true ");
    } else
        System.out.println(" Condition is false ");

    System.out.println(" Finished ");
}

Notice the else keyword. This keyword is used together with If statements, to execute something when the if evaluation is not meet.

Compiling and running this code will produce :

- Running firstComparison
 Condition is false 
 Finished 

As like before, only the statement after the else keyword is execute. If the programmer wants to execute more statements in case the evaluation fails, then a block ( { } ) must be used, like this :

    if (  firstComparison(value1) && secondComparision(value2) ) {
        System.out.println(" Condition is true ");
    } else {
        System.out.println(" Condition is false ");
        System.out.println(" Condition is false ");
    }

Which would print the same thing twice..... just to demonstrate the block.

If Statements are binary, the expression evaluates either to true or false and there are only two paths of execution.

To allow for more paths of execution we could chain If Else Statements and create something like this:

    if ( age < 18) {
        System.out.println(" underage ");
    } else {

        if (age < 70) {
            System.out.println(" adult ");
        } else {
            System.out.println(" elder ");
        }

    }

This is completely valid, and commonly done.

Not

Also, there is a wait to invert a boolean. Lets look at the following code :

if ( age < 18) {
    System.out.println(" underage ");
} 

This is equivalent to :

if ( ! age >= 18) {
    System.out.println(" underage ");
} 

Notice the ! operator, that inverts the result of the age >= 18 expression.

So, if we have age defined like int age = 5 ; , this is how the evaluation would be evaluated :

  1. Replacing we get : if ( ! 5 >= 18 )
  2. 5 >= 18 is evaluated first , resulting in false , because 5 is not Getter nor Equal to 18.
  3. we would then have : if ( ! false )
  4. !false is true , because the ! changes the boolean value ( this is what it does )
  5. we have : if ( true )

Is this making sense?

In fact, to demonstrate this better, look at the following code :

boolean value = true;
System.out.println("Value is : " + value);

Executing this would produce :

Value is : true

Now, modifying the code like this :

boolean value = !true;
System.out.println("Value is : " + value);

Would produce :

Value is : false

So, as you can see, the ! operator just inverts the boolean.

There are many many other ways to control the flow of execution of a program, If Statements are one , another is the Switch Statement , which is not used as much as the If Statement but is also important to know.



Switch Statement

The Switch statement works a bit differently from the If Statement. The switch statement also takes an expression, but this expression must evaluate to byte, short, char, int, String.

Lets look at the following example:

int value = 1 ;

switch ( value ) {

    case 1:
        System.out.println("Detected");
        System.out.println("Value is 1");
        break;

}

If we were to execute this code, the result would be :

Detected
Value is 1

So what this does is:

  1. switch ( value) : the switch take the value the expression evaluates to. In this case the expression is just a value that evaluates to int.

  2. The value of the expression gets compared with all the case options available.

  3. Because the evaluation of the expression is 1 and there is a case that matches that case 1: , everything after that is executed until a break; is found.

Very simple!

Look at this modified version of the previous code:

int value = 2 ;

switch (value) {
    case 1:
        System.out.println("Detected");
        System.out.println("Value is 1");
        break;
    case 2:
        System.out.println("Detected");
        System.out.println("Value is 2");
        break;
    case 3:
        System.out.println("Detected");
        System.out.println("Value is 3");
        break;
}

In this example we modified the value the expression evaluates to, and we added a few other cases.

Compiling and executing this will produce :

Detected
Value is 2

There is also a special catch, which is the default case, which can be used to execute in case the expression does not evaluate to any of the other cases :

int value = 5 ;

switch (value) {
    case 1:
        System.out.println("Detected");
        System.out.println("Value is 1");
        break;
    case 2:
        System.out.println("Detected");
        System.out.println("Value is 2");
        break;
    case 3 :
        System.out.println("Detected");
        System.out.println("Value is 3");
        break;
    default:
        System.out.println("Nothing Detected");
        break;
}

Compiling and executing this will produce :

Nothing Detected

Very easy, yes ? But now , just out of curiosity, lets remove all the breaks; from the code. Give a look at this:

int value = 2 ;

switch (value) {

    case 1:
        System.out.println("Detected");
        System.out.println("Value is 1");
        //break;
    case 2:
        System.out.println("Detected");
        System.out.println("Value is 2");
        //break;
    case 3 :
        System.out.println("Detected");
        System.out.println("Value is 3");
        //break;
    default:
        System.out.println("Nothing Detected");
        //break;
}

Executing would produce :

Detected
Value is 2
Detected
Value is 3
Nothing Detected

Because value is now 2, it does not match the first case, but it matches case 2, so it starts executing until it finds the break; statement, which does not exist, so it executes until the end of the Switch statement.

It is very important to remember that, if a case matches, execution will be until a break; is reached, or the Switch body ends.

Wrapping up

So, with this basic knowledge of Flow Control, you are ready to try out a few exercises, just to get some practice in solving some small problems, and getting used to writing code. Check the first exercises section before going for the next Tutorial!



References



comments powered by Disqus