A Java statement is a minimal construct that can be executed. It describes an action and ends with a semicolon (;
). We have seen many statements already. For example, here are three statements:
float f = 23.42f;
String sf = String.valueOf(f);
System.out.println(sf);
The first line is a declaration statement combined with an assignment statement. The second line is also a declaration statement combined with an assignment statement and method invocation statement. The third line is just a method invocation statement.
Here is a list of Java statement types:
- An empty statement that consists of only one symbol,
;
(semicolon) - A class or interface declaration statement (we will talk about this inChapter 2,Java Object-Oriented Programming (OOP))
- A local variable declaration statement:
int x
; - A synchronized statement: this is beyond the scope of this book
- An expression statement
- A control flow statement
An expression statement can be one of the following:
- A method invocation statement:
someMethod();
- An assignment statement:
n = 23.42f;
- An object creation statement:
new String("abc");
- A unary increment or decrement statement:
++x ; or --x; or x++; or x--;
We will talk more about expression statements in theExpression statements section.
A control flow statement can be one of the following:
- A selection statement:
if-else
orswitch-case
- An iteration statement:
for
,or while
, ordo-while
- An exception-handling statement:
throw
,try-catch
, ortry-catch-finally
- Abranching statement:
break
,continue
, orreturn
We will talk more about control statements in theControl flow statements section.
Expression statements
An expression statement consists of one or moreexpressions. An expression typically includes one or more operators. It can be evaluated, which means it can produce a result of one of the following types:
- A variable:
x = 1
, for example - A value:
2*2
, for example
It returns nothing when the expression is an invocation of a method that returnsvoid
. Such a method is said to produce only a side effect:void someMethod()
, for example.
Consider the following expression:
x = y++;
The preceding expression assigns a value to anx
variable and has a side effect of adding 1 to the value of they
variable.
Another example would be a method that prints a line, like this:
System.out.println(x);
Theprintln()
method returns nothing and has a side effect of printing something.
By its form, an expression can be one of the following:
- A primary expression: a literal, a new object creation, a field or method access (invocation).
- A unary operator expression:
x++
, for example. - A binary operator expression:
x*y
, for example. - A ternary operator expression:
x > y ? true : false
, for example. - A lambda expression:
x -> x + 1
(seeChapter 14,Java Standard Streams). - If anexpression consists of other expressions, parentheses are often used to identify each of the expressions clearly. This way, it is easier to understand and to set the expressions’ precedence.
Control flow statements
When a Java program is executed, it is executed statement by statement. Some statements have to be executed conditionally, based on the result of an expression evaluation. Such statements are called control flow statements because, in computer science, a control flow (or flow of control) is the order in which individual statements are executed or evaluated.
A control flow statement can be one of the following:
- A selection statement:
if-else
orswitch-case
- An iteration statement:
for
,while
, ordo-while
- An exception-handling statement:
throw
,try-catch
, ortry-catch-finally
- A branching statement:
break
,continue
, orreturn
Selection statements
Selection statements are based on an expressionevaluation and have four variations, as outlined here:
if
(expression) {do something}if
(expression) {do something}else
{do something else}if
(expression) {do something}else if
{do something else}else
{do something else}switch...case
statement
Here are some examples ofif
statements:
if(x > y){
//do something
}
if(x > y){
//do something
} else {
//do something else
}
if(x > y){
//do something
} else if (x == y){
//do something else
} else {
//do something different
}
Aswitch...case
statement is a variation of anif...else
statement, as illustrated here:
switch(x){
case 5: //means: if(x = 5)
//do something
break;
case 7:
//do something else
break;
case 12:
//do something different
break;
default:
//do something completely different
//if x is not 5, 7, or 12
}
As you can see, theswitch...case
statement forks the execution flow based on the value of the variable. Thebreak
statement allows theswitch...case
statement to be executed. Otherwise, all the following cases would be executed.
In Java 14, a newswitch...case
statement has been introduced in a less verbose form, asillustrated here:
void switchStatement(int x){
switch (x) {
case 1, 3 -> System.out.print("1 or 3");
case 4 -> System.out.print("4");
case 5, 6 -> System.out.print("5 or 6");
default -> System.out.print("Not 1,3,4,5,6");
}
System.out.println(": " + x);
}
As you can see, it uses an arrow (->
) and does not use abreak
statement.
Execute themain()
method of thecom.packt.learnjava.ch01_start.ControlFlow
class—see theselection()
method that calls theswitchStatement()
method with different parameters, as follows:
switchStatement(1); //prints: 1 or 3: 1
switchStatement(2); //prints: Not 1,3,4,5,6: 2
switchStatement(5); //prints: 5 or 6: 5
You can see the results from the comments.
If several lines of code have to be executed in each case, you can just put braces ({}
) around the block of code, as follows:
switch (x) {
case 1, 3 -> {
//do something
}
case 4 -> {
//do something else
}
case 5, 6 -> System.out.println("5 or 6");
default -> System.out.println("Not 1,3,4,5,6");
}
The Java 14switch...case
statementcan even return a value, thus becoming in effect aswitch
expression. For example, here is a case when another variable has to be assigned based on theswitch...case
statement result:
void switchExpression1(int i){
boolean b = switch(i) {
case 0, 1 -> false;
case 2 -> true;
default -> false;
};
System.out.println(b);
}
If we execute theswitchExpression1()
method (see theselection()
method of thecom.packt.learnjava.ch01_start.ControlFlow
class), the results are going to look like this:
switchExpression1(0); //prints: false
switchExpression1(1); //prints: false
switchExpression1(2); //prints: true
The following example of aswitch
expression is based on a constant:
static final String ONE = "one", TWO = "two", THREE = "three",
FOUR = "four", FIVE = "five";
void switchExpression2(String number){
var res = switch(number) {
case ONE, TWO -> 1;
case THREE, FOUR, FIVE -> 2;
default -> 3;
};
System.out.println(res);
}
If we execute theswitchExpression2()
method (see theselection()
method of thecom.packt.learnjava.ch01_start.ControlFlow
class), the results are going to look like this:
switchExpression2(TWO); //prints: 1
switchExpression2(FOUR); //prints: 2
switchExpression2("blah"); //prints: 3
Here’s yet another example of aswitch
expression, this time based on theenum
value:
enum Num { ONE, TWO, THREE, FOUR, FIVE }
void switchExpression3(Num number){
var res = switch(number) {
case ONE, TWO -> 1;
case THREE, FOUR, FIVE -> 2;
};
System.out.println(res);
}
If we execute theswitchExpression3()
method (see theselection()
method of thecom.packt.learnjava.ch01_start.ControlFlow
class), the results are going to look like this:
switchExpression3(Num.TWO); //prints: 1
switchExpression3(Num.FOUR); //prints: 2
//switchExpression3("blah"); //does not compile
In case a block of code has to be executed based on a particular input value, it is not possible to use areturn
statement because it is reserved already for the returning value from a method. That is why, to return a value from a block, we have to use ayield
statement, as shown in the following example:
void switchExpression4(Num number){
var res = switch(number) {
case ONE, TWO -> 1;
case THREE, FOUR, FIVE -> {
String s = number.name();
yield s.length();
}
};
System.out.println(res);
}
If we execute theswitchExpression4()
method (see theselection()
method of thecom.packt.learnjava.ch01_start.ControlFlow
class), the results are going to look like this:
switchExpression4(Num.TWO); //prints: 1
switchExpression4(Num.THREE); //prints: 5
Iteration statements
An iteration statement can take one of the followingthree forms:
- A
while
statement - A
do...while
statement - A
for
statement, also called aloop
statement
Awhile
statement looks like this:
while (boolean expression){
//do something
}
Here is a specific example (execute themain()
method of thecom.packt.learnjava.ch01_start.ControlFlow
class—see theiteration()
method):
int n = 0;
while(n < 5){
System.out.print(n + " "); //prints: 0 1 2 3 4
n++;
}
In some examples, instead of theprintln()
method, we use theprint()
method, which does not feed another line (does not add a line feed control at the end of its output). Theprint()
method displays the output in one line.
Ado...while
statement has a very similar form, as we can see here:
do {
//do something
} while (boolean expression)
It differs from awhile
statement by always executing the block of statements at least once before evaluating the expression, as illustrated in the following code snippet:
int n = 0;
do {
System.out.print(n + " "); //prints: 0 1 2 3 4
n++;
} while(n < 5);
As you can see, it behaves the same way when the expression istrue
at the first iteration. But if theexpression evaluates tofalse
, theresults are different, as we can see here:
int n = 6;
while(n < 5){
System.out.print(n + " "); //prints nothing
n++;
}
n = 6;
do {
System.out.print(n + " "); //prints: 6
n++;
} while(n < 5);
for
statement syntax looks like this:
for(init statements; boolean expression; update statements) {
//do what has to be done here
}
Here is how afor
statement works:
init
statements initialize a variable.- A Boolean expression is evaluated using the current variable value: if
true
, the block of statements is executed; otherwise, thefor
statement exits. update
statements update the variable, and the Boolean expression is evaluated again with this new value: iftrue
, the block of statements is executed; otherwise, thefor
statement exits.- Unless exited, the final step is repeated.
As you can seehere, if you aren’t careful, you can get into an infinite loop:
for (int x = 0; x > -1; x++){
System.out.print(x + " "); //prints: 0 1 2 3 4 5 6 ...
}
So, you have to make sure that the Boolean expression guarantees eventual exit from the loop, like this:
for (int x = 0; x < 3; x++){
System.out.print(x + " "); //prints: 0 1 2
}
The following example demonstrates multiple initialization andupdate
statements:
for (int x = 0, y = 0; x < 3 && y < 3; ++x, ++y){
System.out.println(x + " " + y);
}
And here is a variation of the preceding code for statements for demonstration purposes:
for (int x = getInitialValue(), i = x == -2 ? x + 2 : 0,
j = 0; i < 3 || j < 3 ; ++i, j = i) {
System.out.println(i + " " + j);
}
If thegetInitialValue()
method is implemented likeint getInitialValue(){ return -2; }
, then the preceding twofor
statements produce exactly the same results.
To iterate over an array of values, you can use an array index, like so:
int[] arr = {24, 42, 0};
for (int i = 0; i < arr.length; i++){
System.out.print(arr[i] + " "); //prints: 24 42 0
}
Alternatively, youcan use a more compact form of afor
statement that produces the same result, as follows:
int[] arr = {24, 42, 0};
for (int a: arr){
System.out.print(a + " "); //prints: 24 42 0
}
This last form is especially useful with a collection, as shown here:
List<String> list = List.of("24", "42", "0");
for (String s: list){
System.out.print(s + " "); //prints: 24 42 0
}
We will talk about collections inChapter 6,Data Structures, Generics, and Popular Utilities.
Exception-handling statements
In Java, there are classes calledexceptions that represent events that disrupt the normal execution flow. They typically have names that end withException
:NullPointerException
,ClassCastException
,ArrayIndexOutOfBoundsException
, to name but a few.
All the exception classes extend thejava.lang.Exception
class, which, in turn, extends thejava.lang.Throwable
class (we will explain what this means inChapter 2,Java Object-Oriented Programming (OOP)). That’s why all exception objects have common behavior. They contain information about the cause of the exceptional condition and the location of its origination (line number of the source code).
Each exception object can be generated (thrown) either automatically by the JVM or by the application code, using thethrow
keyword. If a block of code throws an exception, you can use atry-catch
ortry-catch-finally
construct to capture the thrown exception object and redirect the execution flow to another branch of code. If the surrounding code does not catch the exception object, it propagates all the way out of the application into the JVM and forces it to exit (and abort the application execution). So, it is good practice to usetry-catch
ortry-catch-finally
in all the places where an exception can be raised and you do not want your application to abort execution.
Here is a typical example of exception handling:
try {
//x = someMethodReturningValue();
if(x > 10){
throw new RuntimeException("The x value is out
of range: " + x);
}
//normal processing flow of x here
} catch (RuntimeException ex) {
//do what has to be done to address the problem
}
In the preceding code snippet, normal processing flow will be not executed in the case ofx > 10
. Instead, thedo what has to be done
block will be executed. But, in thex <= 10
case, the normal processing flow block will be run and thedo what has to be done
block will be ignored.
Sometimes, it is necessary to execute a block of code anyway, whether an exception was thrown/caught or not. Instead of repeating the same code block in two places, you can put it in afinally
block, as follows (execute themain()
method of thecom.packt.learnjava.ch01_start.ControlFlow
class—see theexception()
method):
try {
//x = someMethodReturningValue();
if(x > 10){
throw new RuntimeException("The x value is out
of range: " + x);
}
//normal processing flow of x here
} catch (RuntimeException ex) {
System.out.println(ex.getMessage());
//prints: The x value is out of range: ...
//do what has to be done to address the problem
} finally {
//the code placed here is always executed
}
We will talk about exception handling in more detail inChapter 4,Exception Handling.
Branching statements
Branching statements allow breaking of thecurrent execution flow and continuation of execution from the first line after the current block or from a certain (labeled) point of the control flow.
A branching statement can be one of the following:
We have seen howbreak
was used inswitch-case
statements. Here is another example (execute themain()
method of thecom.packt.learnjava.ch01_start.ControlFlow
class—see thebranching()
method):
String found = null;
List<String> list = List.of("24", "42", "31", "2", "1");
for (String s: list){
System.out.print(s + " "); //prints: 24 42 31
if(s.contains("3")){
found = s;
break;
}
}
System.out.println("Found " + found); //prints: Found 31
If we need to find the first list element that contains"3"
, we can stop executing as soon as thes.contains("3")
condition is evaluated totrue
. The remaining list elements are ignored.
In a more complicated scenario, with nestedfor
statements, it is possible to set a label (witha : column
) that indicates whichfor
statement has to be exited, as follows:
String found = null;
List<List<String>> listOfLists = List.of(
List.of("24", "16", "1", "2", "1"),
List.of("43", "42", "31", "3", "3"),
List.of("24", "22", "31", "2", "1")
);
exit: for(List<String> l: listOfLists){
for (String s: l){
System.out.print(s + " "); //prints: 24 16 1 2 1 43
if(s.contains("3")){
found = s;
break exit;
}
}
}
System.out.println("Found " + found); //prints: Found 43
We have chosen a label name ofexit
, but we could call it any other name too.
Acontinue
statement works similarly, as follows:
String found = null;
List<List<String>> listOfLists = List.of(
List.of("24", "16", "1", "2", "1"),
List.of("43", "42", "31", "3", "3"),
List.of("24", "22", "31", "2", "1")
);
String checked = "";
cont: for(List<String> l: listOfLists){
for (String s: l){
System.out.print(s + " ");
//prints: 24 16 1 2 1 43 24 22 31
if(s.contains("3")){
continue cont;
}
checked += s + " ";
}
}
System.out.println("Found " + found); //prints: Found 43
System.out.println("Checked " + checked);
//prints: Checked 24 16 1 2 1 24 22
Itdiffers frombreak
by stating which of thefor
statements need to continue and not exit.
Areturn
statement is used to return a result from a method, as follows:
String returnDemo(int i){
if(i < 10){
return "Not enough";
} else if (i == 10){
return "Exactly right";
} else {
return "More than enough";
}
}
As you can see, there can be severalreturn
statements in a method, each returning a different value in different circumstances. If the method returns nothing (void
), areturn
statement isnot required, although it is frequently used for better readability, as follows:
void returnDemo(int i){
if(i < 10){
System.out.println("Not enough");
return;
} else if (i == 10){
System.out.println("Exactly right");
return;
} else {
System.out.println("More than enough");
return;
}
}
Execute thereturnDemo()
method by running themain()
method of thecom.packt.learnjava.ch01_start.ControlFlow
class (see thebranching()
method). The results are going to look like this:
String r = returnDemo(3);
System.out.println(r); //prints: Not enough
r = returnDemo(10);
System.out.println(r); //prints: Exactly right
r = returnDemo(12);
System.out.println(r); //prints: More than enough
Statements are the building blocks of Java programming. They are like sentences in English—complete expressions of intent that can be acted upon. They can be compiled and executed. Programming is like expressing an action plan in statements.
With this, theexplanation of the basics of Java is concluded. Congratulations on getting through it!