Вы находитесь на странице: 1из 332

Getting started with Java programming

language
Getting started with Java programming language is a hands-on guide to begin developing programs
using Java. This book is meant for students and professionals with little or no knowledge of Java.
The examples that accompany this book are based on Java 8. You can download the examples
(consisting of 30 sample projects) discussed in this book from the following Google Drive location:
https://drive.google.com/open?id=0B1IwsLB5TOglZXYxWW9JMndUX3M .

Chapter 1 – Hello World!


Chapter 2 – Variables, data types and operators
Chapter 3 – Control flow statements
Chapter 4 – Objects, classes and methods
Chapter 5 – Packages, access modifiers, static and this keywords
Chapter 6 – Object-oriented programming concepts
Chapter 7 – Abstract classes and interfaces
Chapter 8 – Exception handling
Chapter 9 – Arrays, immutability, recursive methods and wrapper classes
Table of Contents
Preface
How to use this book?
Conventions used in this book
Feedback and questions
About the authors
Chapter 1 - Hello World!
1-1 Introduction
1-2 Setting up the development environment
Downloading and installing JDK and Eclipse IDE
Configuring Eclipse IDE to use the installed JDK
1-3 Creating your first Java program
Creating a Java project
Creating the ‘Hello World !’ program
Java project structure
1-4 What makes Java platform-independent?
JDK and JRE
1-5 Importing projects into Eclipse IDE
QUIZ
1-6 Summary
Chapter 2 – Variables, data types and operators
2-1 Introduction
2-2 Variables and data types
Primitive types
Literals
F (or f) and L (or l) suffixes
Narrowing and widening conversions
2-3 Operators
Java expressions and statements
Arithmetic operators
Relational operators
Conditional operators
Assignment operators
Bitwise operators
2-4 Operator precedence
Intermediate expression types
Parentheses and operator precedence
QUIZ
2-5 Summary
Chapter 3 – Control flow statements
3-1 Introduction
Types of control flow statements
3-2 Conditional statements
if statement
Passing values to programs at execution time
if - else statement
switch statement
3-3 Looping statements
while statement
do - while statement
for statement
Nested loops
3-4 Branching statements
break statement
continue statement
3-5 Infinite loops
QUIZ
3-6 Summary
Chapter 4 – Objects, classes and methods
4-1 Introduction
4-2 Java class – the blueprint for creating objects
4-3 Creating objects of a class
4-4 Calling methods of an object
4-5 Attributes
Setting initial value (or default value) of an attribute
Instance vs local vs class variables
Default values of attributes
4-6 Constructors
Defining multiple constructors in a class
Default constructor of a class
4-6 Methods
return statement and program flow
QUIZ
4-7 Summary
Chapter 5 – Packages, access modifiers, static and this keywords
5-1 Introduction
5-2 Packages
Creating a package
Organizing classes in a project
import statement
Defining multiple classes with the same name
5-3 Access modifiers
5-4 static modifier
static variables and methods
Restrictions on static methods
5-5 this keyword
5-6 ‘Pass by value’
Called method changes value of the passed primitive type
Called method modifies the passed object’s attributes
Called method modifies the passed memory address
QUIZ
5-7 Summary
Chapter 6 – Object-oriented programming concepts
6-1 Introduction
a-2 Encapsulation
6-3 Inheritance
extends keyword
super keyword
Method overriding
Restrictions on the overriding method
Upcasting and downcasting
Inheritance and is-a relationship
Multi-level inheritance
6-4 Polymorphism
Hiding superclass’s instance (or static) variables and static methods
6-5 Method and constructor overloading
6-6 java.lang.Object class
equals method
toString method
QUIZ
6-7 Summary
Chapter 7 – Abstract classes and interfaces
7-1 Introduction
7-2 Abstract classes
Using a concrete class as a superclass
Using an abstract class as a superclass
7-3 Interfaces
Multiple inheritance and interfaces
Interface inheritance
Interfaces vs abstract classes
7-4 instanceof operator
7-5 final keyword
final classes
final methods
final variables
final arguments
7-6 static and instance initializer blocks
QUIZ
7-7 Summary
Chapter 8 – Exception handling
8-1 Introduction
8-2 Exception classes
java.lang.NullPointerException
java.lang.ClassCastException
java.lang.ArithmeticException
8-3 Exception propagation and handling
Catching exceptions
finally block
8-4 Custom exception types
QUIZ
8-5 Summary
Chapter 9 – Arrays, immutability, recursive methods and wrapper classes
9-1 Introduction
9-2 Creating and initializing arrays
9-3 Accessing array elements
9-4 Passing and returning arrays
9-5 Multi-dimensional arrays
9-6 String object and immutability
9-7 Recursion
Calculating factorial of a number using recursion
Finding a number using binary search
9-8 Wrapper classes
QUIZ
9-7 Summary
Answers to quizzes
Chapter 1
Chapter 2
Chapter 3
Chapter 4
Chapter 5
Chapter 6
Chapter 7
Chapter 8
Chapter 9
INDEX
Preface
How to use this book?
1. Download samples
This book comes with many sample programs that you can download as a single ZIP file
named java-book-code from the following Google Drive location: https://drive.google.com/open?
id=0B1IwsLB5TOglZXYxWW9JMndUX3M .

Unzipping the downloaded java-book-code will create a java-book-code directory with multiple sub-
directories. Each sub-directory represents an Eclipse IDE project that you can import into your
Eclipse IDE.
2. Import samples into Eclipse IDE
If you see IMPORT at any point while reading the book, you should import the specified
directory into your Eclipse IDE. The steps to import a project into the Eclipse IDE are described
in section 1-5 of chapter 1.
3. Refer to sample programs
Each program listing specifies the sample project name (using Project label) and the location of
the .java file (using Source location label). If the Project and Source location labels are not
specified, it means that there is no sample program corresponding to the listing. In such cases, it
is recommended that you write and run the program shown in the listing to better understand the
concepts.
4. Try hands-on exercises
If you see Hands-on at any point while reading the book, you should go ahead and make changes
to the program(s) as explained in the text.
5. Take the quiz
Each chapter ends with a few quiz questions whose answers are provided at the end of this book.
You should take the quiz to test your knowledge of the concepts covered in the chapter.
Conventions used in this book
Italics has been used for emphasizing terms
Comic Sans MS has been used for sample programs and keywords
Comic Sans MS has been used in program listings to highlight important parts of the program
NOTE highlights an important point or concept
Feedback and questions
You can post your feedback and questions to the authors in the following Google Groups forum:
https://groups.google.com/forum/#!forum/getting-started-with-java
About the authors
Ashish Sarin is a Sun Certified Enterprise Architect with more than 17 years of experience in
architecting applications. He is the author of Getting started with Spring Framework (self-
published), Spring Roo 1.1 Cookbook (by Packt Publishing) and Portlets in Action (by Manning
Publications)
J Sharma is a freelance Java developer with extensive experience in developing Java applications.
Chapter 1 - Hello World!
1-1 Introduction
Java is an object-oriented programming language that simplifies writing computer programs. Java
was introduced to programmers in 1995 by Sun Microsystems, and is currently maintained by Oracle
Corporation. Java programs are platform-independent, that is, the behavior of Java programs
remains the same irrespective of the platform (which means the hardware and the operating system)
on which you run them. This means that the sample Java programs that accompany this book will
behave the same way if you run them on Windows, Ubuntu, Mac, or any other system.
In this chapter, we’ll first look at how to download and install the following software that you’ll need
for writing and running Java programs:
JDK (Java SE Development Kit) – provides the necessary tools to compile and run Java
programs
Eclipse IDE – an integrated development environment (IDE) that simplifies writing,
compiling, debugging and running Java programs
Once we’ve setup the development environment, we’ll look at a simple Java program that prints
‘ Hello World ! ’ message. We’ll wrap this chapter up by looking at what makes Java programs platform-
independent, and how to import programscontained in java-book-samples ZIP file into Eclipse IDE.
1-2 Setting up the development environment
To setup the development environment, you need to do the following:
Download and install JDK and Eclipse IDE
Configure Eclipse IDE to use the installed JDK
Let’s first look at how to download and install JDK and Eclipse IDE.
Downloading and installing JDK and Eclipse IDE
You can download JDKfrom Oracle’s website by going to the following
URL: http://www.oracle.com/technetwork/java/javase/downloads/index.html . As shown in figure 1-1, click
the Download option under JDK. This will open the web page (refer figure 1-2) that shows JDK
downloads available for different processor types (32- and 64-bit) and operating systems. Accept the
license agreement and click the JDK that is applicable to your system. For instance, if you are using a
64-bit Windows system, download jdk-8u101-windows-x64.exe . You can also view the installation
instructions specific to your system by clicking the Installation Instructions link (refer figure 1-1).

Figure 1-1 Click the Download option to go to the JDK download page

Figure 1-2 Accept the license agreement, and select the JDK applicable for your system
NOTE The name of JDK shown in figures 1-1 and 1-2 is 8u101 , which means JDK’s versionis 8 and
its update number is 101 . By default, Oracle’s website shows the latest JDK update. So, don’t be
surprised if the JDK update number mentioned in this book doesn’t match with latest JDK available
from Oracle’s website.
If you are using Windows, install JDK by double-clicking the downloaded .exe file and following the
installation wizard. A JRE (Java Runtime Environment) is also installed along with JDK. By default,
JDK is installed in C:\Program Files\Java\jdk1.8.0_101 folder, and JRE is installed in C:\Program
Files\Java\jre1.8.0_101 folder. We’ll learn more about JDK and JRE later in this chapter.

To verify that JDK is successfully installed, open Windows command prompt and execute java -version
command. The command prints the version of JDK installed, as shown here:
C:\>java -version
java version "1.8.0_101"
Java(TM) SE Runtime Environment (build 1.8.0_101-b13)
Java HotSpot(TM) Client VM (build 25.101-b13, mixed mode)

Once you have installed JDK, the next step is to download and install Eclipse IDE. You can
download Eclipse IDE installer from the Eclipse website: http://www.eclipse.org/downloads/eclipse-packages/ .
Eclipse IDE Installers are available for different operating systems and processor types, as shown in
the following figure:

Figure 1-3 Choose the installer for your system and download
As shown in the above figure, choose the operating system and the processor type (32- or 64-bit) to
download the Eclipse installer.

If you select Windows operating system and 64-bit processor, you’ll get eclipse-inst-win64.exe file as the
installer. To install Eclipse IDE, double-click the downloaded installer. As Eclipse IDE comes in
many flavors and for many languages, choose ‘ Eclipse IDE for Java Developers ’ from the list of options
(refer figure 1-4) that show up.
You’ll now be asked to specify the installation location of Eclipse IDE:

If the specified folder location doesn’t exist, the installer will automatically create it. We’ve
chosen C:\myide folder as the location of installation.Click ‘ INSTALL ’ to start the installation. After
Eclipse IDE is successfully installed, you’ll see the ‘ LAUNCH ’ button, as shown here:

If you had chosen myide as the installation directory, Eclipse IDE is installed in C:\myide\eclipse folder.
To start Eclipse IDE, click the ‘ LAUNCH ’ button or go to C:\myide\eclipse folder and double-
click eclipse.exe file.
When you start Eclipse IDE, it asks for the workspace location – the location where Eclipse IDE
savesJava programs. The following figure shows that we’ve set C:\java-samples folder as the workspace
location:

After you click OK button, Eclipse IDE’s welcome screen is shown:


After you close the welcome screen, you’ll see different sections of Eclipse IDE (refer figure 1-9).
You must familiarize yourself with Eclipse IDE, as you’ll be using it for writing and running
programs. The Package Explorer tab on the left side of the IDE shows files and directories that form the
Java programs. Any Java project or Java program that you create, will appear in the Package Explorer
tab. The central area is the place where your currently open Java programs are displayed. This is the
area where you’ll be editing your Java programs. The Problems tab at the bottom displays syntax
errors that Eclipse IDE finds in your Java programs. As we work through Java programs in this book,
we’ll look at different features offered by Eclipse IDE that simplify writing programs.

Figure 1-9 Important sections of Eclipse IDE – Package Explorer tab, Program editorarea and Problems tab
Before you can use Eclipse IDE for writing Java programs, you need to tell Eclipse IDE about the
installed JDK.
Configuring Eclipse IDE to use the installed JDK
Figure 1-10 Add the installed JDK to the list of installed JREs
To configure Eclipse IDE to use the JDK that we installed earlier, open Eclipse IDE preferences by
selecting Windows Preferences option from the menu. As shown in figure 1-10, select Java Installed JREs
option from the list of preferences.
Selecting the Installed JREs option displays the list of JREs that are currently configured with Eclipse
IDE. The above figure shows that Eclipse IDE is already configured with theJRE located in C:\Program
Files\Java\jre1.8.0_101 folder. To configure Eclipse IDE with JDK, click the Add buttonand select Standard
JVM from the Add JRE dialog box:

Click Next button to select the directory in which you had installed the JDK:
Once you have selected the JDK installation directory, click the Finish button.
The last step in configuring Eclipse IDE with JDK is to specify that the newly configured JDK must
be used by default by Eclipse IDE:

Figure 1-13 Click OK to save changes in the preference


The above figure shows that jdk1.8.0_101 is checked, and jre1.8.0_101 is unchecked. Now, click OK to save
changes in the preference.
You are now ready to create your first Java program.
1-3 Creating your first Java program
In this section, we’ll look at how to create a simple Java program that prints ‘ Hello World ! ’ when we
run it.
Before you create a Java program, you need to create a Java project in Eclipse IDE that will contain
your Java program.
NOTE Java is a case-sensitive programming language; therefore, ensure that you are using the
correct capitalization while creating the Java project and the Java program.
Creating a Java project
To create a Java project, go to Package Explorer tab and right-click inside it. This will show a popup
menu, as shown in figure 1-14.

Selecting New Java Project option opens the dialog box for creating a new Java project:

Enter myproject as the name of the project, ensure that Use default location option is checked and Use default
JRE option is selected. Click the Finish button to create myproject Java project.This will create a folder
named myproject in the Project Explorer tab.
We are now ready to create Java programs in the newly created myproject .
Creating the ‘Hello World !’ program
Select myproject folder in the Package Explorer tab and right-click to view the popup menu. Select
New Class , as shown here:

Figure 1-16 New Class is used to create a Java class where you write your program
New Class option shows the dialog box for creating a new Java class. A Java class is the file in
which you write your Java program. The following figure shows the dialog box for creating a new
Java class:

The default value of Source folder and Package fields is myproject , which is the name of the Java project.
Enter HelloWorld as the value of Name field and click Finish . This will create:
a folder (referred to as a Java package) named myproject , and
afile named HelloWorld.java inside myproject package
The following figure shows what is a Java project, package, class and program:
Figure 1-18 Java project, package, class and program in the context of myproject
HelloWorld.javafile represents the HelloWorld Java class. Creating a Java class means you are creating a
file with .java extension. You should note that Java programs are written inside .java files.
If you open the HelloWorld.java file by double-clicking it, you’ll see that it already contains the following
text:
Listing 1-1 HelloWorld.java file
1 package myproject;
2
3 public class HelloWorld {
4
5 }

The above listing shows the bare minimum details that a Java class must contain. The
actual HelloWorld.java file doesn’t have line numbers but we’ve specified them in the above listing.
We’ve mentioned line numbers so that it is easy for us to discuss a particular line in a program. We’ll
be following this practice throughout this book.
Let’s look at each of the lines in the HelloWorld.java file.
Line #1 – package myproject;
This line specifies that the HelloWorld class is inside the Java package named myproject .As shown in
figure 1-18, HelloWorld.java file doesreside inside myproject package.
Line #2 – blank lines have no significance in Java programs. They only help with readability of the
program
Lines #3, #4 and #5 – defines the bodyof the HelloWorld class. You write your program logic inside
opening '{' and closing '}' braces.
The .java file must contain the definition of the Java class in the following format:
public class <class-name>
here, <class-name> is the name of the Java class
The <class-name> mustbe same as the name of the .java file. For this reason, when we
create HelloWorld class using Eclipse IDE, it creates a HelloWorld.java file and adds HelloWorld class
definition inside it.
As we want to write a Java program that prints ‘ Hello World ! ’, modify the HelloWorld.java file as shown
here:
Listing 1-2Modified HelloWorld.java file
1 package myproject;
2
3 public class HelloWorld {
4 public static void main(String[] args) {
5 System.out.println("Hello World !");
6 }
7 }

In the above listing, we’ve added a main method that prints ‘ Hello World ! ’ message. A Java method
contains a sequence of program instructions (enclosed within opening '{' and closing '}' braces) that
are executed when that method is called. In the above listing, the main method contains only one
program instruction System.out.println("Hello World !") thatprints the ‘ Hello World ! ’ message. After making
changes to HelloWord.java file, save it by selecting File Save option from the menu baror by using Ctrl + S
key combination.
NOTE The contentsof a .java file are referred to as source code or simply code.
To run the main method of HelloWorld class, do the following:
open the HelloWorld.java file in the editor
right-click inside the editor, and
select Run As Java Application

Figure 1-19 shows that execution of the main method of HelloWorld class prints ‘ Hello World ! ’message in
the Console tab.
NOTE A Java program is also referred to as a Java application. We’ll use the
terms ' program ' and ' application ' interchangeably in this book.

Figure 1-19 Console tab shows the ‘ Hello World ! ’ message printed by System.out.println
One of the advantages of using Eclipse IDE is that it’ll highlight portions of the code that don’t match
the Java programming language rules. Figure 1-20 shows a scenario in which System.out.println was
incorrectly typed as System.Out.println .
Figure 1-20 Errors in the Java class are highlighted by the Eclipse IDE editorand also displayed in
the Problems tab
Figure 1-20 shows that the Eclipse IDE underlines Out part of System.Out.println in redand also shows an
error message in the Problems tab to indicate that there is a problem with the HelloWorld class.
In this section, we created a HelloWorld class, myproject project and myproject package. Let’s look at how
these Java artifacts are represented in the file system.
Java project structure
If you go to C:\java-samples directory (the workspace that we specified for use by Eclipse IDE), you’ll
see the following directories and files:

Figure 1-21 The directory structure of myproject Java project


The above figure shows that a folder is created corresponding to both Java project and Java package.
HelloWorld.java file is created corresponding to the HelloWorld class that we created via Eclipse IDE.
HelloWorld.class file is created by Eclipse when it compilesthe HelloWorld.java file.When you make changes
to a .java file and save it, Eclipse IDE uses the Java compilercontained in the configured JDK to
compile the .java file.
NOTE Java compiler is responsible for checking that the program instructions written in .java files
are in accordance with the programming language rules. Java compiler is also responsible for
convertinga .java file into Java bytecode - a platform-independent format.
Let’s look at what makes Java a platform-independent programming language.
1-4 What makes Java platform-independent?
We saw in the previous section that Java programs are written in .java files. As shown in figure 1-22,
program instructions contained in a .java file are converted into Java bytecode by the Java compiler.
The Java compiler takes .java file as an input and creates a .class file that contains the bytecode. You
can think of bytecode as an intermediatelanguage between program instructions written in .java file
and the machine language instructions understood by the underlying platform.

Figure 1-22 Java compiler converts program instructions written in .java file to Java bytecode
Java bytecode is platform-independent. This means, if you compile the HelloWorld.java file (refer listing
1-2) on Windows and on Linux, the generated .class files will be identical. The bytecode is
understood by the Java Virtual Machine (JVM). JVM is part of Java Runtime Environment (JRE) that
is responsible for running Java programs.
When you run a Java program, the following sequence of actions are performed by the JVM:
reads the bytecode contained in .class file
translates bytecode into machine language instructions understood by the underlying platform
executes the translated machine language instructions
The following figure summarizes the role played by JVM in running Java programs:

Figure 1-23 JVM converts bytecode into machine language instructions


As JVM is responsible for taking care of platform-specific requirements, you don’t need to worry
about the platform on which you are writing the Java program or the platform on which you are
running the compiled Java program. This is what makes Java a platform-independent programming
language.
NOTEWhen you run a Java program using Run As Java Application option, the Eclipse IDE uses the
JRE contained in the configured JDK to run the Java program.
JDK and JRE are at the heart of compiling and running Java programs. Let’s take a closer look at
them.
JDK and JRE
We saw earlier that JDK was installed in C:\Program Files\Java\jdk1.8.0_101 folder. jdk1.8.0_101 folder’s bin
directory contains executables that are used for compiling and running Java programs. The following
table describes some of the executables contained in the installed JDK’s bin directory:
Table 1-1– Development tools contained in JDK’s bin directory
Executable Description
javac compiles a .java file into a .class file that contains the
Java bytecode
java runs the public static void main(String args[]) method contained
in the compiled .class file
jar packages .class files into a JAR (Java Archive) file.
JAR is a standard file format in which Java
applications are packaged.
javadoc creates HTML documentation from comments
contained in .java files
NOTE When we save a .java file in Eclipse IDE, itinternally uses javac to compile the .java file into
a .class file. And, when we choose Run As Java Application option, Eclipse IDE uses java to run the
class’s main method. The java executable in turn uses the JVM to execute the main method.
The jdk1.8.0_101 folder’s contains a jre folder that contains the Java Runtime Environment (JRE). The
JRE contains the JVM (Java Virtual Machine) for translating the Java bytecode (contained in .class
files) to the underlying platform and executing them.
We saw earlier that JRE is also installed in C:\Program Files\Java\jre1.8.0_101 folder.The JRE contained
inside jdk1.8.0_101 folder is referred to as privateJRE, and the JRE installed in jre1.8.0_101 folder is
referred to as public JRE. The private JRE is only available to the JDK, and public JRE is meant to
be used by other applications (like, web browser) installed in the system for running compiled Java
programs.
NOTE As we configured Eclipse IDE to uses JDK, the Eclipse IDE uses the private JRE to run Java
programs.
Let’s now look at how to import an existing project into Eclipse IDE.
1-5 Importing projects into Eclipse IDE
The java-book-code ZIP file that accompanies this book contains Eclipse IDE projects that you can
directly import into your Eclipse IDE. If you unzip the java-book-code , you’ll see that it contains folders
like myproject , chapter02 , and so on. Each folder represents an Eclipse project that you can import into
your Eclipse IDE.
To import a project, select File Import option in the Eclipse IDE:

As we want to import existing Eclipse IDE projects, select the ‘ Existing Projects into Workspace ’ option
from the dialog box and click ‘ Next > ’ button:

You’ll now be asked to select the folder that contains one or more Eclipse projects:
Click the Browse button and select the project subfolder inside java-book-code that you want to import into
your Eclipse IDE. For instance, if you want to import chapter02 project, then select the chapter02 folder
of java-book-code .Once you have selected the project folder, click the Finish button to import the project
into Eclipse IDE.
NOTEYou can import all the projects inside java-book-code folder by selecting the java-book-code folder
itself.
QUIZ
1-1 Which of the following statements are true?
a) Java programs are written in files with .java extension
b) Eclipse IDE simplifies writing and running Java programs
c) You need JDK for ensuring that Java programs are correctly written
d) Java is a platform-dependent programming language
1-2 Which of the following statements are true?
a) JDK contains JRE, and JRE contains JVM
b) JDK has a private JRE that is not available to other programs
c) You can run Java programs without using JDK
d) JRE is used for compiling .java files to .class files
e) Java bytecode is not compatible across different platforms
f) Java bytecode and JVM provide Java’s platform-independence capability
g) Instead of using Eclipse IDE, you can directly use javac and java executables in JDK’s bin
directory to compile and run Java programs
1-6 Summary
In this chapter, we looked at how to set up JDK and Eclipse IDE, and how to write and run a simple
Java program that prints ‘ Hello World ! ’. In the next chapter, we’ll look at the concept of variables,
data types and operators in Java.
Chapter 2 – Variables, data types and operators
2-1 Introduction
Variables, data types and operators are at the heart of a programming language. A variable stores
information that is used in the program, and the type of the information it stores is referred to as its
data type (or simply ‘type’). The operators perform operations (like, subtraction, addition, and so
on) on variables. In Java, data types are of two types: primitive types and reference types. Primitive
types are covered in this chapter, and reference types are covered in chapter 4.
In this chapter, we’ll look at:
defining primitive type variables,
using Java operators to perform operations on variables, and
statements and expressions
Let’s first begin by looking at how variables and data types are used in Java programs.
2-2 Variables and data types
A variable is a named data store that stores primitive values (or objects). The syntax for defining a
variable in Java is:
<variable-type> <variable-name>;
where, <variable-type> specifies the type of the variable, <variable-name> specifies the
name of the variable
A variable name mustbegin with underscore ‘ _ ’, dollar sign ‘ $ ’ or a letter. For better readability, it
is recommended that you don’t define variable names beginning with‘ _ ’ and ‘ $ ’, and use camel-case
to bring out the meaning of a variable. For instance, instead of naming a variable as isworkdone , nameit
as isWorkDone . The name of a variable must not be a Java keyword. As new , final , static , class , and so on,
are keywords (or reserved words) in Java, you must not define a variable with these names.
NOTE As Java is a case-sensitive programming language, variablesnamed isWorkDone and isworkdone
are considered as two different variables in the program.
The following exampleshows a Person class that defines a variable named age of type int :
Listing 2-1 Defining a variable
1 public class Person {
2 public static void main(String args[]) {
3 int age;
4 }
5 }

In the above example, line #3 defines a variable named age of type int . You should note that all
programming instructions (like line #3) in Java end with a semi-colon. int is a primitive type (also
referred to as a simple type) that represents an integer value, like 1, 2, 1001, 12292, and so on.
In the above example, we’ve defined the age variable but not assigned it any value. You assign a
value to a variable by using the assignment operator (represented by = symbol), as shown in the
following example:
Listing 2-2 Assigning value to a variable
1 public class Person {
2 public static void main(String args[]) {
3 int age = 20;
4 System.out.println(age);
5 }
6 }

In the above example, the value of age variable is set to 20 .As shown above, you can print the value
of age variable by using System.out.println .
NOTE The process of setting value of a variable for the first time is referred to as initialization. In
listing 2-2, the age variable was initializedto value 20 on line #3.
Let’s look at the different primitive types defined by Java.
Primitive types
Java defines 8 primitive types, as described in the following table:
Table 2-1 – Primitive types
Primitive What does it represents? Example
type
byte an integer numberranging byte temp = -27;
from +127 to -128
short an integer number ranging from - short length = 100;
215 to 215-1
int an integer numberranging from - int distance = 10000;
231 to 231-1
long an integer numberranging from - long id =
9223372036854775807L;
263 to 263-1
float a floating-point number ranging float mileage = 1.123456F;
from
-3.40282347 x 1038F t0
+3.40282347 x 1038F
double a floating-point number ranging double particleDistance =
1.1234567890123;
from
-1.79769313486231570 x 10308
to +1.79769313486231570 x
10308
char a single Unicode character char alphabet = ‘a’;
boolean true or false boolean isWorkDone = false;

As the above table suggests, you can categorize primitive types into integer, floating-point, character
and boolean. An integer type represents a whole number, a floating-point type represents a decimal
number, a character type represents a character, and a boolean type represents the value true or false .
IMPORTIt is recommended that you import the chapter02 project into your Eclipse IDE. Refer section
1-5 of chapter 1 for the steps required for importing a project into Eclipse IDE.
Literals
A literal refers to a fixed (or constant) value that you assign to a variable.Consider the
following Variables class of chapter02 project that shows the use of literals:
Listing 2-3 Variables and literals
Project: chapter02
Source location: src\chapter02\Variables.java
1 package chapter02;
2
3 public class Variables {
4 public static void main(String args[]) {
5 byte temp = -27;
6 int age = 20;
7 short length = 100;
8 int distance = 10000;
9 long id = 9223372036854775807L;
10 float mileage = 1.123456F;
11 double particleDistance = 1.1234567890123456;
12 char alphabet = 'a';
13 boolean isWorkDone = false;
14
15 System.out.println(temp);
16 System.out.println(age);
17 .....
17 }
18 }

In the above listing, fixed values are assigned to all the variables.For instance, -27 is assigned
to temp , 20 is assigned to age , 1.1234567890123456 is assigned to particleDistance , and so on. These fixed (or
constant) values are examples of literals.
Some of the important things to notice in the above listing:
- If the variable type is char , the value is enclosed in single quotes. For instance,
value ‘a’ is assigned to alphabet variable (refer line #12).
- If the variable type is boolean , it can only take the value true or false . For instance,
value false is assigned to isWorkDone variable (refer line #13)
- As float and double type variables representfloating-point numbers, mileage and particleDistance
variables are assigned values containing a decimal point. By default, any floating-point
literalis considered to be of type double by Java. You can add suffix F to specify that a
floating-point literal is of type float . As the mileage variable is of type float , F suffix is added
to 1.123456 (refer line #10) to specify that it is a float type literal.
- By default, an integer literalis considered to be of type int . You can add suffix L to
specify that an integer literal is of type long . As the id variable is of type long , suffix L is added
to the value 9223372036854775807 to specify that it is a long type literal.
Let’s now look at why adding F suffix to a floating-point literaland L suffix to an integer literal is
sometimes required.
F (or f) and L(or l) suffixes
To understand purpose of F (or f ) and L (or l ) suffixes, you first need to understand the rules that
apply when assigning values to primitive types.
In table 2-1, we saw the range of values different primitive types can accept. The range depends on
the number of bytes (that is, computer memory) used by the primitive type for storing values. The
following table specifies the number of bytes used by different primitive types for storing values:
Table 2-2 – Storage size of primitive types
Primitive Storage size (in
type bytes)
byte 1
short 2
int
4
long 8
float 4
double 8
char 2
boolean not precisely
defined
So, if you define variable named x of type int , then 4 bytes of memory is allocated by Java for storing
the value assignedto x . As the storage size of a primitive type is fixed, you can only store a value that
fits into that size. So, what happens if we try to store a value which is outside the acceptable range of
a primitive type? Let’s look at this by doing some hands-on activity.
Hands-on Assign a value outside a primitive type’s acceptable range
In listing 2-3, we saw that Variables class defines temp , age , alphabet , and so on, variables of different
primitive types. The values assigned to these variables are then printed using System.out.println program
instruction.
As shown here, open the Variables class of chapter02 project in your Eclipse IDE and change the value
of temp variable(of type byte ) from -27 to -129 :

Figure 2-1 Eclipse shows an error if you assign a value of -129 to temp variable
After you’ve set the value of temp variable to -129 and saved the Variables.java file, you’ll notice that
Eclipse shows an error on the line that defines the temp variable. If you take the mouse over red x
symbol, it’ll show you the following error message ‘Type mismatch: cannot convert from int to byte ’.
This error is reported because the value -129 is outside the acceptable limit of 127 to -128 for the byte
type (refer table 2-1).
Integer literals can be used toset values of short , byte , int and long type variables. Eclipse doesn’t
complain if the value being assigned to the temp variable is within the range of 127 to -128 . If you go
beyond the acceptable limit of the byte type, Java treats the integer value (which is -129 in our
example) to be of type int . As the storage size of byte type is 1 and that of int type is 4 , assigning the
value -129 to temp variable will result in loss of information. For this reason, Eclipse complains that
this assignment is incorrect and you must notassign the value -129 to the temp variable.
NOTE The errors reported by Eclipse IDE are referred to as compile-time errors (also, referred to
as compilation errors). A compile-time error is reported when a Java compiler compiles a Java
program. When you make changes to a .java file and save, Eclipse IDE automatically compiles the .java
file using the configured JDK. These compile-timeerrors are also displayed in the Problems tab.
Remember that you can’t run a Java program until it is compiled successfully.
If the compiler complains that conversion from one type of value to another type is not allowed, you
can explicitly tell the compiler that the type conversion is fine even if it results in loss of information.
The syntax for explicitly specifying type conversion is:
(<type>) <value>
here, <value> is the value that you want to convert, and <type> is the primitive type to
which you want to convert the value to
In the following example, specifying (byte) tells the compiler that the value -129 is converted
into byte before it is assigned to the temp variable:
byte temp = (byte) -129;

As we are explicitly telling the compiler that the value -129 is converted to byte typebefore it is
assigned to the temp variable, the compiler no longer complainsabout assigning -129 to temp .
NOTE You should note that the errors reported by Java compiler tell you only about possible issues
with your program that the compiler finds by simply analyzing your program. You can change your
program to make compiler happy, but that doesn’t mean your program is correct.
The above example represents a conversion scenario in which a value of large-sized primitive type
( int of 4 bytes) is converted into a small-sized primitive type ( byte of 1 byte). This conversion is
referred to as narrowing conversion. You should note that when narrowing conversion is performed,
data may be lost.If you run the main method of Variables class by selecting Run As Java Application ,you’ll
see that the value of temp variable is printed as 127 instead of -129 . This is because information loss
occurs when we assign -129 (a value outside byte type’s limit) to the temp variable.
L suffixfor long type values
As mentioned earlier, an integer literal is considered to be of type int .You can use an integer literal to
set values of byte , short , int and long type variables.While setting the value of a long type variable, you
may come across a situation in which the value of the integer literal is beyond the acceptable limits of
the int type. In such cases, you need to explicitly tell the compiler that the integer literal is of
type long using L suffix.For instance, the value of id variable in Variables class is specified
as 9223372036854775807L because the value 9223372036854775807 is outside the acceptable limit of the int type
(refer table 2-1). If you remove the L suffix from the value, you’ll see that the compiler shows an
error in your program.
As shown in figure 2-2, Eclipse displays the error message ‘The literal 9223372036854775807 of type int is
out of range’. Table 2-1 showed that the maximum value that an int type can store is 231-1 (that
is, 2417483647 ) which is less than 9223372036854775807 .As you can’t define an int type literal with
value 9223372036854775807 , you need to add L suffix to the value 9223372036854775807 .
Figure 2-2 Eclipse shows an error if you remove L suffix from 9223372036854775807 .

F (or f ) suffix for float type values


By default, a floating-point literal is considered to be of type double . In Variables class,
the mileage variable (of type float )is assigned 1.123456F as value. If you remove F suffix from 1.123456F ,
compiler will complain ‘Type mismatch: cannot convert from double to float ’. If you refer to table 2-2,
you’ll notice that the size of double is 8 bytes and that of float is 4 bytes. As converting a double type literal
to a float type will result in loss of information, you must tell the compiler (by using the F suffix) that a
floating-point value is of float type.
Narrowing and widening conversions
When the value of a large-sized primitive type (like long ) is assigned to a small-sized primitive
type(like int ), it is referred to as a narrowing conversion. As explained in the previous section, a
narrowing conversion is explicitly performed, and it might result in data loss. When the value of a
small-sized primitive type(like int ) is assigned to a type of large-sized type (like long ), it is referred to
as a widening conversion. Unlike narrowing conversion, a widening conversion is performed
automatically (that is, the compiler will not complain when it sees a widening conversion being
performed).
Listing 2-4 shows the Conversions class of chapter02 project that does the following:
defines variables of different primitive types and assigns them values
performs widening and narrowing conversions using the defined variables
prints the value of variables affected by narrowing and widening conversions
NOTE You assign value of a variable to another variable by using the = assignment operator. The
value of the variable on the right sideof = is assigned to the variable on the left side.
Listing 2-4 Narrowing and widening conversions
Project: chapter02
Source location: src\chapter02\Conversions.java
1 package chapter02;
2
3 public class Conversions {
4 public static void main(String args[]) {
5 byte temp = -127;
6 int age = 20;
7 char alphabet = 'a';
8 short length = 100;
9 long id = 9223372036854775807L;
10 ...
11 age = temp; // -- value of temp is assigned to age
12 System.out.println("age = temp: " + age);
13
14 age = length; // --value of length is assigned to age
15 System.out.println("age = length: " + age);
16 ...
17 }
18 }

In the above listing, thevalue of temp variable is assigned to age (line #11) and then the new value
of age variable is printed (line #12). Similarly, the value of length variable is assigned to age (line
#14) and then the new value of age is printed (line #15).
On lines #11 and #14, we’ve used // to specify single-line comments in the program. The use of
comments helps you document the working of your program. Anything that comes after the // is
ignored by the Java compiler. If you want to write multi-line commentsthen enclose your comments
between /* and */ . As shown in the following listing, Conversions.java uses multi-line comment to specify
what the program does:
Listing 2-5 Multi-line comments
Project: chapter02
Source location: src\chapter02\Conversions.java
1 package chapter02;
2 /*
3 This program shows examples of narrowing and widening conversions.
4 The values of the affected variables are printed after each conversion.
5 */
6 public class Conversions {
7 ...
8 }
In listing 2-4, System.out.println prints a string (specified in double quotes) along with the value of
the age variable. This approach simplifies understanding the output of the program. The following
figure shows how System.out.println prints a string along with a variable’s value.

The + sign (referred to as concatenation operator) specifies that the string "age = temp: " is
concatenated with the age variable’s value. If you run the main method of Conversions class, you’ll see
the following output:
age = temp: -127
age = length: 100
...

From the above output it is easy to determine that the output age = temp: -127 corresponds to line #12
and age = length: 100 corresponds to line #15 of Conversions.java file (refer listing 2-4).
Let’s look at some examples of widening conversions in Conversions class.
Examples of widening conversions
Example 1: byte to int
byte temp = -127;
int age = 20;
age = temp; // -- value of temp is assigned to age

Example 2: short to int


short length = 100;
int age = 20;
age = length; // --value of length is assigned to age

Example 3: char to int


char alphabet = 'a';
int age = 20;
age = alphabet; // --value of alphabet is assigned to age

A char type in Java stores a single Unicode character. Unicode is an industry standard that
uniquely represents characters used in human languages. A char type internally stores Unicode
characters as an integer value ranging from 0 to 65,535 . This range is enough to store most of
the characters found in human languages. As the character ‘ a ’ is internally stored as integer
value 97 , the age = alphabet assignment sets the value of age variable to 97 . The age = alphabet
assignment is an example of widening conversion because we assign alphabet (the char type)
that uses 2bytes for storage to age (the int type) that uses 4 bytes for storage.
Example 4: int to float
int age = 20;
float mileage = 1.123456F;
mileage = age; // --value of age is assigned to mileage

Even though float and int have the same size (4 bytes), conversion from int to float is a widening
conversion. You should note thatwhen int is converted to float , you may lose some of the less
significant digits (that is, digits that are towards the end). The reason for loss is related to
the way floating-point numbers are stored. In the case of float type, only 24 bits are used for
storing the actual numberand 8 bits for exponent. For this reason, loss of precisionmay occur
when conversion is performed from a large int type to float . For instance, if you convert
integer value 1073741824 (which is 230 ) to float , the value of float comesto 1.07374182 x 109 . The
information about the last digit '4' is lost in the conversion.
Similarly, when you convert a significantly large long number to double (which uses 53 bits for
storing the number and 11 bits for exponent), some of the less significant digits are lost.
Example 5: float to double
double particleDistance = 1.1234567890123456;
float mileage = 1.123456F;
particleDistance = mileage; // --value of mileage is assigned to particleDistance

Let’s now look at some examples of narrowing conversionsused in Conversions class.


Examples of narrowing conversions
Example 1: long to int
int age = 20;
long id = 9223372036854775807L;
age = (int) id; // --value of id is assigned to age
As the value of long type is assigned to int , information may be lost. If you run the main method
of Conversions class, you’ll see the value of age variable is printed as -1 (and not
9223372036854775807 ).

Example 2: float to int


int age = 20;
float mileage = 1.123456F;
age = (int) mileage; // --value of mileage is assigned to age
As the value of float type is assigned to int , information may be lost. If you run the main method
of Conversions class, you’ll see the value of age variable is printed as 1 (and not 1.123456 ). As
the age variable is of type int ,the value 1.123456 is rounded-off to the integer value 1 .
The following figure shows that conversions from left to right are widening conversions and right to
left are narrowing conversions:

Figure 2-4 Narrowing and widening conversions in primitive types


The above figure shows that even though int and float are of the same size, conversion from int to float is a
widening conversion. Similarly, long to double is a widening conversion.Also, notice that conversion
from char to int is a widening conversion, but conversion from char to short or byte is a narrowing
conversion.
Type conversion and compatibility
You should note that variables involved in type conversion (narrowing or widening) must be
compatible. For instance, you can’t assign a boolean type to any other primitive type and vice
versa.This is because boolean is a non-numeric type and the other primitive types are of numeric type.
Even if you explicitly tell the compiler that you want to do the conversion, the compiler reports error.
For instance, the following piece of code will not compile:
1 int distance = 100;
2 boolean isWorkDone = true;
3 distance = (boolean)isWorkDone;

The statement on line #3 will not compile because it is not possible to convert a boolean type into any
other primitive type.A boolean type can only be assigned to another boolean type.
Let’s now look at Java operators that you can use to perform operations on variables.
2-3 Operators
Java defines operators that you can use in your programs to perform operations involving variables
and literals. The variables (or literals) on which an operator works are referred to as its operands.
The operators in Java are classified into following categories:
arithmetic - defines operators for performing mathematical operations, like addition,
multiplication, division, and so on
relational - defines operators for performing relational operations, like equality, greater
than, less than, and so on
conditional - defines operators for performing conditional operations, like and, or, and so
on.
assignment - defines operators for assigning values to variables. We’ve already seen usage
of simple assignment operatorrepresented by = .
bitwise - defines operators for performing operations on the individual bits of primitive types
that store integer values (like short , byte , int , long and char ).
NOTE An operator that works on two operands is referred to as a binary operator, and an operator
that works on a single operand is referred to as a unary operator.
Before we delve deeper into operators, let’s look at the concepts of expressions and statements in
Java.
Java expressions and statements
Java expressions are made up of variables, literals, method calls (explained in chapter 4) and
operators. An expression typically evaluates to a value and has a type. For instance, following are
some of the examples of expressions (the expressions arehighlighted in bold ):
1 int distance1 = 100;
2 distance2 = distance1;
3 x = y + 1;

On line #1, the literal 100 is assigned to distance1 . As distance1 is of type int , the expression distance1 =
100 evaluates to 100 and is of type int .

On line #2, distance2 = distance1 expression evaluates to the value of distance2 variable and has the same
type as distance2 .
You should note that an expression itself may consist of one or more sub-expressions to form a
compound expression. The expression on line #3 is an example of compoundexpression. The sub-
expression y + 1 is first evaluated and its value is then assigned to x .The expression x = y + 1 evaluates
to the value of y + 1 and has the same type as x .
A Java statement is a unit of execution in your program that terminates with a semicolon. Unlike
expressions, statements never return values. A statement represents an action in the program. For
instance, int distance1 = 100; represents a statement that declares a variable named distance1 and initializes
it withvalue 100 . The distance2 = distance1; statement assigns value of distance1 variable to distance2 variable.
And, x = y + 1; represents a statement that assigns the result of expression y + 1 to x .
You should note that statements are executed from top to bottom in the order they appear in the
program. You can change the order in which the statements are executed by using control flow
statements (explained in chapter 3).
Let’s now look at each of the categories of operators in detail.
Arithmetic operators
The following table specifies various arithmetic operators available in Java and the purpose they
serve:
Table 2-3 – Arithmetic operators
Operator Type Description Example
+ Binary adds two operands 10 + 20

- Binary subtracts right operand from left operand 10 – 20

* Binary multiplies left operand with right operand 10 * 20

/ Binary divides left operand with right operand 10 / 20

% Binary returns the remainder from dividing left operand with 10 % 20


right operand
++ Unary increments the value of the operand by 1 ++10

-- Unary decrements the value of the operand by 1 --20

NOTE As arithmetic operators are applicable only to numeric primitive types, you can’t use them
for boolean types.
Thefollowing listing shows the ArithmeticOperators class of chapter02 project that uses the arithmetic
operators shown in the above table:
Listing 2-6 Arithmetic operators
Project: chapter02
Source location: src\chapter02\ArithmeticOperators.java
1 package chapter02;
2
3 public class ArithmeticOperators {
4 public static void main(String args[]) {
5 int a = 10;
6 int b = 20;
7
8 int addition = a + b;
9 int subtraction = a - b;
10 int multiplication = a * b;
11 int division = a / b;
12 int remainder = a % b;
13 int increment = ++a;
14 int decrement = --b;
15
16 System.out.println("addition: " + addition);
17 System.out.println("subtraction: " + subtraction);
18 System.out.println("multiplication: " + multiplication);
19 System.out.println("division: " + division);
20 System.out.println("remainder: " + remainder);
21 System.out.println("increment: " + increment);
22 System.out.println("decrement: " + decrement);
23 }
24 }

NOTEWe saw earlier that + operator is used by System.out.println to concatenate string and a variable’s
value. The + operator is also used as an arithmetic operator if both its operands are of numeric type.
This is referred to as operator overloading, which means that the same operator behaves differently
for different types of operands.
In the above listing, the result of arithmetic operation is stored in addition , subtraction , and so on,
variables. If you run the main method of ArithmeticOperators class, you’ll get the following output:
addition: 30
subtraction: -10
multiplication: 200
division: 0
remainder: 10
increment: 11
decrement: 19

Notice that ++ operator (line #13) resulted in incrementing the value of a by 1 and -- operator (line
#14) resulted in decrementing the value of b by 1 . The above output shows that the right side of the
assignment operator = is evaluated first, and the result is then assigned to the variable on the left side.
NOTEThe assignment operator = is the only binary operator that evaluates from right to left. This
means, expression on the right side of = is evaluated first, and then the result of expression is
assigned to the variable on the left side of = . All other binary operators are evaluated from left to
right.
You can use ++ and -- operators before or after the operand, and they have different implications.
Consider the following piece of codethat uses ++ operator before and after an operand:
Listing 2-7 Using ++ operator before and after the operand
1 int a = 10;
2 int b = 20;
3
4 int y = a++;
5 int z = ++b;
6
7 System.out.println("value of a : " + a);
8 System.out.println("value of y : " + y);
9 System.out.println("value of z : " + z);

On line #4, the ++ operator is used afterthe variable a and the result is assigned to y . And, on line #5,
the ++ operator is used beforethe variable b and the result is assigned to z .
If the above code is executed, it’ll show the following output:
value of a : 11
value of y : 10
value of z : 21

The value of a is printed as 11 , which is the incremented value of a . But the value of y is printed
as 10 , which means that the original value (and notthe incremented value) of a was assigned to y .The
value of z is printed as 21 , which means that the incremented value of b wasassigned to z .
This shows that if you are using ++ (or -- ) operator after the operand, the operand itself is
incremented (or decremented) but the original value of operand is assigned to the variable on the left
side of the = operator. Onthe other hand, if you are using ++ (or -- ) operator before the operand, the
operand is incremented (or decremented) and the incremented (or decremented) value of operand is
assigned to the variable on the left side of the = operator.
NOTE You should note that you can declare multiple variables on the same line as long as they are of
the sametype. For instance, you can declare and set initial values of a and b variables (of type int ) on
the same line as shown here: int a = 10, b = 20;
Relational operators
Relational operators are used for comparing values of operands. The result of comparison is a boolean
type. The following table describes relational operators available in Java:
Table 2-4 – Relational operators
Operator Description Example
== checks if the operands have the same value 10 == 10

!= checks if the operands have unequal values 10 != 10

> checks if the left operand’s value is greater than right 10 > 20 The
operand’s value following
< 10 < 20
listing
checks if the left operand’s value is less than right
shows
operand’s value
>= checks if the left operand’s value is greater than or 10 >= 20
equal to right operand’s value
<= checks if the left operand’s value is less than or 10 <= 20
equal to right operand’s value
the RelationalOperators class of chapter02 project that uses relational operators:
Listing 2-8 Relational operators
Project: chapter02
Source location: src\chapter02\RelationalOperators.java
1 package chapter02;
2
3 public class RelationalOperators {
4 public static void main(String args[]) {
5 int a = 10;
6 int b = 20;
7 boolean isEqualTo = a == b;
8 boolean isNotEqualTo = a != b;
9 boolean isGreaterThan = a > b;
10 boolean isLessThan = a < b;
11 boolean isGreaterThanEqualTo = a >= b;
12 boolean isLessThanEqualTo = a <= b;
13
14 System.out.println("isEqualTo " + isEqualTo);
15 System.out.println("isNotEqualTo " + isNotEqualTo);
16 System.out.println("isGreaterThan " + isGreaterThan);
17 System.out.println("isLessThan " + isLessThan);
18 System.out.println("isGreaterThanEqualTo " + isGreaterThanEqualTo);
19 System.out.println("isLessThanEqualTo " + isLessThanEqualTo);
20 }
21 }

In the above listing, relational operators have been used to compare a and b variables.If you run
the main method of RelationalOperators class, you’ll see the following output:
isEqualTo false
isNotEqualTo true
isGreaterThan false
isLessThan true
isGreaterThanEqualTo false
isLessThanEqualTo true

NOTEThe relational operator for checking if two operands have the same value is == and not = .
The = operator is the assignment operator that is used for assigning the value of the variable(or
expression) on the right of = to the variable on the left side of = .
Conditional operators
Conditional operators check conditions specified by operands.The operands are of boolean type, and
the result is also of a boolean type. The following table describes conditional operators available in
Java:
Table 2-5 – Conditional operators
Operator Description Example The
&& The AND operator that returns true if conditions (10 == 20) && (10 != 20)
specified by both the operands are true
|| The OR operator that returns true if one of the (10 == 20) || (10 != 20)
conditionsis true
! The NOT unaryoperator that returns true if !(10 != 20)
thecondition is false , andreturns false if the
condition is true
following example listingshows the ConditionalOperators class of chapter02 project that uses conditional
operators:
Listing 2-9 Conditional operators
Project: chapter02
Source location: src\chapter02\ConditionalOperators.java
1 package chapter02;
2
3 public class ConditionalOperators {
4 public static void main(String args[]) {
5 int a = 10;
6 int b = 20;
7
8 boolean and = (a == b) && (a != b);
9 boolean or = (a == b) || (a != b);
10 boolean not = !(a != b);
11
12 System.out.println("and : " + and);
13 System.out.println("or : " + or);
14 System.out.println("not : " + not);
15 }
16 }

In the above listing, == and != relational operators are used with variables a and b to generate boolean
type operands for the conditional operators. The following figure shows how the expression on line
#8 is evaluated:

The numbered balls in the above figure specify the order in which different parts of expression boolean
and = (a == b) &&(a != b) are evaluated. We mentioned earlier that except the = assignment operator, the
operands of an operator are evaluated from left to right. As the evaluation order is left to right
for && operator, the expression (a == b) is evaluated first, followed by evaluation of (a != b) expression.
The && operator is then applied to the return values ( true or false ) of both the expressions to
determine the result. If the left operand returns false , there is no point in evaluating the right operand
because the result will always be false . For this reason, the right operand of && is evaluated only if
the left operand returns true . As the value of a is 10 and b is 20 , the expression (a == b) returns false . For
this reason,the right side expression (a != b) is not evaluated.
As in the case of && operator, the right operand of || is notevaluated if the left operand returns true . If
the left operandof || operatorreturns true , there is no point in evaluating the right operand; the result
will always be true .
As the right operandsof && and || operators may not be evaluated, these operators are referred to as
‘short-circuit’ operators (that is, operators that don’t require evaluation of all its operands).
NOTE In listing 2-9, parentheses ( ) were used to group operands of && and || operators. If multiple
operators (like == , != , && , || , and so on) are present in an expression, you can use parentheses to
divide the expression into smaller sub-expressions that are evaluated independently of each other.
Assignment operators
Java defines a simpleassignment operator = and a couple of compound assignment operators. A
compound assignment operator combines an assignment operator with an arithmetic (or bitwise)
operator to perform both assignment and arithmetic (or bitwise) operation. This expression shows
usage of += compound assignment operator:
a += 9;

In the above expression, += operator adds 9 to a and assigns the resultback to a . The following
expression is same as the above expression:
a = a + 9;

The following table describes some of the compound assignment operators defined by Java:
Table 2-6 – Compound assignment operators
Operator Description Example
+= adds the right operand to the left, and then a += 10;
assigns the result to the left operand
-= subtracts the right operand from the left, and then a -= 10;
assigns the result to the left operand
*= multiplies the right operand with the left, and a *= 10;
then assigns the result to the left operand
<<= performs bitwise left shift operation, and then a <<= 10;
assigns the result to the left operand

Bitwise operators
Bitwise operators are used to perform operations on individual bits of integer types (like
short , byte , int , long and char types). This means, you can’t use bitwise operators with floating-point
(like float and double types) and boolean types.
Before delving into the details of bitwise operators, let’s take a look at how an integer number is
stored in computer memory.
Binary numbers
We typically deal with numbers using decimal number system. In decimal number system, a number
is represented using digits from 0 to 9 . In computers, numbers are stored using binary number system.
In binary number system,a number is represented using digits 0 and 1 .
So, the decimal numbers that you define in your Java programs are stored as binary numbers in the
computer memory. For instance,an int type variable whose value is 25 is represented as the following
binary number in computer memory:
00000000 00000000 00000000 00011001

As each byte consists of 8 bits and an int type is of 4 bytes (refer table 2-2), the number 25 is stored
as a binary number consisting of 32 bits. For readability, leading 0 s are typically eliminated from a
binary number. So, the decimal number 25 can be written as 11001 in binary format.
You can convert a binary number into a decimal number by multiplying each digit of the binary
number with powers of 2 from right to left, and then summing the individual outputs. Start with 20 ,
and increment the exponent by 1 for each binary digit till you reach the last digit on the left. For
example, the following table shows thatbinary number 11001 represents the decimal number 25 :
Binary 0 0 0 1 1 0 0 1
number
2 ’s power 27 26 25 24 23 22 21 20
27x0 26x0 25x0 24x1 23x1 22x0 21x0 20x1
Result: 16+8+1 = 0 0 0 16 8 0 0 1
25

As shown above, leading 0 s don’t contribute to the calculation.


Now that we know what binary numbers are, let’s look at bitwise operators that you can use to
perform actions on individual bits of a binary number.
Bitwise operators
Table 2-7 shows the bitwise operators availablein Java. & , | , ^ , << , >> and >>> are binary operators,
and ~ is a unary operator.In the table, binary number 00000111 represents decimal number 7 ,
and 10011001 represents decimal number 153 . If leading bits beyond first 8 bits are 0 s, then we’ve only
shown the first 8 bits of the operands in the examples.
Table 2-7 – Bitwise operators
Operator Description Example
& Bitwise AND operator that returns 1 if both 00000111 & 10011001 = 00000001
the bits have the value 1 , else it returns 0
| Bitwise OR operator that returns 1 if one or 00000111 | 10011001 = 10011111
both the bits have the value 1 The
^ Bitwise XOR (exclusive OR) operatorthat 00000111 ^ 10011001 = 10011110
returns 1 if one of the bits is 1 and the other is 0
~ Bitwise NOT unary operator that flips the bits. ~00000111 = 11111111 11111111
This means, 0 s are turned into 1 s and 1 s 11111111 11111000
into 0 s.
<< Bitwise left shift operator that left-shifts the 00000111 << 2 = 00011100
bits of the left operand by the number of digits
specified by the right operand
>> Bitwise right shift operator that right-shifts the 00000111 >> 2 = 0000001
bits of the left operand by the number of digits
specified by the right operand
>>> Bitwise unsigned right shift operatorthat 11111111 11111111 11111111 11111001
shifts the bits of left operand by the number of >>> 2 = 00111111 11111111 11111111
11111110
digits specified by the right operand. In the
case of >>> operator, the shifted bits are filled 11111111 11111111 11111111 11111001
with 0 . is binary representation of -7
In the case of >> operator, shifted bits are
filled with 0 or 1 depending on the sign of the
number. If the number is negative, shifted bits
are filled with 1 . And, if the number is
positive, shifted bits are filled with 0 .
following listing shows the BitwiseOperators class of chapter02 project that shows usage of various
bitwise operators:
Listing 2-10 Bitwise operators
Project: chapter02
Source location: src\chapter02\BitwiseOperators.java
1 package chapter02;
2
3 public class BitwiseOperators {
4 public static void main(String args[]) {
5 System.out.println("7 & 153 : " + (7 & 153));
6 System.out.println("7 | 153 : " + (7 | 153));
7 System.out.println("7 ^ 153 : " + (7 ^ 153));
8 System.out.println("~7 : " + (~7));
9 System.out.println("7 << 2 : " + (7 << 2));
10 System.out.println("7 >> 2 : " + (7 >> 2));
11 System.out.println("-7 >>> 2 : " + (-7 >>> 2));
12 System.out.println("-7 >> 2 : " + (-7 >> 2));
13 }
14 }

If you run the main method of BitwiseOperators class, you’ll see the following output:
7 & 153 : 1 binary equivalent of 1 is 00000001
7 | 153 : 159 binary equivalent of 159 is 10011111
7 ^ 153 : 158 binary equivalent of 158 is 10011110
~7 : -8 binary equivalent of -8 is 11111111 11111111 11111111 11111000
7 << 2 : 28 binary equivalent of 28 is 00011100
7 >> 2 : 1 binary equivalent of 1 is 0000001
-7 >>> 2 : 1073741822 binary equivalent of 1073741822 is 00111111 11111111 11111111 11111110
-7 >> 2 : -2 binary equivalent of -2 is 11111111 11111111 11111111 11111110
Notice that the use of right shift operator in -7 >> 2 preserves the sign of the number by filling the
shifted bits with 1 s.
2-4 Operator precedence
Java operators are evaluated in a certain pre-defined order. The result of an expression may vary
depending on the order in which operators are evaluated. For instance, consider the following
statement:
int a = 2 + 3 * 4;

If + operator is evaluated first,followed by * , the result is 5 * 4 = 20 .If * operator is evaluated


first,followed by + , the result is 2 + 12 = 14 .
The following table describes precedence of some of the Java operators:
Table 2-8 – Operator precedence
Highest * / %
precedence
+ -
<< >> >>>
> >= <
<=
== !=
&
^
|
&&
||
Lowest = += *= -
=
precedence
In the above table, operators that appear higher up in the table are given higher precedenceover other
operators. For instance, * gets higher precedence than + , and == gets higher precedence than && , and
so on. The operators in the same table row have the same precedence.
Let’s look at a few expressions to better understand implications of operator precedence.
Example 1
int a = 2 + 3 *4;

The value of a is 2 + 12 = 14 because * has higher precedence than +


Example 2
int a = 100 / 10 * 5;

The value of a is 10 * 5 = 50 because / and * have the same precedence. If the operators have the
same precedence, they are evaluated in the order they appear in the expression.
Example 3
boolean a = 100 / 10 == 10;
As / operator has higher precedence than == , the evaluation of / operatorresults in the
following expression 10 == 10 . As 10 == 10 is true , the value of a becomes true .
Example 4
boolean a = 10 == 10 + 3;

As + operator has higher precedence than == , the evaluation of + operatorresults in the


following expression 10 == 13 . As 10 == 13 is false , the value of a becomes false .
In the complete evaluation of a compound expression, multiple intermediate expressions are formed.
Let’s look at why the types of these intermediate expressions matter.
Intermediate expression types
You should note that evaluation of an operator should result in a type that is accepted by the
remainder of the expression. For instance, consider the following expression:
boolean a = 10 == 4 >= 3;

As >= has higher precedence, the expression 4 >= 3 evaluatesto true . So, the expression becomes:
boolean a = 10 == true ;
The above expression is incorrect because the left operand is an int type and the right operandis
a boolean type. When using an operator, the types of left and right operands must be compatible. As the
Java compiler can determine the types of intermediate expressions, such issues with expressions are
identified during the compilation of the Java program itself. If you are using Eclipse, the editor will
show the compilation error:

If an intermediate expression type is not compatible with the rest of the expression, Java
Figure 2-6
compiler reports an error
For the above expression, the error message displayed by Eclipse is 'The operator == is undefined for
the argument type(s) int , boolean '.
Let’s now look at how you can enclose sub-expressions in parentheses to override operator
precedence.
Parentheses and operator precedence
The expression enclosed within parentheses ( ) is given highest precedence. Consider the following
expression that evaluates to 14 because precedence of * operator is higher than + operator:
int a = 2 + 3 * 4;

If you enclose the + operator and its operands in parentheses, then the expression inside the
parentheses is given the highest precedence. Which means, that + operator ends up getting higher
precedence than * . The following expression is a variant of the above expression that uses
parentheses:
int a = (2 + 3) * 4;

In the above expression, 2 + 3 is evaluated first because use of parentheses gives highest precedence
to the enclosed expression.So, the final result of evaluating the above expression is 20 (and not 14 ).
QUIZ
2-1 : Which of the following statements are true?
a) a Java literal is a fixed (or constant) value
b) a Java variable name can begin with a number
c) a Java variable name can begin with $ symbol
d) a narrowing conversion results in loss of precision
e) an integer literal in Java is considered to be of type long
f) a floating-point literal in Java is considered to be of type float
2-2: Which of the following Java variable names are correct?
a) 7someVariable
b) class
c) $someVariable
d) someVariable
e) final
f) _someVariable
2-3: Which assignments in the following ConversionsTest class will result in errors during compilation
of the program?
1 package somepackage;
2
3 public class ConversionsTest {
4 public static void main(String args[]) {
5 byte temp = -127;
6 int age = 20;
7 char alphabet = 'a';
8 float mileage = 1.123456F;
9
10 alphabet = age;
11 age = mileage;
12 mileage = alphabet;
13 temp = alphabet;
14 }
15 }

2-4: Consider the following ConversionsTest class that defines a few variables and assigns them different
values. The variables are then assigned to each other using the = assignment operator. What will be
printed by the System.out.println statements?
1 package somepackage;
2
3 public class ConversionsTest {
4 public static void main(String args[]) {
5 int distance1 = 100;
6 int distance2 = 500;
7 int distance3 = 700;
8
9 distance2 = distance1;
10 distance3 = distance2;
11
12 System.out.println("distance1 : " + distance1);
13 System.out.println("distance2 : " + distance2);
14 System.out.println("distance3 : " + distance3);
15 }
16 }

2-5: Consider the following OperatorsTest class that uses various Java operators. What will be printed
by the System.out.println statements?
1 public class OperatorsTest {
2 public static void main(String args[]) {
3 int a = 10;
4 int b = 100;
5 boolean isDone = false;
6
7 boolean x1 = (b % a) != 0;
8 boolean x2 = (b / a) != 0;
9 boolean x3 = x1 && x2;
10 boolean x4 = x1 || x2;
11 boolean x5 = !isDone;
12
13 System.out.println("x1 : " + x1);
14 System.out.println("x2 : " + x2);
15 System.out.println("x3 : " + x3);
16 System.out.println("x4 : " + x4);
17 System.out.println("x5 : " + x5);
18 }
19 }

2-6: Consider the following OperatorsTest class that uses various operators. What will be printed by
the System.out.println statements?
1 package somepackage;
2
3 public class OperatorsTest {
4 public static void main(String args[]) {
5 int a = 10;
6 int b = 100;
7
8 int x1 = b % a + 10;
9 int x2 = b / a * 10;
10 boolean x3 = b % a != 10 && b / a * 10 != 100;
11 boolean x4 = b % a != 10 || true && b / a * 10 != 100;
12 boolean x5 = (b % a != 10 || true) && (b / a * 10 != 100);
13
14 System.out.println("x1 : " + x1);
15 System.out.println("x2 : " + x2);
16 System.out.println("x3 : " + x3);
17 System.out.println("x4 : " + x4);
18 System.out.println("x5 : " + x5);
19 }
20 }
2-5 Summary
In this chapter, we looked at variables, primitive types, operators and how to combine them to form
expressions. We also looked at precedence of commonly used operators. The concepts learnt in this
chapter will be used extensively throughout the rest of this book.
Chapter 3 – Control flow statements
3-1 Introduction
In the previous chapter, we saw that Java statements represent actions performed, and are executed
from top to bottom in the order of their appearance in the program.
There are three types of Java statements:
expression statements – statements that are created by adding semicolons to expressions:
distance2 = distance1;
x = y + 1;

declaration statements – statements that declare variables:


int distance1 = 100;

control flow statements – statements that change the order of execution of statements in the
program. This means, control flow statements change the program flow.
We’ve already seen examples of expression and declaration statements in chapter 2. In this chapter,
we’ll look at control flow statements.
NOTE In programming terminology, a program control (or simply control) identifies the statement
being executed. A control flow statement changes the order of execution of statements by transferring
the program control from one part of the program to another. For this reason, it is often said that a
control flow statement changes the flow of program control.
Types of control flow statements
Java provides following types of control flow statements:
conditional – a conditional control flow statement executes a group of statements only if a
condition is true. The if , if - else and switch statements are examples of conditional control flow
statements.
looping – a looping control flow statement executes a group of statements multiple times.
The for , while and do – while statements are examples of looping control flow statements.
branching – a branching control flow statement transfers the program control to another part
of the program.The break , continue and return statements are examples of branching control flow
statements.
Let’s begin by looking at conditional control flow statements.
IMPORTIt is recommended that you import the chapter03 project into your Eclipse IDE. Refer section
1-5 of chapter 1 for the steps required for importing a project into Eclipse IDE.
3-2 Conditional statements
You should use conditional statements if you want to execute one or more statements only when a
certain condition is true.Java provides if , if – else and switch statements to perform conditional
execution of statements.
if statement
The if statement has the following syntax:
if( <condition> ) {
<statement1> ;
<statement2> ;
}
here, <condition> is an expression which evaluates to a boolean type. If the <condition>
expressionevaluates to true , <statement1> and <statement2> statements are executed.
You should note that the statements to be executed when the <condition>is true are enclosed within
opening { and closing } braces. The <statement1> and <statement2> statements are referred to be in
the if statement block because they are executed only when <condition>evaluates to true . If the
<condition>evaluates to false , <statement1> and <statement2> statements are not executed and the
program execution moves directly to the end of the if statement.
The following listing shows the IfStatement class of chapter03 project that uses the if statement:
Listing 3-1 if statement usage
Project: chapter03
Source location: src\chapter03\IfStatement.java
1 package chapter03;
2
3 public class IfStatement {
4 public static void main(String args[]) {
5 int age = 2;
6 if(age <= 2) {
7 System.out.println("infant");
8 }
9 }
10 }

At line #6, the if statement specifies the expression age <= 2 , which will evaluate to true because value
of age variable is 2 (refer line #5).This means, if you run the main method of IfStatement class, the
statement System.out.println("infant") is executed and the message 'infant' is printed on the output.
Let’s now make some changes to the IfStatement class to understand the behavior of the if statement.
Hands-on Change the if condition to return false
As shown in the following figure, open the IfStatement class of chapter03 project and change the value
of age variable to 3 .
Figure 3-1 The if statement returns false as the value of age variable is 3
If age variable’s value is 3 , the expression age <= 2 returns false . This means, enclosing System.out.println
statement will not be executed. If you now run the IfStatement ’s main method, you’ll not see 'infant'
message printed on the output because System.out.println statement is not executed.
You should note that the expression used by the if statement can be complex, as shown here:
if(speed >= 3 && distance < 100 && acceleration == 10) {
.....
}

Hands-on Add statements before and afterthe if statement


You can have statements before and afterthe if statement. As shown in the following listing, change
the IfStatement classto include a statement before and after the if statement:
Listing 3-2 statements before and afterthe if statement
1 package chapter03;
2
3 public class IfStatement {
4 public static void main(String args[]) {
5 int age = 2;
6 System.out.println("before if statement");
7 if(age <= 2) {
8 System.out.println("infant");
9 }
10 System.out.println("after if statement");
11 }
12 }

In the above listing, System.out.println("before if statement") statement is beforethe if statement


and System.out.println("after if statement") is afterthe if statement. If you now run the main method of IfStatement
class, you’ll get the following output:
before if statement
infant
after if statement

Hands-on Add multiple if statements


As shown in the following listing, modify the IfStatement class to contain multiple if statements:
Listing 3-3 multiple if statements
1 package chapter03;
2
3 public class IfStatement {
4 public static void main(String args[]) {
5 int age = 18;
6 if(age < 30) {
7 System.out.println("age is less than 30"); executed
8 }
9 if(age < 15) {
10 System.out.println("age is less than 15"); not executed
11 }
12 System.out.println("age : " + age); executed
13 }
14 }

The above listing shows the IfStatement class that contains two if statements. The if statement on line #6
checks if age < 30 and the if statement on line #9 checks if age < 15 .As the value of age variable is 18 ,
running IfStatement ’s main method shows the following output:
age is less than 30
age : 18

As age < 15 expression on line #9 evaluates to false , System.out.println("age is less than 15") statement is not
executed.
Hands-on Create nested if statements
You can nest an if statement inside another if statement. The following example listing shows
themodified IfStatement class that uses nested if statements:

Listing 3-4 nested if statements


1 package chapter03;
2
3 public class IfStatement {
4 public static void main(String args[]) {
5 int age = 15;
6 if(age < 30) {
7 System.out.println("age is below 30");
8 if(age < 20) {
9 System.out.println("age is even below 20");
10 if(age < 18) {
11 System.out.println("age is even below 18");
12 }
13 }
14 }
15 System.out.println("age is : " + age);
16 }
17 }

The above listing shows the IfStatement class that contains three if statements nested inside each other.
The value of age variable is set to 15 on line #5.The if statements on line #6, #8 and #10 check the
value of age variable.
If you run IfStatement ’s main method, you’ll get the following output:
age is below 30
age is even below 20
age is even below 18
age is : 15

As age is 15 , the conditions age < 30 , age < 20 and age < 18 evaluateto true . This results in printing 'age is
below 30' (refer line #7), 'age is even below 20' (refer line #9) and 'age is even below 18' (refer line
#11) messages on the output.
Let’s look at the flowchart that depicts execution order of statements in the IfStatement class shown in
listing 3-4.
if statement flowchart
If a program uses control flow statements, you can draw a flowchart to better understand the program
flow. Figure 3-2 depicts the program flow for the IfStatement class’s main method shown in listing 3-4.

Figure 3-2 Flowchart that shows the flow of program control in the IfStatement class’s main method
shown in listing 3-4. The numbered balls ❶ , ❷ and ❸ represent transfer of control when
the if condition evaluates to false .
In the flowchart, following are the commonly used shapes:
rounded rectangleslabelled START and END represent start and end of the main method,
respectively
arrows depict flow of program control
rectanglesrepresent regular statements in the program (like assigning value to age variable,
printing a string to the output, changing a variable’s value, and so on), and
diamond shaped boxes represent if statements in the program
The condition specified in the diamond shaped boxcorresponds to the if statement condition. As the
condition may evaluate to true or false , the arrows originating from the box depict program flow when
the condition evaluates to true and false . For instance, if the value of age variable isset to 40 , the
expression age < 30 (refer line #6 in listing 3-4) will evaluateto false , resulting in transfer of control to
the statement that follows after the if(age < 30) statement block. This means, the control is transferred to
the statement that prints 'age is: 40' (refer line #15 in listing 3-4). In figure 3-2, this transfer of control
is represented by line ❶ .
Similarly, if age variable’s value is 25 , the expression age < 20 (refer line #8 in listing 3-4) will
evaluate to false , resulting in transfer of control to the statement that follows after the if(age < 20)
statement block. This means, the control is transferred to the statement that prints 'age is : 25' (refer
line #15 in listing 3-4). In figure 3-2, this transfer of control is represented by line ❷ .
Instead of setting the value of a variable at the time of writing the Java class, you can supply the value
for a variable at the time of running the main method. Let’s look at how we can add this ability to a
program.
Passing values to programs at execution time
So far we’ve seen programs in which we specified the value of a variable at the time of writing the
program. For instance, the value of age variable in the IfStatement class (refer listing 3-4) was set
to 15 at the time of writing the class. If you want to check the behavior of IfStatement ’s main method
for 5 different values of age variable (let’s say 10 , 20 , 25 , 30 , and 40 ), you’ll need to change the value
of age variable 5 times in the program. You can save the effort of changing the value of age variable by
supplying the value of age variable at the time of running the program.
The following listing shows the NestedIfStatement class (a modified version of IfStatement class shown in
listing 3-4) of chapter03 project that accepts the value of age variable at the time of running the
program:
Listing 3-5 Specifying age variable’s value at execution time
Project: chapter03
Source location: src\chapter03\NestedIfStatement.java
1 package chapter03;
2
3 public class NestedIfStatement {
4 public static void main(String args[]) {
5 int age = Integer.parseInt(args[0]);
6 if (age < 30) {
7 System.out.println("age is below 30");
8 if (age < 20) {
9 System.out.println("age is even below 20");
10 if (age < 18) {
11 System.out.println("age is even below 18");
12 }
13 }
14 }
15 System.out.println("age is : " + age);
16 }
17 }

Notice that instead of specifying aninitial value for the age variable, the value of age variable is set
to Integer.parseInt(args[0]) expression (refer line #5). For now, you can assume that this expression
contains the value passed for the age variableat the time of running the NestedIfStatement ’s main method.
NOTETo understand what exactly Integer.parseInt(args[0]) expression does, you need to know about
objects and classes (explained in chapter 4), static methods (explained in chapter 5), and arrays
(explained in chapter 9).
To pass value for the age variable to the NestedIfStatement class’s main method, right-click on the
NestedIfStatement class in the Package Explorer and select Run As Run Configurations... option:

Figure 3-3 Run Configurations option shows the dialog box for configuring parameters to be passed to the
program
Selecting the Run Configurations option displays the Run Configurations dialog box (refer figure 3-4).
In the Run Configurations dialog box, right-click on Java Application and select New option. This will create a
new configuration (referred to as run configuration) named NestedIfStatement (refer figure 3-5) that you
can customize for running the main method of NestedIfStatement class.

Figure 3-4 Run Configurations dialog box is used for configuring the settings for running the main method of
a Java class
Figure 3-5 The configuration options available for running the NestedIfStatement ’s main method
Go to the Arguments tab and specify the value(s) that you want to pass to
the NestedIfStatement ’s main method. You can pass one or more values separated by spaces. As we want
to pass only a single value to NestedIfStatement ’s main method, we’ve specified the value 15 (refer figure
3-6).

Figure 3-6 Specify the value(s) that you want to pass in the Arguments tab
You can now run the main method of NestedIfStatement class by clicking the Run button. Alternatively, you
can save the settings by clicking the Apply button and later use the Run As Java Application option to
run NestedIfStatement ’s main method.
When you run NestedIfStatement ’s main method, you’ll see the following output:
age is below 30
age is even below 20
age is even below 18
age is : 15
As you can see, the value specified in the Arguments tab is assigned to the age variable in
the NestedIfStatement class. To run the NestedIfStatement ’s main method with a different value
for age variable, go to NestedIfStatement run configuration andchange the value in Arguments tab and click
the Run button. If you change the value to 20 , you’ll now see the following output:
age is below 30
age is : 20
Let’s now look at if-else control flow statement which is an enhanced variantof if statement.
if - else statement
The if statement is used when you want to execute one or more statements ifa condition is true . The if-
else statement is used when you also want to execute one or more statements if the condition is false .

The if-else statement has the following syntax:


if(<condition>) {
<statement1> ;
<statement2> ;
} else {
<statement3> ;
<statement4> ;
}
here, <condition> is the expression thatevaluates to a boolean type. If the <condition>
evaluates to true , <statement1> and <statement2> statements are executed. If the
<condition>evaluates to false , <statement3> and <statement4> statements are executed.
NOTE The statements within opening { and closing } braces following the else statement are referred
to be in the else statement block.The statements in the else statement block are executed only if the
<condition>evaluates to false .
The following listing shows the IfElseStatement class of chapter03 project that uses if-else statement:
Listing 3-6 if - else statement
Project: chapter03
Source location: src\chapter03\IfElseStatement.java
1 package chapter03;
2
3 public class IfElseStatement {
4 public static void main(String args[]) {
5 int age = 30;
6 System.out.println("age : " + age);
7 if (age < 30) {
8 System.out.println("age is below 30");
9 } else {
10 System.out.println("age is >= 30");
11 }
12 }
13 }

On line #5,the value of age variable is set to 30 ; therefore, the age < 30 expression evaluates to false on
line #7.As the age < 30 expression evaluates to false , the if statement block is skipped and the control
moves directly to the else statement on line #9. If you run IfElseStatement ’s main method, you’ll get the
following output:
age : 30
age is >= 30

If you change the value of age variable to 15 , then the expression age < 30 evaluates to true . This results
in execution of the if statement block, and the following output is generated:
age : 15
age is below 30

The following flowchart depicts the behavior of if-else statement in listing 3-6:

Figure 3-7 Flowchart depicting program flow when using if-else statement
The above figure shows that the if statement block is executed when the age < 30 expression evaluates
to true and the else statement block is executed when age < 30 evaluates to false .
You can write complex programming logic by nesting if-else statements inside if and if-else
statements.For instance, the following NestedIfElseStatement class of chapter03 project determines if the
value of age variable is greater than 30 or less than 15 :
Listing 3-7 Nested if - else statement
Project: chapter03
Source location: src\chapter03\NestedIfElseStatement.java
1 package chapter03;
2
3 public class NestedIfElseStatement {
4 public static void main(String args[]) {
5 int age = Integer.parseInt(args[0]); value of age is supplied at program execution time
6 System.out.println("age : " + age);
7 if (age > 30) {
8 System.out.println("age is greater than 30");
9 } else {
10 System.out.println("age is <= 30");
11 if (age < 15) {
12 System.out.println("age is less than 15");
13 } else {
14 System.out.println("age is >= 15");
15 }
16 }
17 }
18 }

Line #5 shows that the value of age variable is supplied at the time of
running NestedIfElseStatement ’s main method. The if statement on line #6 checks if age > 30 . If age
>30 evaluates to true , 'age is greater than 30' (refer line #8) is printed on the output. If age > 30 evaluates
to false , the control movesto the else statement block on line #9.At this time, we know that the value
of age variable is lessthan or equal to 30 , but we don’t know whether it’s lessthan 15 .For this reason,
another if-else statement is used to check if age <15 . Again, if age < 15 evaluates to true , 'age is less than
15' is printed, else 'age is >= 15' is printed.
Figure 3-8 shows the flowchart that depicts program flow in the case of NestedIfElseStatement class. A
program’s execution path is the path followed by the program from start to finish. The flowchart in
figure 3-8 uses numbered balls to represent different execution paths that the program can have. A
quick look at the flowchart suggests that number of execution paths increase as you add more if-else
statements into your programs. For instance, the flowchart in figure 3-8 shows that there are three
possible execution paths that the program can take.
Figure 3-8Flowchart depicting program flow when an if-else statement is used inside an existing if-else
statement. The numbered balls represent the different execution paths that the program can have.
Let’s now look at the switch control flow statement.
switch statement
In a switch control flow statement, a group of statements are mapped to the result of evaluation of an
expression. The expression must evaluate to a numeric or string valueor an Enum type.
NOTE The coverage of Enum types is outside the scope of this book.
The syntax of a switch statement is:
switch( <expression> ) {
case x:
<statement1>;
<statement2>;
break;
case y:
<statement3>;
<statement4>;
break;
}

here, <expression>is an expression that evaluates to byte , short , char or int primitive type, or to
a string valueor to an Enum type
x and y are the two possible values to which the <expression> might evaluate to. The case
x: and case y: labels specify the statements that are executed when <expression>evaluates
to x and y , respectively. If the <expression>evaluates to x , the <statement1>, <statement2>
and break statements are executed. And, if the <expression>evaluates to y , the
<statement3>, <statement4> and break statements are executed.
NOTE Later in this section, we’ll see whystatements associated with case labels typically end with
the break statement
The following example listing shows the SwitchStatement class of chapter03 project that uses the switch
statement:
Listing 3-8 switch statement
Project: chapter03
Source location: src\chapter03\SwitchStatement.java
1 package chapter03;
2
3 public class SwitchStatement {
4 public static void main(String args[]) {
5 int x = 15;
6 switch (x % 2) {
7 case 0:
8 System.out.println(x + " is an even number");
9 break;
10 case 1:
11 System.out.println(x + " is an odd number");
12 break;
13 }
14 System.out.println("After switch statement");
15 }
16 }

The above program checks if the value of variable x is odd or even. If the value is odd (which means
the result of x % 2 expression is 1 ), it prints '<value of x> is an odd number'. And, if the value is even
(which means the result of x % 2 expression is 0 ), it prints '<value of x> is an even number'.As x % 2
can evaluate either to 0 or 1 , switch statement (refer line #6) has been used to decide what statements
to executewhen the value is 0 and 1 .If x % 2 evaluates to 0 , the control moves directly to case 0: label
(refer line #7) and the System.out.println(x + " is an even number") statement is executed. If x % 2 evaluates to 1 ,
the control moves directly to case 1: label (refer line #10) and the System.out.println(x + " is an odd number")
statement is executed.
A break statement endsthe switch statement. This means, when the break statement is encountered, the
control is transferred to the statement that comes afterthe switch statement. For this reason, when
the break statementinside case 0: and case 1: labels is executed in listing 3-8, the control is transferred to
line #14 that prints 'After switch statement'.
If you run SwitchStatement ’s main method, you’ll get the following output:
15 is an odd number
After switch statement

The above output shows that the statement System.out.println(x + " is an odd number") (refer line #11)
associated with case 1: label was executed, followed by execution of the statement System.out.println("After
switch statement") that comes after the switch statement.

Figure 3-9 shows the flowchart that depicts the behavior of switch statement used in listing 3-8.
Let’s do some hands-on exercise to better understand how switch statement works.
Hands-on Define duplicate case labels
As shown in the following figure, modify the SwitchStatement class to have duplicate case 1: labels:

Figure 3-10 As case 1: is defined twice in the switch statement, Eclipse editor complains that
duplicate case 1: labels have been defined for the switch statement
As duplicate case labels are notallowed in a switch statement, the above figure shows that Eclipse
complains about the presence of duplicate case 1: labels in the switch statement.
Hands-on Remove break statement from case 0: label
As shown in listing 3-9, make the following changes to the SwitchStatement class:
change the value of variable x from 15 to 16 , and
remove the break statement from case 0: label

Listing 3-9 case0: label without break statement


1 package chapter03;
2
3 public class SwitchStatement {
4 public static void main(String args[]) {
5 int x = 16;
6
7 switch (x % 2) {
8 case 0:
9 System.out.println(x + " is an even number");
10 case 1:
11 System.out.println(x + " is an odd number");
12 break;
13 }
14 System.out.println("After switch statement");
15 }
16 }

As shown above, case 0: doesn’tcontain the last statement as the break statement.If you now run
the SwitchStatement ’s main method, you’ll see the following output:
16 is an even number
16 is an odd number
After switch statement

The output shows that statements associated withboth case 0: and case 1: labels are executed. As the
value of x is 16 , x % 2 evaluates to 0 . The switch statement transfers control to case 0: label, which
results in execution of System.out.println(x + " is an even number") statement. As the default behavior of a switch
statement is to execute statements of all the case labels that come after the matching case label, the
System.out.println(x + " is an odd number") statement associated with case 1: label is also executed. And, for this
reason, we specify break as the last statement associated with a case label to ensure that only the
statements associated with the matching case label are executed.
The flowchart shown in figure 3-11 depicts the behavior of SwitchStatement ’s main method when
the break statement isn’t used in the case 0: label: The figure shows that if x % 2 evaluates to 0 ,
statements in both case 0: and case 1: labels are executed.
The default: label
If you want that a set of statements are executed only when none of the case labels are matched, then
specify such statements using default: label. Listing 3-10shows the PrintDayOfWeek class
of chapter03 project that prints the day of the week (like, Sunday, Monday, and so on) depending on the
value of day variable.

Listing 3-10 default: label


Project: chapter03
Source location: src\chapter03\PrintDayOfWeek.java
1 package chapter03;
2
3 public class PrintDayOfWeek {
4 public static void main(String args[]) {
5 int day = Integer.parseInt(args[0]); value of day variable is provided at execution time
6 // value of day must be between 1 to 7
7 switch (day) {
8 case 1:
9 System.out.println("Sunday");
10 break;
11 case 2:
12 System.out.println("Monday");
13 break;
14 case 3:
15 System.out.println("Tuesday");
16 break;
17 case 4:
18 System.out.println("Wednesday");
19 break;
20 case 5:
21 System.out.println("Thursday");
22 break;
23 case 6:
24 System.out.println("Friday");
25 break;
26 case 7:
27 System.out.println("Saturday");
28 break;
29 default:
30 System.out.println("Error: Enter value from 1 to 7");
31 }
32 }
33 }

On line #5, the day variable is assigned the numeric value passed to PrintDayOfWeek ’s main method at
the time of execution. You can pass any integer value from 1 to 7 for the day variable. The
value 1 corresponds to 'Sunday', 2 to 'Monday', and so on. To handle situations in which the passed
value is less than 1 or greater than 7 , a default: label has been added (refer line #29) towards the end of
the switch statement. The default: label contains a single statement that prints 'Error: Enter value from 1
to 7'.
NOTE In the case of default: label, we haven’t specified the break statementbecause default: label has
been specified after all the case labels. If you specify default: label anywhere except at the end, then
you mustadd the break statement to ensure that only the statements associated with default: label are
executed.
Specifyingmultiple case labels for the same set of statements
You can associate multiple case labels with a set of statements. The following listing shows
the PrintQuarterOfYear class that prints the quarter (first, second, third or fourth) to which a given month
belongs:
Listing 3-11 multiple case labels for a group of statements
Project: chapter03
Source location: src\chapter03\PrintQuarterOfYear.java
1 package chapter03;
2
3 public class PrintQuarterOfYear {
4 public static void main(String args[]) {
5 int month = Integer.parseInt(args[0]); month variable’s value is supplied at execution
6 switch (month) {
7 case 1:
8 case 2:
9 case 3:
10 System.out.println("The month belongs to first quarter of the year");
11 break;
12 case 4:
13 case 5:
14 case 6:
15 System.out.println("The month belongs to second quarter of the year");
16 break;
17 case 7:
18 case 8:
19 case 9:
20 System.out.println("The month belongs to third quarter of the year");
21 break;
22 case 10:
23 case 11:
24 case 12:
25 System.out.println("The month belongs to fourth quarter of the year");
26 break;
27 }
28 }
29 }

On line #5, month variable is assigned the numeric value passed to PrintQuarterOfYear ’s main method at
the time of execution. The switch statement uses the month variable’s value to find the matching case
label. The matched case label prints the quarter to which the month belongs. As multiple months
belong to a quarter, we’d want the same System.out.println statement to be executed for months belonging
to the same quarter. For this reason, we’ve associated case labels corresponding to a quarter with the
same System.out.println statement.For instance, months 1 , 2 and 3 belong to the first quarter; therefore, case
1: , case 2: and case 3: labels are associated with System.out.println("The month belongsto first quarter of the year")
statement.
3-3 Looping statements
Looping control flow statements are used to iterate over a group of statements as long as a given
condition is true.The while , do-while and for statements in Java are examples of looping statements.
Let’s begin by looking at the while statement.

while statement
A while statement (also referred to as a while loop) continues execution of a group of statements as long
as the given condition is true . The syntax of a while statement is:
while(<expression>) {
<statement1>;
<statement2>;
}
here, <expression> represents a conditional expression that evaluates to a boolean type. The
block of statements contained within opening { and closing } braces constitute the while
statement block. <statement1> and <statement2> statements are executed repeatedly until
the <expression>evaluates to false .
The following listing shows the Print10Integers class of chapter03 project that uses the while loop to print
10 consecutive integers starting from 11 :

Listing 3-12 Print 10 consecutive integers


Project: chapter03
Source location: src\chapter03\Print10Integers.java
1 package chapter03;
2
3 public class Print10Integers {
4 public static void main(String args[]) {
5 int number = 11;
6 int count = 0;
7 while(count < 10) {
8 System.out.println("Integer : " + number);
9 count++;
10 number++;
11 }
12 System.out.println("Value of count is : " + count);
13 System.out.println("Value of number is : " + number);
14 }
15 }
In the above listing, number variable (line #5) holds the number that we want to print. As we want to
start printing from 11 , the number variable is initialized to 11 .The count variable (line #6) keeps track of
the count of numbers printed. The value of count variable is initializedto 0 . The while statement (line
#7) is responsible for printing 10 consecutive numbers starting from 11 . As we want to print 10
numbers, the count < 10 expression specifies the condition that must be true for the statements in the while
block to be executed.
Let’s look at how the Print10Integers ’s main method prints 10 integers beginning with 11 :
1. When the program control reaches the while loop for the first time, the value
of number is 11 and count is 0 . The expression count < 10 evaluates to true andthe statements inside
the while loop are executed. The statement System.out.println("Integer : " + number) (line #8) prints
'Integer : 11'on the output. count++ (line #9) increments the value of count to 1 and number++ (line
#10) increments the value of number to 12 .
2. The control goes back to the beginning of the while loop. As the current value of count is 1 , the
expression count < 10 evaluates to true .As the value of number variable is currently 12 , the
statement System.out.println("Integer : " + number) prints 'Integer : 12'on the output. count++ increments
the value of count to 2 and number++ increments the value of number to 13 .
3. The control goes back to the beginning of the while loop. As the current value of count is 2 , the
expression count < 10 evaluates to true . As the value of number variable is currently 13 , the
statement System.out.println("Integer : " + number); prints 'Integer : 13'on the output. count++ increments
the value of count to 3 and number++ increments the value of number to 14 .
This execution sequence continuesall the way till count < 10 returns false . Let’s look at what happens
after count value reaches 9 .
4. The control goes back to the beginning of the while loop. As the current value of count is 9 ,the
expression count < 10 evaluates to true . As the current value of number variable is 20 ,the
statement System.out.println("Integer : " + number) prints 'Integer : 20'on the output. count++ increments
the value of count to 10 and number++ increments the value of number to 21 .
5. The control goes back to the beginning of the while loop. As the current value of count is 10 , the
expression count < 10 evaluates to false . The while statement block is skipped and the control
goes to the statement immediatelyfollowing the while loop.The System.out.println("Value of count is : " +
count) statement (line #12) prints 'Value of count is : 10'and the System.out.println("Value of number is : "
+ number) statement (line #13) prints 'Value of number is : 21'.

If you run Print10Integers ’ main method, you’ll get the following output:
Integer : 11
Integer : 12
Integer : 13
Integer : 14
Integer : 15
Integer : 16
Integer : 17
Integer : 18
Integer : 19
Integer : 20
Value of count is : 10
Value of number is : 21
Figure 3-12 shows the flowchart that depicts how the while loopof Print10Integers class works when the
program is executed. The flowchart clearly indicates that the only way for the program to end is to
reach a condition in which the expression count < 10 evaluates to false . If the condition specified by while
statement is never reached because of some reason, the program will continue to run indefinitely.
NOTEBefore writing a while loop you must think about what condition should be specified for
the while loop and what actions are performed in the while statement block. This will ensure that your
program behaves just the way you want.
Let’s look at another example that uses while loop for printing sum of 20 consecutive numbers starting
from 1 .
The following listing shows the PrintSumOf20Integers class of chapter03 project that prints sum of 20
consecutive numbers starting from 1 (that is, sum of 1 + 2 + 3 + ... + 20 ):
Listing 3-13 Sum of 20 consecutive numbers
Project: chapter03
Source location: src\chapter03\PrintSumOf20Integers.java
1 package chapter03;
2
3 public class PrintSumOf20Integers {
4 public static void main(String args[]) {
5 int number = 1;
6 int sum = 0;
7 int count = 0;
8
9 while(count < 20) {
10 sum = sum + number;
11 number++;
12 count++;
13 System.out.println("Interim sum : " + sum);
14 }
15 System.out.println("Final sum : " + sum);
16 }
17 }

The number variable (line #5) holds the number to be included in the sum. As we want to sum numbers
starting from 1 ,the number variable isinitialized to 1 . The sum variable (line #6) holds the sum.
The count variable (line #7) keeps track of the count of numbers whose values have been included in
the sum. Both count and sum variables are initialized to 0 . The while loop is responsible for calculating
sum by iterating over 20 numbers starting from 1 . As we want to calculate sum of 20 consecutive
numbers, the count < 20 expression specifies the condition that must be true for the statements in the while
block to be executed.
This is how the while loop calculates the sumof 20 consecutive numbers starting from 1 :
1. When the program control reaches the while loopfor the first time, the value
of number is 1 , count is 0 and sum is 0 .The count < 20 expression evaluates to true , and the while
statement block is executed.The sum = sum + number statement (line #10) changes the value
of sum to (0 + 1) , that is 1 . count++ (line #12) increments the value of count to 1 , and number++
(line #11) increments the value of number to 2 .The System.out.println("Interim sum : " + sum) statement
(line #13) prints 'Interim sum : 1' on the output.
2. The control goes to the beginning of the while loop. As the current value of count is 1 , the
expression count < 20 evaluates to true , and the statements inside the while loop are executed. As
the current value of sum is 1 and number is 2 , the value of sum + number (that is, 1 + 2= 3 ) is
assigned to the sum variable. number++ increments the value of number to 3 . count++ increments the
value of count to 2 . As the current value of sum is 3, the System.out.println("Interim sum :" + sum)
statement prints 'Interim sum : 3' on the output.
3. The control goes to the beginning of the while loop.As the current value of count is 2 , the
expression count < 20 evaluates to true , and the statements inside the while loop are executed. As
the currentvalue of sum is 3 and that of number is 3 , the value of sum variable becomes 3 + 3 =
6 . number++ increments number to 4 and count++ increments count to 3 .As the current value
of sum is 6, the System.out.println("Interim sum : " + sum) statement prints 'Interim sum : 6' on the output.
This execution sequence continues all the way till count < 20 returns false . Let’s look at what happens
after count value reaches 19 .
4. The control goes back to the beginning of the while loop. As the value of count is 19 at this time,
the expression count < 20 evaluates to true . As the value of number variable is 20 at this timeand
that of sum is 190 , the value of sum variable becomes 190 + 20 = 210 . number++ increments number
to 21 and count++ increments count to 20 . As the current value of sum is 210 ,
the System.out.println("Interim sum : " + sum) statement prints 'Interim sum : 210' on the output.
5. The control goes back to the beginning of the while loop. As the current value of count is 20 , the
expression count < 20 evaluates to false . The while statement block is skipped and the control
goes to the statement immediately following the while loop. As the current value
of sum variable is 210 , the System.out.println("Final sum : " + sum) statement prints 'Final sum : 210'.
If you run PrintSumOf20Integers ’ main method, you’ll get the following output:
Interim sum : 1
Interim sum : 3
Interim sum : 6
.....
Interim sum : 210
Final sum : 210

A while loop will continue to execute forever if the specified condition never returns false . Let’s see
how we can forcefully stop a program from running forever.
Stopping programs from running indefinitely
If you write a while loop that uses a conditional expression that always evaluates to true , then your
program will continue to run indefinitely. To stop such a program, you can use the 'Terminate' option
(in the Console tab) of Eclipse to forcefully stop the running program. The following figure shows the
'Terminate' option:

Figure 3-13 You can use the' Terminate 'button in the Console tab of Eclipse IDE to terminate a program at
any time
In the above figure, the red square button on the Console tab indicates that the program is running.
Clicking this red button will forcefully terminate the program. When the program terminates, the
button is greyed out.
Let’s now look at the do-while statement - a variant of while statement.

do - while statement
In the do-while statement (also referred to as a do-while loop) the do statement block contains the
statements to be executed and the while statement block is empty.The syntax of do-while loop is:
do {
<statement1>;
<statement2>;
} while(<expression>);
here, the block containing the statements inside the opening { and closing } braces is called
the do statement block. <expression>represents a conditional expression that evaluates to
a boolean type.
When the program control reaches the do-while statement for the first time,the statements in the do
statement block are executed. That is, <statement1> and <statement2> statements are executed
without even evaluating the <expression>. This means that the statements in the do statement block
are executed at least once irrespective of whether the <expression>evaluates to true or false . Once the
statements in the do statement block are executed, the <expression> is evaluated. If the
<expression>evaluates to true , the control moves back to the do statement block and the statements
are executed once again. This process continues until the <expression>evaluates to false . If the
<expression>evaluates to false , the do-while statement terminates and the control moves to the
statement that comes after the do-while statement.
NOTEYou should use do-while statement if you want to execute the loop at least once. And, you should
use while statement if you want to execute the loop only when a given condition is met.
The following listing shows the Print10IntegersDoWhile classof chapter03 project that uses do-while statement
to print 10 consecutive numbers starting from 11 :
Listing 3-14 Print 10 numbers starting from 11
Project: chapter03
Source location: src\chapter03\Print10IntegersDoWhile.java
1 package chapter03;
2
3 public class Print10IntegersDoWhile {
4 public static void main(String args[]) {
5 int number = 11;
6 int count = 0;
7 do {
8 System.out.println("Integer : " + number);
9 count++;
10 number++;
11 } while(count < 10);
12 System.out.println("Value of count is : " + count);
13 System.out.println("Value of number is : " + number);
14 }
15 }

Print10IntegersDoWhile and Print10Integers (refer listing 3-12) classes are same,except


that Print10Integers uses while statement. As shown in figure 3-14, the statements contained in
the while statement block of Print10Integers class are now inside the do statement block
of Print10IntegersDoWhile class. If you run Print10IntegersDoWhile ’s main method, you’ll get exactly the same
output as you got fromrunning Print10Integers ’s main method.

The while and do-while statements look similar. The while statement block is replaced by the do
Figure 3-14
statement block.
Unlike the while statement blockof while loop, the do statement block of do - while loop is executed at
least once. This results in difference in behaviors of programs. For instance, if you initialize the value
of count variable to 10 in Print10IntegersDoWhile class and run its main method, you’ll get the following
output:
Integer : 11
Value of count is : 12
Value of number is : 12

The output shows that the statements in the do statement block are executed once.
Similarly, if you initialize the value of count variable to 10 in Print10Integers class (refer listing 3-12) and
run its main method, you’ll get the following output:
Value of count is : 11
Value of number is : 11

As the count < 10 expression evaluates to false , the statements in the while statement block are not
executed.
In the context of Print10IntegersDoWhile class, the flowchart in figure 3-15 shows how the do-while statement
works. The flowchart clearly indicates that the statements in the do block are executed before the
expression in the while statement is executed.
Let’s now look at the for statement that can also be used for iterating over a group of statements.

for statement
The for statement (also referred to as for loop) offers more options than while and do-while loops for
iterating over a group of statements. The syntax of a for statement is:
for(<init-expression>; <conditional-expression>; <increment-or-decrement-expression>)
{
<statement1>;
<statement2>;
}
here, the statements insideopening { and closing } braces constitute the for statement block
<init-expression> is an expression that declares and initializes one or more variables. The
<init-expression> expression is evaluated only oncewhen the program control reaches
the for statement. The variable(s) declared by the <init-expression>is used inside the for
statement block.
<conditional-expression>is a conditional expression that evaluates to a boolean type. If the
<conditional-expression>evaluates to true , <statement1> and <statement2> statements are
executed.
<increment-or-decrement-expression> refers to an expression that increments or decrements
variable(s) declared in the <init-expression> expression. This expression is evaluated after
each execution of the for statement block.
The following listingshows the Print10IntegersForStatement class of chapter03 project that prints 10
consecutive numbers starting from 1 :
Listing 3-15 Print numbers 10 numbers starting from 1
Project: chapter03
Source location: src\chapter03\Print10IntegersForStatement.java
1 package chapter03;
2
3 public class Print10IntegersForStatement {
4 public static void main(String args[]) {
5 for(int count = 1; count <= 10; count++) {
6 System.out.println("Integer : " + count);
7 }
8 }
9 }
In the above class, following expressions have been used inthe for loop:
int count = 1 corresponds to <init-expression>
count <= 10 corresponds to <conditional-expression>
count++ corresponds to <increment-or-decrement-expression>
NOTEA variable declared in the <init-expression> expression is available only inside the for statement
block; you cannot access it outside the for statement block. This means, in listing 3-15, you cannot
access the count variable outside the for statement block.
This is how the for statement works:
1. When the program control reaches the for statement, the <init-expression> is evaluated.This
means, the int count = 1 expression is evaluated, which declares a count variable with initial
value 1 . The <init-expression> is evaluated only oncewhen the program control reaches
the for statement for the first time.
2. The <conditional-expression> is evaluated. This means, count <= 10 expression is evaluated. If
the expression evaluates to true , the for statement block is executed, otherwise it is skipped.
Notice that we declared the count variable in the for statement itself and now we are using it in
the <conditional-expression> to determine whether to execute or skip the for statement
block.As the value of count variable is 1 , the count <= 10 expression evaluates to true .
3. The for statement block is executed.The System.out.println("Integer : " + count) statement prints 'Integer
: 1'because the current value of count is 1 .
4. The control goes back to the beginning of the for statement and <increment-or-decrement-
expression>is evaluated. This means, count++ expression is evaluated.As the current value
of count is 1 , the count++ increments the current value of count to 2 .
5. The <conditional-expression>is evaluated again to determine if the for statement block
needs to be executed or skipped. This means, count <= 10 expression is evaluated again.As the
current value of count is 2 , count <= 10 evaluates to true .
6. The for statement block is executed.The System.out.println("Integer : " + count) statement prints 'Integer
: 2'because the current value of count is 2 .
The steps from 2 to 4 are executed till the <conditional-expression>(that is, count <= 10 ) evaluates
to false . When the <conditional-expression>evaluates to false , the for loop terminates and the control
is transferred to the statement that comes immediately after the for loop.
Figure 3-16 shows the flowchart that summarizes how the for statement of Print10IntegersForStatement class
works. The numbered balls depict the program flow. The listing 3-15 and figure 3-16 show that a for
loop is quite compact compared to both while and do-while loops.

Figure 3-16 Flowchartshowing how the for loop worksin Print10IntegersForStatement class
Instead of declaring and incrementing a singlevariable in the for loop, you can declare and increment
multiple variables, given that they are of the same type. The following example listing shows
the Print10IntegersForStatementVariant class of chapter03 that uses the for loop for printing 10 consecutive
numbers starting from 11 :
Listing 3-16 Print 10 consecutive numbers starting from 11
Project: chapter03
Source location: src\chapter03\Print10IntegersForStatementVariant.java
1 package chapter03;
2
3 public class Print10IntegersForStatementVariant {
4 public static void main(String args[]) {
5 for(int count = 0, number = 11; count < 10; count++, number++) {
6 System.out.println("Integer : " + number);
7 }
8 }
9 }

In the above listing, following expressions have been used inthe for loop:
corresponds to <init-expression>
int count = 0, number = 11
count <10 corresponds to <conditional-expression>
count++ and number++ corresponds to <increment-or-decrement-expression>
Let’s now look at an example that requires defining a looping statement inside another looping
statement.
Nested loops
You can write programs that contain nesting of looping statements. For instance, the following listing
shows the NestedForStatement class of chapter03 project that contains nested for loops:
Listing 3-17 nested for loops
Project: chapter03
Source location: src\chapter03\NestedForStatement.java
1 package chapter03;
2
3 public class NestedForStatement {
4 public static void main(String args[]) {
5 for(int i = 0; i < 5; i++) {
6 System.out.println("i : " + i);
7 for(int j=0; j < 2; j++) {
8 System.out.println("--> j : " + j);
9 }
10 }
11 }
12 }

In the above listing, a for loop is contained inside another for loop. By looking at the for loop
statements, you can figure out that the external for loop (line #5) executes 5 times (from i = 0 to i = 4 ) and
the nested for loop (line #7) executes 2 times (for j = 0 and j = 1 ). As the nested for loop is encountered
each timethe external for loop is executed, the nested for loop is executed 2 times for each execution
of the external for loop.
If you run the NestedForStatement ’s main method, you’ll get the following output:
i:0
--> j : 0
--> j : 1
i:1
--> j : 0
--> j : 1
i:2
--> j : 0
--> j : 1
i:3
--> j : 0
--> j : 1
i:4
--> j : 0
--> j : 1

The output shows that the nested for loop is executed twice on eachexecution of the external for loop.
In this section, we saw how looping statements (like while , do-while and for ) are used for iterating over a
group of statements multiple times. In the next section, we’ll look at branching control flow statements
that transfer program control from one part of the program to another.
3-4 Branching statements
Java defines break , continue and return branching statements that are used to transfer program control
from one part of the program to another. In this section, we’lllook at break and continue statements.
The return statement is covered in chapter 4 because it is used particularly with methods.

break statement
In the context of switch statement, we saw that the break statement is used to terminate the switch
statement.If a break statement is used inside a for , while or do-while loop, it terminates the loop and the
control is transferred to the statement that immediately follows the loop.
The following listing shows the SimpleBreakStatement class of chapter03 project that contains a for loop
that uses break statement to terminate the loop when the value of count is 5 :
Listing 3-18 break statement usage inside a for loop
Project: chapter03
Source location: src\chapter03\SimpleBreakStatement.java
1 package chapter03;
2
3 public class SimpleBreakStatement {
4 public static void main(String args[]) {
5 for(int count = 0; count < 10; count++) {
6 System.out.println("count : " + count);
7 if(count == 5) {
8 break;
9 }
10 }
11 System.out.println("Outside for loop");
12 }
13 }
In the above listing, the for loop is defined such that it continues to execute till the value of count
variable (line #5) reaches 10 .The if statement (line #7) contained in the for loop keeps checking the
value of count during each iteration. When the value of count reaches 5 , the count == 5 expression
evaluates to true , and the break statement (line #8) is executed.The break statement terminates the for
loop, and the control is transferred to the statement afterthe for loop, that is, to the statement on line
#11.
If you execute SimpleBreakStatement ’s main method, you’ll get the following output:
count : 0
count : 1
count : 2
count : 3
count : 4
count : 5
Outside for loop
The output shows that the for loop is terminated after the value of count reaches 5 .

continue statement
When a continue statement is encountered in a loop, the remaining statements in the current iteration are
skipped and the control goes back to the beginning of the loop.In a way, continue statement completes
the current iteration of the loop without executing the remaining statements in the loop.
The following listing shows the SimpleContinueStatement class whose for loopuses continue statementto
avoid writing anything to the output until the value of count variable is greaterthan 5 :
Listing 3-19 continue statement usage inside for loop
Project: chapter03
Source location: src\chapter03\SimpleContinueStatement.java
1 package chapter03;
2
3 public class SimpleContinueStatement {
4 public static void main(String args[]) {
5 for (int count = 0; count < 10; count++) {
6 if (count <= 5) {
7 continue;
8 }
9 System.out.println("count : " + count);
10 }
11 }
12 }

In the above listing, the for loop continues to execute till the value of count reaches 10 . The if statement
(line #6) contained in the for loop keeps checking the value of count during each iteration. If the
expression count <= 5 evaluates to true , the continue statement (line #7) is executed. This means, the
statement System.out.println("count : "+ count) is skipped and the control is transferred to the beginning
ofthe for loop. The count++ expression is evaluated,followed by evaluation of count < 10
expression.When the value of count reaches 6 , the count <=5 evaluates to false , and the control reaches
the System.out.println("count : "+ count) statement.
Figure 3-17 The continue statement skips the remaining statements in the for loop and transfers control
back to the beginning of the for loop
If you run SimpleContinueStatement ’s main method, you’ll get the following output:
count : 6
count : 7
count : 8
count : 9

The above output shows that System.out.println("count : "+ count) statement was skipped as long as the value
of count was <= 5 .
In the context of SimpleContinueStatement class, figure 3-17 shows the affect of continue statement on
program execution. The numbered balls represent the program flow. The figure shows that when
the continue statement is reached, the control goes back to the beginning of the for loop.
You may come across situations in which may want to run loops that never end. Let’s look at how we
can use different looping statements to create loops that continue to run indefinitely.
3-5 Infinite loops
You can use while , do-while and for statements to create infiniteloops. To create an infinite while loop,
specify the condition as true :
while (true) {
<statement1>;
<statement2>;
}

The above while loop will continue to run forever because the condition is always true .
Similarly, to create an infinite do-while loop, specify the condition as true :
do {
<statement1>;
<statement2>;
} while(true);

To create an infinite for loop, don’t specify any expressions:


for ( ; ; ) {
<statement1>;
<statement2>;
}
If you write an infinite loop and run the program, the only way to end the program is to use the
'Terminate' button (refer figure 3-13 in section 3-3) of Eclipse IDE.
QUIZ
3-1: What would be the output from running the main method of the following MyIfStatement class?
1 package somepackage;
2
3 public class MyIfStatement {
4 public static void main(String args[]) {
5 int age = 2;
6 System.out.println("age : " + age);
7 if(age <= 2) {
8 System.out.println("infant");
9 age = age + 2;
10 System.out.println("age + 2 : " + age);
11 }
12 age = age + 4;
13 System.out.println("age + 4 : " + age);
14 }
15 }

3-2: What would be the output from running the main method of the following MyIfElseStatement class?
1 public class MyIfElseStatement {
2 public static void main(String args[]) {
3 int a = 100;
4 int b = 10;
5 if(a < b) {
6 a = a - b;
7 } else {
8 b = b - a;
9 }
10 if(a - b >= 90) {
11 System.out.println("a is : " + a);
12 } else {
13 System.out.println("b is : " + b);
14 }
15 }
16 }

3-3: What would be the output from running the main method of the following MySwitchStatement class?
1 public class MySwitchStatement {
2 public static void main(String args[]) {
3 int a = 100;
4 switch(a) {
5 case 100:
6 System.out.println("case 100:");
7 case 200:
8 System.out.println("case 200:");
9 default:
10 System.out.println("case default:");
11 }
12 }
13 }

3-4: What would be the output from running the main method of the following Test class?
1 package test;
2
3 public class Test {
4 public static void main(String args[]) {
5 int x = 10;
6 int y = 1;
7 int sum = 0;
8
9 while(x > 0 && y < 10) {
10 sum = x + y;
11 System.out.println("x + y " + sum);
12 x--;
13 y++;
14 }
15 }
16 }

3-5: What is the output from running the main method of the following ContinueStatement class?
1 package somepackage;
2
3 public class ContinueStatement {
4 public static void main(String args[]) {
5 for (int i = 0; i < 10; i++) {
6 System.out.println("i : " + i);
7 for (int j = 0; j < 10; j++) {
8 if (j < 5) {
9 continue;
10 }
11 if (j >= 5) {
12 break;
13 }
14 System.out.println("j : " + j);
15 }
16 }
17 }
18 }
3-6 Summary
In this chapter, we looked at different control flow statements available in Java. The control flow
statements help you write programs that can do the following:
conditionally execute some programming logic (example : if , if-else and switch )
iterate over statements as long as a certain condition is true (example: while , do-while and for )
skip or terminate execution of while , do-while and for loops (example: break and continue )
As control flow statements are at the heart of any program, the programs in the rest of the chapters
make extensive use of these control flow statements. In the next chapter, we look at how to think in
terms of objects, which is central to object-oriented programming.
Chapter 4 – Objects, classes and methods
4-1 Introduction
We typically write computer programs to solve real-world problems. In object-oriented
programming, real-world objects are modelled as software objects. For instance, if you are building
software that simulates car racing, you’ll represent real-world cars as software objects in your
computer program.
An object has state and behavior. The state tells the attributes of the object, and the behavior tells
what the object is capable of doing. For instance, a car’s state consists of its color, model and current
speed. And, a car’s behaviors are acceleration, deceleration and braking. Similarly, if you are
building software for e-commerce, you model a real-world shopper as a customer software object
and a real-world shopping cart as a shopping cart software object in your program. A customer’s
state consists of its name, address, age, credit card, and so on. And, a customer’s behaviors include
adding items into the shopping cart and buying items in the shopping cart.

It’s not necessary that you only model real-world objects as software objects. You may model real-
world concepts also as software objects. For instance, if you are building a flight booking software,
you’ll model the concept of booking as a software object. A booking object will have the flight
number, departure date/time, arrival date/time, origin city and destination city, booking amount, and
so on, as its state. And, the behaviors associated with a booking object are confirmation and
cancellation.
As a general rule, objects and concepts found in the problem domain are modeled as software
objects. For instance, if you are developing an e-commerce software, you’ll model software objects
based on objects and concepts found in the e-commerce domain (like, order, customer, product,
catalogue, product category, shopping cart, and so on).
So, how you go about creating objects in Java programming language? A Java class acts as a
blueprint for creating objects in Java. Let’s look at what a Java class is and how it is used for
creating objects.
IMPORTIt is recommended that you import the chapter04 project into your Eclipse IDE. Refer section
1-5 of chapter 1 for the steps required for importing a project into Eclipse IDE.
4-2 Java class – the blueprint for creating objects
A Java class is a template (or blueprint) for creating objects. This means, if you want to create a car
object in Java, you first need to create a Java class that defines attributes (that is, state) and behavior
of cars.
Let’s say you are interested in the following attributes and behaviors of a car:
attributes: color, model, top speed, current acceleration, and current speed
behaviors: acceleration, deceleration and braking
The following listingshows the Car class of chapter04 project that defines above mentioned attributes
and behaviors:
Listing 4-1: Car class defines attributes and behaviors corresponding to cars in the real-world
Project: chapter04
Source location: src\chapter04\Car.java

Java classes that we saw earlier contained only a main method and had no relation to any real-world
object. Car class is different because it represents real-world cars.
The important points to notice about the Car class are:
there is no main method in the Car class
car attributes are defined as variablesin the Car class. The syntax for defining variables is:
private <variable-type> <variable-name>;
here, private is an access modifier (explained in chapter 5), <variable-type> is the type of the
variable, and <variable-name> is the name of the variable
The type of a variable is determined based on the values that are typically assigned to the
attribute. The following table shows attributes of three cars:
Table 4-1 – Typical values of car attributes
Color Model Top Current Current
speed acceleration speed
(km/hr) (m/sec 2) (km/hr)
Red X 200 1.0 50
Green Y 250 1.5 100
Blue Z 230 2.0 75
As 'Color' and 'Model' attributes are specified as string (or textual)values, color (refer line #4 in
listing 4-1) and model (refer line #5 in listing 4-1) variables are defined to be of type String . We’ll
learn more about String type in the next chapter, but for now you can assume that a String type holds
a string (or textual) value.
NOTE Any value within double quotes is treated to be of type String . This means, you can assign
any value within double quotes to a String type variable. For instance, you can assign the value
"Let’s learn String type in chapter 5" to a String type variable.
As 'Top speed' and 'Current speed' attributes are specified as integer values, topSpeed (refer line
#6 in listing 4-1) and currentSpeed (refer line #8 in listing 4-1) variables are defined to be of
type int . The currentAcceleration variable (refer line #7 in listing 4-1) is defined to be of type float
because the corresponding 'Current acceleration' attribute takes floating-point values.
NOTE As thevariables color , model , and so on, of Car class represent attributes of a car, these
variables are commonly referred to as attributes.
a constructor (line #10 to #18 in listing 4-1) is defined in the Car class. A constructor
createsa Car object based on the attribute information supplied to the constructor. The syntax for
defining a constructor is:
public <class-name> (<arg1-type> <arg1-name>, <arg2-type> <arg2-name>, .....) {
//- - do something
}
here, public is an access modifier (explained in chapter 5), <class-name> is the name of the
class, and each <arg-type> <arg-name> pair represents a constructor argument passed to
the constructor. <arg-type>is the type (like int , float , and so on) of the constructor argument,
and <arg-name> is the name of the constructor argument.
You typically pass initial values for the object’s attributes as constructor arguments. The
portionof the constructor enclosed within opening { and closing } braces is referred to as
constructor body. In listing 4-1, Car ’s constructor accepts String theColor , String theModel , and so on,
as constructor arguments.
behaviors of a car are defined as methods in the class. A method represents some action (like
acceleration, deceleration and braking) being taken by the object, which typically results in
changing the state of the object. For instance, if a car’s 'Current speed' is 50 km/hr and it
accelerates at the rate of 1 m/sec2 for 20 seconds, its 'Current speed' changes to 122 km/hr.
The following table shows how behaviors of real-world carsare mapped to methods in the Car
class:
Table 4-2 – Behaviors of carsare defined as methods in the Car class
Behavior Definitionin the Car Purpose
class
acceleration void accelerate(int accelerates the car for the
timeInSeconds) – refer
line time specified
#20 in listing 4-1 by timeInSeconds
deceleration void decelerate(int decelerates the car for the
timeInSeconds)
time specified
– refer line #24 in by timeInSeconds
listing 4-1
Braking void applyBrakes() applies brakes
– refer line #28 in
listing 4-1
For simplicity, the methods defined in the Car class do nothing except writing a message on the
output.
The syntax for defining a method is:
public <return-type> <method-name>(<arg1-type> <arg1-name>, <arg2-type> <arg2-
name>, ...) {
// do something
}
here, <return-type> is the type of value returned by the method, <method-name> is the
name of the method, and each <arg-type> <arg-name> pair represents a method argument
accepted by the method. <arg-type>is the type (like int , float , and so on) of the method
argument, and <arg-name> is the name of the method argument.
If the <return-type> is specified as void , it means that the method doesn’t return anything when called.
The portionof the method enclosed within opening { and closing } braces is referred to as method
body. Listing 4-1 shows that both accelerate and decelerate methods accept int timeInSeconds as a method
argument.
NOTE The main method that we’ve seen so far is nota behavior of an object. The main method is a
specialmethod that is executed when you select Run As Java application option. The args argument of
the main method contains the value(s) that you pass at the time of running the program. Remember that
you won’tget the Run As Java application option if the selected class doesn’t contain a main method.
Now that we’ve seen how to create a Car class, let’s look at how to create Car objects that represent
real-world car objects.
4-3 Creating objects of a class
A class defines attributes and behaviors of objects it creates. For instance, the Car class tells us that
cars have color , model , and so on, attributes and accelerate , decelerate and applyBrakes behaviors. Car class
is used to create real-world car objects with specific color, model, and so on, attributes.
You create an object by calling the class’s constructor. For example, you create a Car object by
calling Car class’s constructor. The following listing shows the CarDemo class whose main
methodcreates a Car object:
Listing 4-2 Creating a Car object
Project: chapter04
Source location: src\chapter04\CarDemo.java
1 package chapter04;
2
3 public class CarDemo {
4 public static void main(String args[]) {
5 Car car = new Car("Red", "X", 200, 1.0f, 50); Car ’s constructor is called using new
6 .....
7 }
8 }
You use the new keyword to call a class’s constructor. In the above program, the expression new
Car("Red", "X", 200, 1.0f, 50) on line #5 calls constructor of the Car class to createa Car object. This means,
the statement Car car = new Car("Red", "X", 200, 1.0f, 50) creates a Car object and assignsthe newly created Car
object to the variablenamed car (of type Car ).
In previous chapters, we saw how primitive type variables are defined. In listing 4-2, we’ve defined
a variable named car whose type is Car . This shows that we can define variables of both primitive
and class types. A class type variable is also called as a reference type variable because it holds
reference to an object.
The following figure shows how the values (referred to as arguments) passed to Car class’s
constructor in listing 4-2 are mapped to constructor arguments definedin the Car class:

Java’s new keyword is used to call the Car class’s constructor. The values passed to Car ’s
Figure 4-2
constructor must match the argument types accepted by the constructor
The above figure shows that the values passed to Car ’s constructor match the types of the constructor
arguments. For instance, theColor argument is String type and its value is specified as string
"Red", theCurrentAcceleration argument is float type and its value is specified as 1.0f , and so on.
When you call the constructor, the constructor body is executed. The following figure shows the result
of execution of Car ’s constructor with values( "Red" , "X" , 200 , 1.0f , 50 ) passed to it:

Figure 4-3 Call to Car ’s constructor results in execution of constructor body


The above figure shows that when Car ’s constructor body is executed, values passed to the
constructor (like "Red", "X", and so on) are assigned to color , model , and so on, attributes. The
attributes are private to an object; that is, each object gets its own private copy of the attributes. This
means, if you create 10 Car objects by calling Car ’s constructor 10 times, each of the 10 Car objects
will have their own private copy of color , model , topSpeed , currentAcceleration and currentSpeed attributes. The
following figure depicts this behavior:

Figure 4-4 Calling Car ’s constructor creates a new Car object and each Car object has its own private
copy of attributes
In the above figure, three Car objects are created by calling the Car ’s constructor three times. Each Car
object has its own private copy of color , model , topSpeed , currentAcceleration and currentSpeed attributes.
In this section, we saw how to create an object from a class, let’s now look at how to call methods of
an object.
4-4 Calling methods of an object
An object performs some action when its methods are called. The syntax for calling an object’s
method is:
<object>.<method-name>(<arg1-value>, <arg2-value>, …..);
here, <object> is the object whose methods you want to call, <method-name> is the name of
the method that you want to call, and <arg1-value>, <arg2-value>, and so on, refer to the
values passed as method arguments.
The following figureshows how CarDemo ’s main method calls accelerate , decelerate and applyBrakes methods
of the car object (refer listing 4-2), and how the values passed in the method call are mapped to
method arguments specified in the method definition:

Figure 4-5 Values passed in the method call map to the method arguments specified in the method
definition.
The above figure shows that value 1 is passed to accelerate and decelerate methods. This value maps
to timeInSeconds method argument defined by accelerate and decelerate methods. The applyBrakes method
doesn’t accept any argument; therefore, no value is passed when applyBrakes method is called.
You should note that the value passed in the method call must match the corresponding method
argument type. For instance, you can’t pass the value "Red"(which is of type String )
to accelerate and decelerate methods. If you pass an incorrect type when calling a method, the Java
compiler will report an error. The following figure shows that Eclipse IDE reports an error when we
pass the value "Red" to the accelerate method:
When we pass the value "Red"(which of type String ) to the accelerate method, the following error is
reported by Eclipse IDE: 'The method accelerate(int) in the type Car is notapplicable for the arguments
( String )'. The message informs that instead of passing a value of type int , you are passing a value of
type String to the accelerate method.
Let’s do some hands-on activities to better understand how objects work.
Hands-on Define a new printAttributes method in Car class
The attributes defined in the class are accessible to all the methods defined in the same class.This
means, color , model , and so on attributes of Car class are accessible to accelerate , decelerate and applyBrakes
methods.
Let’s add a printAttributes method to Car class to print values of attributes:
Listing 4-3 printAttributes method
1 package chapter04;
2
3 public class Car {
4 private String color;
5 private String model;
6 .....
7 public void printAttributes() {
8 System.out.println("color : " + color);
9 System.out.println("model : " + model);
10 .....
11 }
12 }

The printAttributes method simply prints values of color , model , topSpeed , currentAcceleration and currentSpeed
attributes.The printAttributes method doesn’t accept anyargument. As the return type of the method is void ,
it means that the printAttributes method doesn’t return any value.
Now, create three Car objects and call their printAttributes method.
Hands-on Call printAttributes methodof different Car objects
We mentioned earlier that each object gets its own private copy of attributes. This means, if we
call printAttributes method on a particular Car object, it’ll print the attributes of that Car object.
Open the CarDemo class and modify it as shown in the following listing:
Listing 4-4 Printing attributes of different Car objects
1 package chapter04;
2
3 public class CarDemo {
4 public static void main(String args[]) {
5 Car car1 = new Car("Red", "X", 200, 1.0f, 50);
6 Car car2 = new Car("Green", "Y", 250, 1.5f, 100);
7 Car car3 = new Car("Blue", "Z", 230, 2.0f, 75);
8
9 System.out.println("-->> Attributes of car1");
10 car1.printAttributes();
11
12 System.out.println("-->> Attributes of car2");
13 car2.printAttributes();
14
15 System.out.println("-->> Attributes of car3");
16 car3.printAttributes();
17 }
18 }

The above listing shows that CarDemo ’s main method creates three Car objects (with different sets of
attributes) and calls their printAttributes method. car1 , car2 and car3 variables (refer line #5, #6 and #7)
hold referenceto Car objects. If you run CarDemo ’s main method, you’ll see the following output:
-->> Attributes of car1
color : Red
model : X
topSpeed : 200
currentAcceleration : 1.0
currentSpeed : 50
-->> Attributes of car2
color : Green
model : Y
.....

The output shows that each Car object has its own private copy of attributes.
Hands-on Implement accelerate , decelerate and applyBrakes methods
Car class’s accelerate , decelerate
and applyBrakes methods currently don’t do anything interesting. Let’s
modify these methods to perform some action.
accelerate method
If a car accelerates at the rate of x m/sec2 for a time period of t seconds, then the current speed of the
car changes from v to (v + x*t). So, when the Car object’s accelerate method is called,
the currentSpeed attribute of the Car object must be changed from v to v + x*t.
Add the following implementation of accelerate method in the Car class:
Listing 4-5 accelerate method implementation
1 package chapter04;
2
3 public class Car {
4 private float currentAcceleration;
5 private int currentSpeed;
6 .....
7 public void accelerate(int timeInSeconds) {
8 currentSpeed = (int)(currentSpeed + 3.6 * currentAcceleration * timeInSeconds);
9 }
10 }
The body of accelerate method contains a single statement:
currentSpeed = (int)(currentSpeed + 3.6 * currentAcceleration * timeInSeconds);

NOTE The unit of currentSpeed is considered in km/hr. As we’ve considered currentAcceleration in


m/sec2and timeInSeconds in seconds, the unit of currentAcceleration * timeInSeconds is m/sec. As 1 m/sec is
equal to 3.6 km/hr, we multiply the result of currentAcceleration * timeInSeconds with 3.6 before adding the
result to currentSpeed variable.
When operands of a binary arithmetic operator (like, + and * ) are of different types, automatic
widening conversion of smaller type to larger type is performed. As literal 3.6 is of type double ,
eventually all variables in the expression end up being converted to double . This makes the expression
( currentSpeed + 3.6 * currentAcceleration * timeInSeconds ) to be of type double . As assigning a double type to an int
type is a narrowing conversion, we’ve explicitly converted the result of expression ( currentSpeed + 3.6 *
currentAcceleration * timeInSeconds )to int so that it can be assigned to currentSpeed variable of type int .

decelerate method
If a car decelerates at the rate of x m/sec2 for a time period of t seconds, then the current speed of the
car changes from v to v - x*t. So, when the Car object’s decelerate method is called,
the currentSpeed attribute of the Car object must be changed from v to v - x*t.
Add the following implementation of decelerate method in the Car class:
Listing 4-6 decelerate method implementation
1 package chapter04;
2
3 public class Car {
4 private float currentAcceleration;
5 private int currentSpeed;
6 .....
7 public void decelerate(int timeInSeconds) {
8 currentSpeed = (int)(currentSpeed – 3.6 * currentAcceleration * timeInSeconds);
9 }
10 }

When the decelerate method is called, the currentAcceleration attribute is treated as the current rate of
deceleration of the car.
applyBrakes method
The applyBrakes method decelerates the car until the current speed comes to 0 .For this reason,
the applyBrakes method simply sets the value of currentSpeed attribute to 0 .
Listing 4-7 applyBrakes method implementation
1 package chapter04;
2
3 public class Car {
4 private float currentAcceleration;
5 private int currentSpeed;
6 .....
7 public void applyBrakes() {
8 currentSpeed = 0;
9 }
10 }
Now that we have provided implementations for accelerate , decelerate and applyBrakes methods, let’s look
at what happens when we call these methods.
Hands-on Call accelerate , decelerate and applyBrakes methods
As shown in the following listing, modify the CarDemo class to call
the accelerate , decelerate and applyBrakes methods:
Listing 4-8 Calling different methods of Car object
1 package chapter04;
2
3 public class CarDemo {
4 public static void main(String args[]) {
5 Car car = new Car("Red", "X", 200, 1.0f, 50);
6
7 System.out.println("-->> Initial values of attributes");
8 car.printAttributes();
9
10 car.accelerate(5);
11 System.out.println("-->> After accelerate method");
12 car.printAttributes();
13
14 car.decelerate(2);
15 System.out.println("-->> After decelerate method");
16 car.printAttributes();
17
18 car.applyBrakes();
19 System.out.println(" > After applyBrakes method");
20 car.printAttributes();
21 }
22 }
In the above listing, the printAttributes method is called to show that the currentSpeed attribute of
the Car object changes after each method call.We’ve passed 5 as argument to the accelerate method (line
#10), 2 as argument to decelerate method (line #14), and noargument is passed to the applyBrakes method
(line #18).
If you run CarDemo ’s main method, you’ll get the following output:
-->> Initial values of attributes
currentSpeed : 50
-->> After accelerate method
currentSpeed : 68
-->> After decelerate method
currentSpeed : 60
-->> After applyBrakes method
currentSpeed : 0
The above output suggests that the currentSpeed changes as we call methods on the Car object.For
brevity, attributes other than currentSpeed have not been shown in the above output.
So far in this chapter we’ve seen how attributes, constructors and methods are defined in a class.
We’ve also seen how to call constructor to create an object, and how to call methods of an object.
Let’s now take an in-depth look at attributes, constructors and methods.
4-5 Attributes
In this section, we’ll look at:
setting initial value of an attribute
instance vs local vs class variables
default values of attributes

Setting initial value (or default value) of an attribute


We mentioned earlier that the syntax for defining an attribute is:
private <variable-type> <variable-name>;

As in the case of variables defined inside the main method, you may initialize an attribute with a
constant value:
private String color = "RED";
If you specify an initial value for an attribute in the class, then all the objects created will have the
same value. For instance, if you want to create only red colored Car objects, set the color attribute to
"RED"in the Car class, as shown above. As we want all Car objects to have their color attribute’s value
"RED", change the Car class’s constructor such that it doesn’t accept the value for color attribute:
Listing 4-9 Car class with initial value of color attribute as "RED"
1 package chapter04;
2
3 public class Car {
4 private String color = "RED";
5 private String model;
6 .....
7 public Car(String theModel, int theTopSpeed,
8 float theCurrentAcceleration, int theCurrentSpeed) {
9 model = theModel;
10 topSpeed = theTopSpeed;
11 currentAcceleration = theCurrentAcceleration;
12 currentSpeed = theCurrentSpeed;
13 }
14 .....
15 }
In the above listing, Car ’s constructor doesn’t accept value for the color attribute, which means all
the Car objects by default have their color attributes set to "RED". This means, the above Car class can
only be used to represent red-colored cars.

Instance vs local vs class variables


An object is referred to as an instance of the class. The attributes defined in the class are referred to
as instance variables because each object gets its own private copy of these attributes. A local
variable is a variable that is defined inside a method or a constructor. A class variable (also referred
to as static variable) is an attribute that has static keyword in its declaration. A class variable is
shared between objects, that is, each object doesn’t get its own private copy of a class variable.
NOTE In this book, we’ll use the terms object and instance interchangeably.
Listing 4-10 shows the Dog class of chapter04 project that represents real-world dogs. In the listing:
name(line #4) and distance (line #5) are instance variables.The name represents the name of the
dog, and the distance represents the total distance travelled by the dog.
sound variabledeclaration (line #6) contains the static keyword, which means that it’s a class
variable.The sound variable represents the barking sound of the dog. The initial value of sound
is set to "Woof-woof".
Listing 4-10 Instance, class and local variables
Project: chapter04
Source location: src\chapter04\Dog.java

(line #18) is defined inside the run method, which means it’s a local
distanceTravelled variable
variable. A local variable is private to the method or constructor in which it is defined, that
is, it’s not accessible outside the method or the constructor.
theName(line #8) and theDistance (line #8) are constructor arguments. Constructor arguments
are private to the constructor; they are not accessible outside the constructor.
time (line #17) and theSound (line #23) are method arguments. Method arguments are private
to the method; they are not accessible outside the method.
the bark method represents barking behavior of dogs. This method prints the dog’s name and
its barking sound.
the run method represents the running behavior of dogs. This method assumes that a dog runs
at the speed of 0.5 m/s. The method accepts time argument, which is the time for which the
dog runs.The run method updates the distance instance variable to reflect the total distance
travelled by the dog, and also prints the name of the dog and the total distance travelled.
the setBarkingSound method accepts theSound argument that represents the barking sound. This
method assigns the value of theSound argumentto the sound class variable.
NOTEThe setBarkingSound is not a behavior of a real-world dog; you don’t tell a dog to make a
particular barking sound. In object-oriented programming, it is common to write such methods to
change values of instance or class variables after the object is created.
Notice that in listing 4-10 System.out.println statements (refer line #14 and #20) concatenate multiple
strings and variables using + operator. This saves the effort to write multiple System.out.println
statements.
The following listing shows the DogDemo class of chapter04 project that demonstrates class variables
are shared between objects:
Listing 4-11 DogDemo class
Project: chapter04
Source location: src\chapter04\DogDemo.java
1 package chapter04;
2
3 public class DogDemo {
4 public static void main(String args[]) {
5 Dog dogA = new Dog("Max", 100);
6 Dog dogB = new Dog("Buddy", 200);
7
8 dogA.bark();
9 dogB.bark();
10
11 dogB.setBarkingSound("Bow-wow");
12 dogB.bark();
13 dogA.bark();
14 dogB.run(5);
15 dogA.run(5);
16 }
17 }

DogDemo ’s main method creates two instances of Dog class – dogA and dogB . The dogA ’s name is "Max"
and has travelled a distance of 100 meters, and dogB ’s name is "Buddy" and has travelled a distance
of 200 meters. As the initial value of sound attribute is set to "Woof-woof", both dogA and dogB objects
havethe same value of sound attribute. This means callsto bark method on dogA and dogB objects (refer
line #8 and #9) prints the same barking sound "Woof-woof". On line #11, we change the barking
sound of dogB to "Bow-wow" by calling the setBarkingSound method.You’d now expect that dogB ’s sound
attribute is changed to "Bow-wow", and dogA ’s sound attribute remains "Woof-woof". But, if you
run DogDemo ’s main method, you’ll see the following output:
Dog named 'Max' is making sound 'Woof-woof'
Dog named 'Buddy' is making sound 'Woof-woof'
Dog named 'Buddy' is making sound 'Bow-wow'
Dog named 'Max' is making sound 'Bow-wow'
Dog named 'Buddy' has travelled distance '202.5'
Dog named 'Max' has travelled distance '102.5'
The output shows that after sound attribute of dogB was set to "Bow-wow", call to bark method of dogB
prints "Bow-wow"(which was expected) and call to bark method of dogA also prints "Bow-wow" (this
was not expected because we didn’t change the barking soundof dogA object).So, how
come sound attribute of dogA got changed when we changed dogB ’s sound attribute? This happened
because sound attribute is a class variable; therefore, it is shared between objects of Dog class.
When the run method is called on dogA and dogB objects, their distance attribute is updated. As distance
attribute is an instance variable, the output shows that the change in distance attribute of dogA doesn’t
affectthe distance attribute of dogB .

Default values of attributes


If you don’t set an initial value of an instance or class variable, a default value is automatically
assigned by Java when the object is created.
The following listing shows the Employee class of chapter04 project that represents an employee in an
organization:
Listing 4-12 Employee class
Project: chapter04
Source location: src\chapter04\Employee.java
1 package chapter04;
2
3 public class Employee {
4 private String id;
5 private String name;
6 private String address;
7 private float salary;
8 private boolean isMarried;
9 private int age;
10 private char gender;
11 private Dog dog;
12
13 public Employee(String theId, String theName) {
14 id = theId;
15 name = theName;
16 }
17
18 public void performTask() {
19 System.out.println("Performing task");
20 }
21
22 public void printAttributes() {
23 System.out.println("Employee [id=" + id + ", name=" + name
24 + ", address=" + address + ", salary="
25 + salary + ", isMarried=" + isMarried + ", age=" + age + ", gender=" + gender + ", dog="
26 + dog + "]");
27 }
28 }
Employee class defines multiple attributes but the constructor (line #13) sets values of only id and name
attributes. The rest of the attributes are not assigned any value.The dog attribute indicates the dog (if
any) owned by the employee. Employee ’s printAttributes method prints values of all the attributes. If we
call the printAttributes of an Employee object, we’ll know the default values assigned
to address , salary , isMarried , age , gender and dog attributes.
NOTE Listing 4-12 shows that you can define a class type (like Dog ) as an attribute of another
class(like Employee ). In fact, the String type that we’ve been using all along is a class provided by Java
for holding textual values. String is different from other classes in the sense thatyou don’t need to
create a String object by calling String class’s constructor. When you assign a value in double quotes to
a String type variable, a String object is created behind the scenes and assigned to the variable. You
should note that the class types (like Employee , Dog , String , and so on) can also appear as method
arguments and constructor arguments.
The following listing shows EmployeeDemo class whose main method creates an instance of Employee and
calls its printAttributes method:
Listing 4-13 EmployeeDemo class
Project: chapter04
Source location: src\chapter04\EmployeeDemo.java
1 package chapter04;
2
3 public class EmployeeDemo {
4 public static void main(String args[]) {
5 Employee employee = new Employee("123", "John");
6 employee.printAttributes();
7 }
8 }

If you run EmployeeDemo ’s main method, you’ll get the following output:
Employee [id=123, name=John, address=null, salary=0.0, isMarried=false, age=0, gender= , dog=null]

The output shows that the value of address (of type String ) and dog (of type Dog ) are printed
as null , salary (of type float ) as 0.0 , age (of type int ) as 0 , isMarried (of type boolean ) as false , gender (of
type char ) as empty.
NOTE The above output shows that variables of class types(like, String and Dog ) are set to null (a Java
reserved word) if you don’t assign them any object.The default value of char type is the unicode
character ‘\u0000’ , which represents a null character in Unicode. You should note that the null value
assigned to class types and the null characterassigned to char types are not the same.
No default values for local variables
Unlike instance and class variables, local variables are not assigned any default value by Java. The
following figure shows the LocalVariables class of chapter04 project whose main method defines age (of
type int ), gender (of type char ) and dog (of type Dog ) local variables:

Figure 4-7 age , dog and gender local variables are used without assigning any initial value
In the above figure, local variables are not assigned any initial value. As Java doesn’t assign default
values to local variables, Java compiler complains that you are using the variables without assigning
them any value. For instance, if you hover your mouse over x symbol corresponding to dog.bark() call,
it’ll show you the following error message 'The local variable dog may not have been initialized'. To
address this issue, explicitly assign values to all the local variables.
The following table summarizes the default values assigned to variables of primitive and class types:
Table 4-3 – Default values of variables of primitive and class types
Type Default value
byte, short, 0
int
long 0L

float 0.0F

double 0.0

char ‘\u0000’

boolean false

class type null

Let’s now take an in-depth look at constructors.


4-6 Constructors
In this section, we’ll look at:
how to define multiple constructors in a class
the default constructor of a class

Defining multiple constructors in a class


The classes ( Car , Dog and Employee ) that we’ve seen so far, there was only one constructor defined in
the class. You can define multiple constructors in a class to provide different ways for creating an
object of that class.
The following listing shows the Fish classof chapter04 project that defines two constructors:
Listing 4-14 Fish class
Project: chapter04
Source location: src\chapter04\Fish.java
1 package chapter04;
2
3 public class Fish {
4 private String name;
5 private String classification;
6
7 public Fish(String theName) {
8 name = theName;
9 }
10
11 public Fish(String theName, String theClassification) {
12 name = theName;
13 classification = theClassification;
14 }
15
16 public void swim() {
17 System.out.println("I'm swimming");
18 }
19
20 public void printAttributes() {
21 System.out.println("name : " + name + ", classification : " + classification);
22 }
23 }

Fish class defines two attributes– name and classification . The name attribute specifies the name of the fish
(likeSwordfish, Stingray, and so on), and the classification attribute specifies the classification (like
Actinopterygii, Chondrichthyes, and so on) to which the fish belongs. The first constructor (line
#7)accepts theName argument, which is assigned to the name attribute. The second constructor (line
#11) accepts theName and theClassification as arguments, which are assigned to name and classification
attributes, respectively.The printAttributes method (line #20) prints the attributes of the Fish object.
So, what’s the need for defining multiple constructors? As mentioned earlier, you typically pass
initial values for the object’s attributes as constructor arguments. We define multiple constructors only
if we consider some of the attributes as optional for creating an object.For instance, we want to
create a Fish object even if we don’t know the classification of the fish. In such cases, the first
constructor (line #7) is used to create a Fish object. The second constructor (line #11) is used to
create a Fish object when we know both name and classification of the fish.
The following listing shows the FishDemo class that creates Fish objects by calling different
constructors:
Listing 4-15 FishDemo class– create Fish objects by calling different constructors
Project: chapter04
Source location: src\chapter04\FishDemo.java
1 package chapter04;
2
3 public class FishDemo {
4 public static void main(String args[]) {
5 Fish fish1 = new Fish("Swordfish");
6 Fish fish2 = new Fish("Stingray", "Chondrichthyes");
7
8 fish1.printAttributes();
9 fish2.printAttributes();
10 }
11 }

FishDemo ’s main method calls Fish(String theName) and Fish(String theName, String theClassification) constructors to
create two Fish objects.If you run FishDemo ’s main method, you’ll get the following output:
name : Swordfish, classification : null
name : Stingray, classification : Chondrichthyes

As classification attribute’s value is notset when Fish(String theName) constructor is called, null (the default
value for class types) is assigned to the classification attribute.
Even if you don’t know the classification, you can still call Fish(String theName, String
theClassification) constructor by using null as the value for theClassification argument:
Fish fish2 = new Fish("Stingray", null);

The above constructor call results in setting the value of classification attribute of Fish object to null , which
is same as calling Fish(String theName) constructor.
NOTE You should define multiple constructors of a class only if you expect that each constructor
will create a legitimate object of the class. For instance, if all the fishes must have a name and
classification, then there is no point in defining a Fish(String theName) constructor that only allows you to
create a Fish object which has name but no classification.
Let’s now look at how you can create objects of a class without explicitly defining a constructor.

Default constructor of a class


Each Java class has an implicitly defined default constructor which doesn’t accept any argument and
does nothing. This default no-argument constructor disappears as soon as you explicitly define a
constructor that accepts one or more arguments. As the default constructor doesn’t accept any
argument, you set the attributes of the object by calling methods of the class.
Let’s modify Fish and FishDemo classes to understand usage of default constructors.
Hands-on Use thedefault constructor to create Fish objects
Open the Fish class of chapter04 project, and do the following:
remove constructors
add setName and setClassification methodsfor setting name and classification attributes, respectively.
The following listing shows the modified Fish class:
Listing 4-16 Fish class – without a constructor
1 package chapter04;
2
3 public class Fish {
4 private String name;
5 private String classification;
6
7 public void setName(String theName) {
8 name = theName;
9 }
10 public void setClassification(String theClassification) {
11 classification = theClassification;
12 }
13
14 public void swim() {
15 System.out.println("I'm swimming");
16 }
17
18 public void printAttributes() {
19 System.out.println("name : " + name + ", classification : " + classification);
20 }
21 }

The Fish class no longer defines a constructor. You can still create an instance of Fish by using the
default no-argument constructor which is implicitly defined in a Java class. You can think of that
default constructor to be like this:
public Fish() { }
The constructor doesn’t accept any argument and its body is empty (that is, it does nothing).
Now, change the FishDemo class as shown in the following listing:
Listing 4-17 FishDemo class – creating Fish objects using the default constructor
1 package chapter04;
2
3 public class FishDemo {
4 public static void main(String args[]) {
5 Fish fish1 = new Fish();
6 fish1.setName("Swordfish");
7
8 Fish fish2 = new Fish();
9 fish2.setName("Stingray");
10 fish2.setClassification("Chondrichthyes");
11
12 fish1.printAttributes();
13 fish2.printAttributes();
14 }
15 }
FishDemo calls the default constructor (line #5 and #8) of Fish class to create instances
of Fish .The setName and setClassification methods of Fish class are used to set name and classification attributes
of the Fish object.If you run the FishDemo ’s main method, you’ll get the following output:
name : Swordfish, classification : null
name : Stingray, classification : Chondrichthyes
If you now add a constructor to the Fish class that accepts one or more arguments, the default no-
argument becomes unavailable. The following listing shows the modified Fish class that defines a
constructor that accepts name of the fish as argument:
Listing 4-18 Fish class – with a constructor that accepts an argument
1 package chapter04;
2
3 public class Fish {
4 private String name;
5 private String classification;
6
7 public Fish(String theName) {
8 name = theName;
9 }
10 .....
As we’ve added Fish(String theName) constructor, the default no-argument constructor is no longer
available. If you now open the FishDemo class in Eclipse IDE, you’ll see that Eclipse complains 'The
constructor Fish() is undefined':

Figure 4-8 Eclipse IDE complains that the Fish() constructor is notavailable in the Fish class
You can address this problemby explicitly defining a no-argument constructor in the Fish class. It is
quite common to define a no-argument constructor along with constructors that accept one or more
arguments.
Let’s now look at how you can change the behavior of the default constructor.
Changing the behavior of default constructor
As the default constructor has an empty body, no action is performed when it is called. To perform
some action when the default constructor is called, explicitly define a no-argument constructor in the
class. For instance, the following listing shows the Frog class which defines a no-argument
constructor that prints the message 'Frog's constructor called':
Listing 4-19 Frog class – explicitly defining a no-argument constructor
1 public class Frog {
2 private String name;
3
4 public Frog() {
5 System.out.println("Frog's constructor called");
6 }
7
8 public void setName(String theName) {
9 name = theName;
10 }
11
12 public void jump() {
13 System.out.println("I’m jumping");
14 }
15 }

As the Frog class has explicitly defined a no-argument constructor, it is treated as the default
constructor.
Let’s now take an in-depth look at methods.
4-6 Methods
Methods are similar to constructors in the sense that they accept 0 or more arguments. Unlike
constructors, methods can have arbitrary names and can return primitive or class type. So far in this
book we’ve seen methods that return void (that is, the method doesn’t return anything). In this section,
we’ll look at methods that return either a primitive or class type.
Listing 4-20shows the Calculator class of chapter04 project that represents an
arithmeticcalculator. Calculator class defines add , subtract and multiply methods that perform addition,
subtraction and multiplication of numbers, respectively. The return statement in a method specifies the
value returned by the method. For instance,the return statement in multiply method returns
the memory instance variable (of long type) that holds the result of multiplication. The typeof value
returned by the method must also be specified as part of the method definition. For instance, multiply
method’sreturn type is specified as long because it returns the memory instance variable of type long .
NOTE If a return statement is not followed by any primitive or class type variable, then it means that
the method doesn’t return anything (that is, its return type is void ). If a method returns void , we
typically don’t specify the return statement.
Listing 4-21shows the Order class of chapter04 project that defines methods that return an
object. Order class represents orders placed on an e-commerce website. The item1 and item2 attributes
are of type Item (a class type) and represent the items in an order. The getItem1 and getItem2 methods
return item1 and item2 attributes, respectively. As the getItem1 and getItem2 methods return an object of
type Item , the return type of these methods isspecified as Item .
Listing 4-20 Calculator class
Project: chapter04
Source location: src\chapter04\Calculator.java

Listing 4-21 Order class


Project: chapter04
Source location: src\chapter04\Order.java
The following listing shows the MethodTest class of chapter04 project that creates Order and Calculator
objects and calls their methods:

Listing 4-22 MethodTest class – calling methods that return simple values or objects
Project: chapter04
Source location: src\chapter04\MethodTest.java

On line #5 and #6, Item objects are created by passing description and price of items to Item class’s
constructor. On line #7, an Order object is created by passing Item objects (created on line #5 and
#6)to Order ’s constructor. On line #9, call to order.getItem1 method returns an object of type Item . We then
call the getItemDescription method of the Item object to get item’s description.Similarly, on line #10, we
call the getPrice method of the Item object to get item’s price.This shows that you don’t need to store
the Item object returned by the getItem1 method call into an Item type variable before calling the Item
object’s getItemDescription or getPrice method.
NOTE In the context of MethodTest class, main method is a calling method (that is, the method from
which calls are made), and getItem1 , getItemDescription , add , multiply , and so on, are called methods (that
is, the methods which are calledfrom the main method).
If you run MethodTest ’s main method, you’ll get the following output:
item1 description : Item One
item1 price : 100
add(1,2) : 3
multiply(3,2) : 6
Let’s now look at how the return statement influences the program flow.

return statement and program flow


When the return statement is encountered, the method execution stops and the program control returns
to the calling method and the returned value (which could be primitive type or object) becomes
available to the calling method.
NOTEA method whose return type is void typically doesn’t specify a return statement. In such cases, it’s
implied that the return statement is the last statement in the method body.
Let’s consider the following statement of MethodTest ’s main method:
System.out.println("item1 description : " + order.getItem1().getItemDescription());

The following figure summarizes how the expression order.getItem1().getItemDescription() is evaluated:

The numbered balls specify the orderin which the expression order.getItem1().getItemDescription() is
evaluated. At ❶, the getItem1 method of order object (of type Order ) is called that returns item1 (of
type Item ) object. At ❸, getItemDescription method of item1 is called that returns itemDescription (of
type String ). This means, the result of expression order.getItem1().getItemDescription() is of type String .The
returned String is then appended to "item1 description : "text and written out by System.out.println
statement.
Multiple return statements in a method
It is possible that a method contains more than one return statement. For instance, listing 4-23
shows isOrderValueAcceptable method of Order class that uses two return statements.
The isOrderValueAcceptable returns true if the order is acceptable, else false . An order is considered
acceptable if the order amount is more than 500 . The order amount is calculated by summing the
prices of individual items (line #8). If the value of totalPrice variable is less than or equal to 500 , false is
returned, else true is returned. We’ve used the return statement to stop the control flow and return the
control back to the calling method. Once the control returns to the calling method, the execution of the
calling method continues.
Listing 4-23 Order class – multiple return statements
Project: chapter04
Source location: src\chapter04\Order.java

The following listing shows the MultipleReturnTest class of chapter04 project that
calls Order ’s isOrderValueAcceptable method:
Listing 4-24 MultipleReturnTest class
Project: chapter04
Source location: src\chapter04\MultipleReturnTest.java
1 package chapter04;
2
3 public class MultipleReturnTest {
4 public static void main(String args[]) {
5 Item item1 = new Item("Item One", 400);
6 Item item2 = new Item("Item Two", 200);
7
8 Order order = new Order(item1, item2);
9 boolean isAcceptable = order.isOrderValueAcceptable();
10 System.out.println("isOrderValueAcceptable : " + isAcceptable);
11
12 if(isAcceptable) {
13 System.out.println("This order will be processed");
14 } else {
15 System.out.println("This order will NOT be processed");
16 }
17 }
18 }
At first, we create two Item objects- one with price 400 and another with price 200 .We then create
an Order object (line #8) by passing Item objects to Order ’s constructor.On line #9, Order
object’s isOrderValueAcceptable method is called and the returned value is stored in isAcceptable
variable.As the isOrderValueAcceptable method returns a boolean type value, the isAcceptable is defined as a
boolean type variable.If the isAcceptable valueis true , the message 'This order will be processed' is
written, else the message 'This order will NOT be processed' is printed.
If you run MultipleReturnTest ’s main method, you’ll get the following output:
isOrderValueAcceptable : true
This order will be processed
The output shows that after the isOrderValueAcceptable method call returns (line #9), the statements
following the isOrderValueAcceptable method call are executed.
Let’s make changes to isOrderValueAcceptable method by adding statements after the return statement.
Hands-on Adding statements after the return statement
If you add statements afterthe return statement, it’ll result in compilation error. To verify this behavior,
open Order class of chapter04 project in Eclipse IDE and add System.out.println statements as shown in the
following figure.

Figure 4-10 Statements afterthe return statement are unreachable. The last statement of the method is
also unreachable.
The Eclipse IDE complains that all the System.out.println statements in the isOrderValueAcceptable are
unreachable. The first two System.out.println statements are not reachable because the program execution
stops when the return statement is encountered. The third System.out.println is not reachablebecause
both if and else blocks of the if-else statement contain the return statement. So, irrespective of whether the
condition totalPrice <= 500 evaluates to true or false , the statements following the if-else statement will
neverbe executed. If you remove return statement from either if or else block, then there will be
situations in which the statements following the if-else statement are executed.
QUIZ
4-1: Which of the following statements are true?
a) an object has state and behavior
b) a class acts as a blueprint for creating objects
c) an object’s state is represented by methods of the class
d) an object’s behavior is represented by attributes of the class
4-2: Consider the following Airplane class that represents real-world airplanes:
1 public class Airplane {
2 private float speed;
3 private float distanceCovered;
4
5 public Airplane(int speed1) {
6 speed = speed1;
7 }
8
9 public void fly(int time) {
10 distanceCovered = distanceCovered + speed*time;
11 }
12 }

Which of the following statements are true about the above Airplane class?
a) Airplane class defines a constructor that accepts an int type argument
b) The fly method represents a behavior of the Airplane
c) The return type of fly method is float
d) The speed and distanceCovered variables represent the state of an Airplane object
e) The return type of Airplane ’s constructor is void
4-3 : Which of the following methods are correctly defined?
a) public void doSomething { ... }
b) public doSomething() { … }
c) public float doSomething { ... }
d) public void doSomething(float f) { ... }
4-4 : Which of the following constructors are correctly defined?
a) public void MyClass{ ... }
b) public MyClass() { … }
c) public float MyClass{ ... }
d) public void MyClass(float f) { ... }
4-5 : Consider the following Airplane class that represents real-world airplanes:
1 public class Airplane {
2 private float speed;
3 private float distanceCovered;
4
5 public Airplane(int speed1) {
6 speed = speed1;
7 }
8
9 public void fly(int time) {
10 distanceCovered = distanceCovered + speed*time;
11 }
12 }

Which of the following statements represent the correct way to create an Airplane object?
a) Airplane myAirplane = Airplane(100);
b) Airplane myAirplane = new Airplane();
c) Airplane myAirplane = new Airplane(100);
4-6 : Consider the following Airplane class that represents real-world airplanes:
1 public class Airplane {
2 private float speed;
3 private float distanceCovered;
4
5 public Airplane(int speed1) {
6 speed = speed1;
7 }
8
9 public void fly(int time) {
10 distanceCovered = distanceCovered + speed*time;
11 }
12
13 public float getDistanceCovered() {
14 return distanceCovered;
15 }
16 }

What would be the output from executing the following main method?
1 public static void main(String args[]) {
2 Airplane airplane1 = new Airplane(100);
3 airplane1.fly(10);
4
5 Airplane airplane2 = new Airplane(50);
6 airplane2.fly(10);
7
8 System.out.println("airplane1's distanceCovered is: " + airplane1.getDistanceCovered());
9 System.out.println("airplane2's distanceCovered is: " + airplane2.getDistanceCovered());
10 }

4-7 : Which of the statements are true about different types of variables in Java?
a) instance variables are accessible to all the methods of the class
b) local variables are defined inside a method or constructor
c) if local variables are not set by the constructor, they are set to their default values when
the object is created
d) if instance variables are not set by the constructor, they are set to their default values
when the object is created
e) class variables are defined using the static keyword
f) instance variables are shared between objects of the class
g) class variables are private to an object, that is, they are not shared between objects of the
class
h) if a boolean type instance variable’s value is not set by the constructor, its value is set
to false when the object is created

4-8 : Consider the following Airplane class that represents real-world airplanes:
1 public class Airplane {
2 private float speed;
3 private float distanceCovered;
4
5 public Airplane(int speed1) {
6 speed = speed1;
7 }
8
9 public Airplane(int speed1, float distanceCovered1) {
10 speed = speed1;
11 distanceCovered = distanceCovered1;
12 }
13 }

Which of the following statements are correct about the Airplane class?
a) Airplane airplane = new Airplane(); – this statement creates an Airplane object
whose speed is 0.0 and distanceCovered is 0.0 .
b) Airplane airplane = new Airplane(100); - thisstatement creates an Airplane object
whose speed is 100.0 and distanceCovered is 0.0 .
c) Airplane airplane = new Airplane(100, 10); - thisstatement creates an Airplane object
whose speed is 100.0 and distanceCovered is 10.0 .
4-9 : Consider the following Airplane class that represents real-world airplanes:
1 public class Airplane {
2 private float speed;
3 private float distanceCovered;
4
5 public Airplane(int speed1) {
6 speed = speed1;
7 }
8
9 public boolean canFly() {
10 if(distanceCovered <= 2000) {
11 return true;
12 }
13 return false;
14 }
15
16 public void fly(int time) {
17 distanceCovered = distanceCovered + speed*time;
18 }
19
20 public float getDistanceCovered() {
21 return distanceCovered;
22 }
23 }

What would be the output from running the following main method?
1 public static void main(String args[]) {
2 Airplane airplane = new Airplane(100);
3
4 while (airplane.canFly()) {
5 airplane.fly(10);
6 System.out.println("Distance covered : " + airplane.getDistanceCovered());
7 }
8 }
4-7 Summary
In this chapter, we looked at the fundamentals of object-oriented programming. We saw:
classes act as blueprints for creating objects
classes define attributes and behaviors of objects they represent
objects are created using constructors
attributes of objects are set via constructors or methods
methods are called to perform action on the object, which may result in modifying one or
more attributes of the object
return statement is used to return simple values or objects from a method
These are foundational concepts in Java which we’ll be using extensively in the rest of this book.
Chapter 5 – Packages, access modifiers, static
and this keywords
5-1 Introduction
In chapter 1, we saw that when you create a project in Eclipse IDE, a package with the same name as
the project is automatically created. A package is simply a sub-folder inside the project folder. In this
chapter, we’ll look at how Java packages are used for organizing classes that form your project.
All the classes, attributes, methods and constructors that we’ve seen so far had public or private keyword
as part of their definitions. These are called access modifiers – they determine availability of a class,
attribute, method or constructor to other classes in the project. In this chapter, we’ll take an in-depth
look at the different access modifiers provided by Java.
In chapter 4, we saw that class variables (also referred to as static variables) are attributes that are
defined using the static keyword. Unlike instance variables (also referred to as non-static variables),
class variables are shared between objects. In this chapter, we’ll take a closer look at the use of static
and this keywords.
We’ll wrap this chapter up by looking at ‘pass by value’ approach that is followed by Java when
passing arguments to methods and constructors.
Let’s begin this chapter by looking at packages.
5-2 Packages
Java packages serve the following purpose:
help organize classes in the project
allow you to define multiple classes with the same name
allow you to control access to classes, constructors, methods, and attributes
In this section, we’ll only look at how packages are used to organize classes and how they help define
multiple classes with the same name in the project. In section 5-3, we’ll look at how packages can
play a role in controlling access to classes, constructors, methods and attributes.
Before we delve into the above mentioned features, let’s look at how packages are created using
Eclipse IDE.

Creating a package
In the Eclipse IDE, select File New Java Project option or right-click in the Package Explorer tab and
select New Java Project option to create a new Java project named chapter05 . This will create a chapter05
sub-folder inside the folder that you have chosen as the Eclipse workspace. If you’ve chosen C:\java-
samples folder as the workspace, then this will create a sub-folder named chapter05 inside C:\java-samples
folder. By default a src sub-folder is also created inside chapter05 folder to contain .java source files of
the project.
To create a package inside a project, select the project and choose File New Package or right-click
the project in the Package Explorer tab and choose New Package . This opens up the dialog box for
creating a new package, as shown in the following figure:

Figure 5-1 Specify the package name in the Name field and click Finish to create a new package
field specifies the folder that contains the .java files of the project. By default, this field’s
Source folder
value is <project-name> /src . As we are creating a package inside chapter05 project, this field is pre-
populated with value chapter05/src . Specify com.sample.javabook as the package name in the field
labeled Name and click the Finish button. This will create a package named com.sample.javabook in chapter05
project, as shown in the following figure:
Figure 5-2 The newly created package com.sample.javabook is shown in the Package Explorer tab
When you create the com.sample.javabook package, it results in creation of com/sample/javabook sub-folder
inside chapter05/src folder.This means, if we create a .java file inside com.sample.javabook package, then it’ll
be located in C:\java-samples\chapter05\src\com\sample\javabook folder.
If you don’t remember the location of your workspace (or the project), simply right-click on the
project and choose Properties option. You’ll see the dialog box shown in figure 5-3. Select the Resource
option from the left pane to view the location of the project on the file system.
NOTE You can also select a package and choose Properties option to view the folder corresponding to
that package.

Figure 5-3 Resource option allows you to view the location of the project or package on the file
system.
The following naming conventions are typically followed when creating packages:
package names are always in lowercase
package names begin with the domain name (in reverse) of the company. For instance, a Java
programmerworking at mywebsite.com will create a package name beginning with com.mywebsite .
NOTE Each part of the package name must follow the Java variable naming convention. For
instance, you cannot create packagesnamed com.static.myprogram and com.123.myprogram because static is a
keyword and 123 is not a valid Java variable name.
IMPORTIt is recommended that you import the ecommerce project into your Eclipse IDE. This project
has the same structure and classes as shown in figure 5-4.
The first statement in the class is the package statement that specifies the name of the package. The
following listing shows the Customer class of ecommerce project:
Listing 5-1 package statement
Project: ecommerce
Source location: src\com\mywebsite\customer\Customer.java
1 package com.mywebsite.customer;
2 .....
3 public class Customer {
4 .....
5 }

As the Customer class is contained in com.mywebsite.customer package, the package statement specifies the
same. You should note that aclass can have only one package statement.
Let’s now look at how packages help organize classes in a project.

Organizing classes in a project


So far in this book we’ve seen projects in which there was only a single package and all the classes
were created in that package. To organize classes in a project, you’ll typically create multiple
packages to group together closely related classes.
Let’s say that you are developing an e-commerce website which sells a wide variety of products. You
can create different packages to organize classes based on different concepts or objects (like
catalogue, order, customer, and so on) that constitute an e-commerce website. The following figure
shows the structure of the ecommerce project that contains classes for the e-commerce website:

Figure 5-4 Structure of ecommerce project


The above figure shows that we’ve created packages like com.mywebsite.catalogue , com.mywebsite.customer ,
and so on, to organize classes. The name of a package typically specifies the functionality provided
by the classes contained in that package. This convention for naming packages simplifies maintenance
of Java applications. For instance, if you want to make changes to the catalogue functionality of the
website, you can quickly figure out from figure 5-4 that such changes will go into the classes
contained in com.mywebsite.catalogue folder.
The following table describes packages and classes of the ecommerce project:
Table 5-1 – Packages and classes of the ecommerce project
Packages Classes
com.mywebsite.catalogue Catalogue – represents the catalogue of products
sold on the ecommerce website
CatalogueManager – responsible for creating
the Catalogue . For simplicity, CatalogueManager
creates a Catalogue with a single product.
com.mywebsite.customer Customer – represents a customer who buys
products from the ecommerce website
Address – current residential address of the
customer
CustomerManager – responsible for creating
the Customer .For simplicity, CustomerManager creates
a single Customer object.
com.mywebsite.order Order – represents an order that a customer places.
It contains information about the bought product
and the customer.
Address – contains the billing and shipping
addresses supplied by the customer while placing
the order.
OrderManager - responsible for creating the Order
and processing it
com.mywebsite.main EcommerceApp – contains the main method that
uses CatalogueManager ,
CustomerManager and OrderManager objects to place an
order for a customer.
Let’s now look at the import statement that allows importing classes from other packages.

import statement
A class can refer to classes defined in other packages by importing those classes using the import
statement. The following listing shows the OrderManager class of ecommerce project that refers
tothe Customer class:
Listing 5-2 import statement
Project: ecommerce
Source location: src\com\mywebsite\order\OrderManager.java
1 package com.mywebsite.order;
2
3 import com.mywebsite.customer.Customer;
4
5 public class OrderManager {
6 private Order order;
7 private Address address;
8
9 public OrderManager(String product, int price, Customer customer, Address theAddress) {
10 order = new Order(product, price, customer);
11 address = theAddress;
12 }
13 .....
14 }
OrderManager class is defined in com.mywebsite.order packageand Customer class is defined
in com.mywebsite.customer package.As Customer is defined in a different package, OrderManager class uses
the import statement (line #3) to import Customer class. The import statement specifies the fully-qualified
name of the class to be imported. The fully-qualified name of a class is formed by appending the
simple name (like Address , Customer , and so on) of the class to the name of the package that contains the
class.For instance, the fully-qualified name of Customer class in com.mywebsite.customer package
is com.mywebsite.shoppingcart.Customer .
NOTE Instead of using the import statement, you can directly refer to a class with its fully-qualified
name. As using the fully-qualified name of a class reduces the readability of the program, you should
import the class using the import statement and refer to the class using its simple name.
Instead of importing one class at a time, you can use the wildcard * in the import statement to import all
the classes in a package:
Listing 5-3 import statement – importing all the classes in a package
Project: ecommerce
Source location: src\com\mywebsite\main\EcommerceApp.java

As Catalogue and CatalogueManager classes are in com.mywebsite.catalogue package, a single import statement
with wildcard character (line #3) is used to import all the classes in com.mywebsite.catalogue package.
NOTE Java classes defined in the java.lang package are implicitly imported into a class. If you are
using Java classes that are defined in any other package except java.lang , then you need to explicitly
import them into your class.
Defining multiple classes with the same name
A package can’t contain multiple classes with the same name. If you need to define multiple classes
with the same name in your project, define them in different packages.
The ecommerce project defines two Address classes, one in com.mywebsite.customer package and another one
in com.mywebsite.order package. As EcommerceApp class defines variables that refer to two
different Address classes, it uses their fully-qualified names (refer listing 5-4) to avoid any ambiguity.
Listing 5-4 EcommerceApp class – referring to different classes with the same name
Project: ecommerce
Source location: src\com\mywebsite\main\EcommerceApp.java
You can run EcommerceApp ’s main method to see how CatalogueManager , CustomerManager and OrderManager
classes are used to place an order for a customer.
NOTEYou can’t use simple names of Address classes in the EcommerceApp class because the Java
compiler will have no way to determine whether a variable is referring to the Address class
in com.mywebsite.customer package or the Address class in com.mywebsite.order package.
Let’s now look at different access modifiers defined by Java that help control access to classes and
its members (which includes attributes and methods) and constructors.
NOTE Anywhere we’ve used the term ‘class members’ it means that we are referring to attributes
and methods of the class. The constructors are not considered ‘members’ of a class.
5-3 Access modifiers
Access modifiers are used in Java to control access to classes, methods, attributes and constructors.
Java defines the following access modifiers: public , private and protected . As protected access modifier is
meaningful when a class inheritsfrom another class, protected access modifier is explained in chapter
6. When no access modifier is specified for the class, constructor, method or attribute, then the access
is considered package-private.
IMPORTIt is recommended that you import the access_modifiers project into your Eclipse
IDE.The access_modifiers project contains examples that show usage of different access modifiers.
The following are the important points to note about each access modifier:
if a class member or constructoris defined as private , it accessible only within the class. For
instance, if you define a method as private , it cannot be called from other classes.
if a class member or constructoris defined as public , it is accessible to all the classes in the
same or different packages. For instance, if you define a method as public , it can be called
from the classes in the same or different packages.
if a class member or constructor has package-private access, it is accessible only to classes
in the same package. For instance, if you define as method as having package-private access,
it can be called only from the classes in the same package.
As aclass can’t be defined as private or protected , we’ll look at examples in which classes are defined as
public or package-private.

NOTE Access modifiers have compile-time semantics, which means access control violations are
reported when you compile the classes.
The following listing shows the Person classof access_modifiers project that defines members and
constructors with different access restrictions:
Listing 5-5 Person class
Project: access_modifiers
Source location: src\modifiers\Person.java
1 package modifiers;
2
3 public class Person {
4 private int privateAge;
5 public int publicAge;
6 int packagePrivateAge;
7
8 public Person(int age) { ..... }
9
10 private Person() { ..... }
11
12 Person(int thePrivateAge, int thePublicAge, int thePackagePrivateAge) { ..... }
13
14 private int getPrivateAge() {
15 return privateAge;
16 }
17
18 public int getPublicAge() {
19 return publicAge;
20 }
21
22 int getPackagePrivateAge() {
23 return packagePrivateAge;
24 }
25 }

In the above listing:


privateclass members and constructors are - privateAge attribute (line #4), no-
argument Person constructor (line #10) and getPrivateAge method (line #14)
publicclass members and constructors are – publicAge attribute (line #5), Person(int age)
constructor (line #8)and getPublicAge method (line #18)
package-private class members and constructors are – packagePrivateAge attribute (line
#6), Person ( int thePrivateAge, int thePublicAge, int thePackagePrivateAge ) constructor (line #12) and
getPackagePrivateAge method (line #22)

the class itself is defined as public


In the same package as the Person class, aclass named Dog is defined with package-private access:
Listing 5-6 Dog class
Project: access_modifiers
Source location: src\modifiers\Dog.java
1 package modifiers;
2
3 class Dog {
4 private String name;
5
6 public Dog(String theName) {
7 name = theName;
8 }
9
10 public String getName() {
11 return name;
12 }
13 }

As no access modifier is specified in the Dog class definition, Dog class has package-private access.
The Dog class defines a single public constructor (line #6)for creating an instance of Dog with the given
name.
The following listing shows the AccessModifiersTest class of access_modifiers project whose main method
createsinstances of Person and Dog classes and accesses their attributes and/or methods:
Listing 5-7 AccessModifiersTest class
Project: access_modifiers
Source location: src\modifiers\AccessModifiersTest.java
NOTE You should note that AccessModifiersTest , Person and Dog classes are defined in the modifiers
package
At first, main method creates Person objects by calling different constructorsof the Person class. It then
accesses the attributes and methods of Person objects. The following syntax is followed for accessing
attributes of an object:
<object>.<attribute-name>
here, <object> is the object whose attribute we want to access, and <attribute-name> is the
name of the attribute.
In listing 5-7, the following statements have been commented out because they result in compilation
error:
Person p1 = new Person()- as the no-argument constructor in Person class is defined private (refer
line #10 in listing 5-5), you can’t call it from any other class
- as the privateAge attribute is defined as private (refer line #4 in
System.out.println(p2.privateAge)
listing 5-5), it can only be accessed by constructors and methods of the Person class
System.out.println(p2.getPrivateAge()) -
as the getPrivateAge method is defined as private (refer line #14 in
listing 5-5), it can only be accessed by other methods of the Person class.
If the AccessModifiersTest class was located in a different package than the Person and Dog classes, then
there would have been more compilation errors. The following listing shows
the AccessModifiersTest class of access_modifiers project that is located in mypackage package:
Listing 5-8 AccessModifiersTest class
Project: access_modifiers
Source location: src\mypackage\AccessModifiersTest.java
In the AccessModifiersTest class shown in the above listing, we’ve additionally commented the following
statements because they result in compilation error:
import access_modifiers.Dog -
as the Dog class (refer listing 5-6) is defined to have package-private
access, it is not accessible to classesoutside the modifiers package
Person p3 = new Person(25, 30, 35) -
as this Person constructor is defined to have package-private
access (refer line #12 in listing 5-5), it cannot be called from classes outside the modifiers
package
System.out.println(p2.packagePrivateAge) -
as the packagePrivateAge attribute has package-private access
(refer line #6 in listing 5-5), it cannot be accessed from classes outside the modifiers package
System.out.println(p2.getPackagePrivateAge()) -
as the getPackagePrivateAge method has package-private
access (refer line #22 in listing 5-5), it cannot be called from classes outside the modifiers
package
Dog dog = new Dog("Max") - as Dog class is not accessible outside the modifiers package, you can’t
call its constructor(s)
NOTE When writing a class, you should carefully consider the access modifier for the class and its
members and constructors. For instance, if an attribute’s value can be accessed by other classes in the
project, then define that attribute as a public attribute.
Let’s now look at the implications of adding static keyword (also referred to as static modifier) to
attributes and methods.
IMPORTIt is recommended that you import the statickeyword project into your Eclipse IDE.
5-4 static modifier
We saw in chapter 4 that if a class defines a static attribute (also referred to as a static variable or
class variable) then it is shared between objects of the class. This means, if you change the value of
the static attribute in one object, the new value is reflected in other objects of the class. We also saw
that to access attributes or methods of a class, you first need to create an object of that class. An
important implication of declaring an attribute or a method with static modifier is – you can access
that attribute or call that method without creating an object of the class.
The syntax for defining an attribute with the static modifier is:
<access_modifier> static <attribute-type> <attribute-name>;
here, <access-modifier>is the access modifier ( public , private , protected or package-private),
<attribute-type> is the type (primitive or class) of the attribute, and <attribute-name> is
the name of the attribute.
These are some of the valid definitions of static variables:
public static int length;
static int x;

The syntax for defining a method with the static modifier is:
<access_modifier> static <return-type> <method-name>(.....) { ..... }
here, <access-modifier>is the access modifier ( public , private , protected or package-private),
<return-type> is the return type (primitive or class) of the method, and <method-name> is
the name of the method.
These are some of the valid definitions of static methods:
public static int getLength() { ..... }
static int getX() { ..... }

NOTE A method definedwith static modifier is also referred to as a class method or static method. A
method that isn’t defined with static modifier is referred to as an instance method or non-static
method. You should note that you can’t define a class or a constructor or a local variable with static
modifier.
Let’s begin by looking at examples that uses static variables and methods.
static variables and methods
The following listing shows the Car class of statickeyword project that defines static variablesand
methods:
Listing 5-9 Car class– static variables and methods
Project: statickeyword
Source location: src\statickeyword\Car.java
Car class defines following static variables and methods:
numberOfCarsvariable (line #6) - keeps track of the total number of Car objects created. This
variable’s value is incremented each time a Car object is created.
getNumberOfCarsmethod (line #21) – returns the value of numberOfCars variable. As we’ve
defined numberOfCars variable as private , we need this method to get the value of numberOfCars
variable.
getCarInstance method (line #16) – a static method that creates and returns an instance of Car
object
We saw earlier that if a constructor is defined private , then it is notaccessible outside the
class. Car class defines a private constructor (refer line #8 in listing 5-9) that is called by
its getCarInstance method to create and return an object of Car class. This shows that the constructor of a
class can also be called from a static method within the class itself.
NOTE An instance method of a class can also call the constructor of the class. This is not uncommon;
an immutable object’s instance methods (explained in chapter 9) typically call the constructor of the
class to create and return new objects of the same class.
As a Car object can be created either by calling Car(String theColor, String theModel) constructor (refer line
#10) or by calling getCarInstance method (refer line #16), both increment the value of numberOfCars
variable(refer line #13 and #17). As numberOfCars is a static variable,there is only a single copy
of numberOfCars variable that is shared across different Car objects.
The following listingshows the StaticTest class of statickeyword project that creates multiple Car objects by
calling Car class’s public constructor and its getCarInstance static method:
Listing 5-10 StaticTest class
Project: statickeyword
Source location: src\statickeyword\StaticTest.java
NOTEWhen you ask JVM to run the main method of a class, JVM first loads classes of your project
into computer memory. The static variables of a class are initialized when the class is loaded by the
JVM. On the other hand, instance (or non-static) variables are initialized when you create an object
of the class. As in the case of instance variables, if you don’t assign an initial value to a static
variable, it is assigned a default value. The static variables are initialized to the same default value as
the corresponding instance variables of the same type (refer table 4-3 of chapter 4).
The following sequence of statements isexecuted by the StaticTest ’s main method:
System.out.println("Initial number of cars: " + Car.getNumberOfCars()) – line #5
As getNumberOfCars is a static method, we don’t need to create an instance of Car to call it.
When the Car class is loaded its numberOfCars static variable (of type int ) is initialized to 0 . For
this reason, call to getNumberOfCars method will return 0 .
new Car("someColor", "someModel") – line #6
This statement creates a new Car object. The call to constructor increments the value
of numberOfCars static variable by 1 (refer line #13 in listing 5-9).
System.out.println("No. of Cars: " + Car.getNumberOfCars()) – line #9
As the value of numberOfCars variable is 1 , getNumberOfCars method will return 1 .
Car.getCarInstance() – line #10
As getCarInstance is a static method (refer line #16 in listing 5-9), we don’t need to create an
instance of Car to call it. The getCarInstance method creates and returns a new instance of Car
object and increments the value of numberOfCars variable to 2 .
System.out.println("No. of Cars: " + Car.getNumberOfCars()) – line #12
The call to getNumberOfCars method will return 2 because the value of numberOfCars variableis 2 .
Car.getCarInstance() – line #13
The getCarInstance returns another Car instance and increments the numberOfCars variable to 3 .
System.out.println("No. of Cars: " + Car.getNumberOfCars()) – line #14
The call to getNumberOfCars method returns 3 .
If you run the StaticTest ’s main method, you’ll get the following output:
Initial number of cars: 0
No. of Cars after constructor call: 1
No. of Cars after getCarInstance method call: 2
No. of Cars after getCarInstance method call: 3

The above output shows that the numberOfCars static variable’s value wasincremented each time we
created a new Car object using either the Car ’s constructor or the getCarInstance static method.
The following listing shows the Calculator class of statickeyword project that defines static methods for
performing mathematical calculations:
Listing 5-11 Calculator class
Project: statickeyword
Source location: src\statickeyword\Calculator.java
1 package statickeyword;
2
3 public class Calculator {
4 public static int memory;
5
6 public static int sum(int a, int b) {
7 return (memory = a + b);
8 }
9 .....
10 }
Calculator class
defines sum , subtract and so on, static methods for performing mathematical calculations
on the passed arguments. The result of calculation isstored in the memory static variable (line #4).
Notice that Calculator class consists only of static methods and attributes. This is how typically static
methods are used; they perform calculations on the arguments passed and return a result.
NOTE In the examples that we’ve seen so far in this book, the main method of the class was called to
run the program. The main method is defined with static keyword, which means it’s a static method.
The use of static keyword also comes into picture when System.out.println method is called to write to the
output. System is a class that defines an out static variableof type PrintStream (a class provided by
Java). PrintStream class defines the println instance method that accepts the argument to be printed to the
output.In listing 3-5, we saw that Integer.parseInt(args[0]) expression was used to obtain the value
of age variable passed to the main method. In this case, Integer is the class that defines parseInt static
method that takes a String argument (represented by args[0] ) and returns the corresponding int value.
Now that we’ve seen examples using static variables and methods, let’s look at some of the
restrictions that apply to static methods.
Restrictions on static methods
As instance variables and methods can be accessed only after an object of the class is created, static
methods cannot access instance variables or call instance methods. As static methods can’t access
instance variables, it means that static methods can’t change the state of an object.
NOTE Static methods can’t access instance variables and call instance methods, but instance
methods and constructors can access static variables and call static methods.
The following figure shows the modified getCarInstance method of Car class (refer listing 5-9) that
setsthe value of color instancevariable to "RED" and also calls the getColor instance method:
Figure 5-5 Accessing instance variables or methods from a static method results in compilation error
The above figure shows that accessing the color instance variable and the getColor instance method
results in compilation error. As the numberOfCars is a static variable, getCarInstance method can access it
without any problem.
Let’s now look at the this keyword that refers to the current object.
IMPORTIt is recommended that you import the thiskeyword project into your Eclipse IDE.
5-5 this keyword
The this keyword is used inside a constructor or instance method to refer to the current object. It is
often used inside a constructor or instance method to access instance variables of the current object.
A constructor may also use the this keyword to invoke another constructor of the current object. Let’s
look at some of the scenarios in which using the this keyword is useful.
NOTEAs this keyword refers to the current object, and static methods are meant to be called without
creating an object, you can’t use the this keyword inside a static method.
The following listing shows the Dog class of thiskeyword project that uses the this keyword in the
constructor to set values of name and distance instance variables of the current object:
Listing 5-12 Dog class - this keyword
Project: thiskeyword
Source location: src\thiskeyword\Dog.java
1 package thiskeyword;
2
3 public class Dog {
4 private String name;
5 private float distance;
6 .....
7 public Dog(String name, float distance) {
8 this.name = name;
9 this.distance = distance;
10 }
11 .....
12 }

In the above listing, instance variables and constructor arguments have same names. If the name of a
constructor (or method) argument is same as the name of an instance (or static) variable, the
constructor or method argument shadows (or hides) the instance (or static) variable. For instance, in
the above listing,the name and distance constructor arguments shadow the name and distance instance
variables, respectively.If you write a statement like System.out.println("name : " + name) inside the
constructor, it’ll always print the value of name constructor argument. For this reason, the this keyword
has been used to distinguish name and distance instance variables from name and distance constructor
arguments, respectively.
The following figure shows the effect of using the this keyword in listing 5-12:
The expression in the above figureshows that the this keyword is used to refer to the current Dog
object whose constructor is being called.The this keyword helps in distinguishing between the name
instance variable and the name constructor argument. As the right-hand side of the assignment
operatorrefers to the name constructor argument and the left-handside refers to the name instance
variable, value of name constructor argument is assigned to the name instance variable.
NOTE If the names of constructor (or method) arguments are different from the names of instance
variables, you don’t need to use the this keyword inside the constructor (or method) to distinguish
between instance variables and constructor (or method) arguments. In the examples that we’ve seen
so far in this book, we kept the names of constructor (or method) arguments different from the names
of instance variables. For this reason, we never usedthe this keyword.
If a constructor (or method) argument shadows a static variable, then you should use name of the
class to distinguish between constructor (or method) argument and the static variable. The following
listing shows Dog class’s setBarkingSound method that accepts sound as argument:
Listing 5-13 Dog class – assigning value to a static variable
Project: thiskeyword
Source location: src\thiskeyword\Dog.java
1 package thiskeyword;
2
3 public class Dog {
4 .....
5 private static String sound = "Woof-woof";
6 .....
7 public void setBarkingSound(String sound) {
8 Dog.sound = sound;
9 }
10 }
The setBarkingSound method acceptsargument named sound (line #7) thatwe want to assign to the sound
static variable (line #5). The following figure shows how setBarkingSound method assigns sound method
argument to sound static variable:

In the above expression, left-handside of the assignment operator refers to the sound static variable
and the right-handside refers to the sound argument passed to the setBarkingSound method. This means,
thevalue of sound method argument is assigned to the sound static variable.
If you define a local variable inside a constructor or a method with the same name as an instance (or
static) variable, it shadows the instance (or static) variable. Considerthe following Person class
of thiskeyword project in which name instance variable is shadowed by the name local variabledefined
in the Person constructor:
Listing 5-14 Person class
Project: thiskeyword
Source location: src\thiskeyword\Person.java
1 package thiskeyword;
2
3 public class Person {
4 private String name = "Hello";
5
6 public Person() {
7 int name = 0;
8 System.out.println("Value of name is : " + name);
9 }
10 }

In the above listing, name local variable (of type int ) shadows the name instance variable (of
type String ). If the Person class’s constructor is called, then what message will be printed by
the System.out.println statement on line #8? As the name local variable (line #7) shadows the name instance
variable (line #4), the following message will be printed:
Value of name is : 0

If a class defines multiple constructors, a constructor may call another constructor of the class to
perform object creation.The following listing shows the Dog class of thiskeyword project whose no-
argument constructor calls the constructor that accepts name and distance as arguments:
Listing 5-15 Dog class - this keyword for calling another constructor of the same class
Project: thiskeyword
Source location: src\thiskeyword\Dog.java
1 package thiskeyword;
2
3 public class Dog {
4 private String name;
5 private float distance;
6 .....
7 public Dog() {
8 this("Max", 100.25f);
9 System.out.println("Dog created");
10 }
11
12 public Dog(String name, float distance) {
13 this.name = name;
14 this.distance = distance;
15 }
16 .....
17 }

In the above listing, the no-argument Dog constructor calls Dog(String name, float distance) constructor (line
#8) using the this keyword.As name and distance arguments are required for calling the constructor, the
no-argument constructor supplies "Max" and 100.25f as values for them.This results in creation of a Dog
object with name as "Max" and distance travelled as 100.25 .
You should note that call to another constructor must be the first statement in the constructor body or
it’ll result in compilation error. Figure 5-8shows that Eclipse IDE complains if the call to the Dog(String
name, float distance) constructor is notthe first statement in the no-argument Dog constructor. In the figure,
call to Dog(String name, float distance) comes after System.out.println("Dog created") statement. For this reason,
Eclipse IDE shows the following compilation error message – 'Constructor call must be the first
statement in a constructor'.
An instance method can call another instance method of the currentobject without using the this
keyword. The following listing shows Dog classof thiskeyword project that defines two run methods–
one that doesn’t accept any argument and one that accepts an int type argument:
Listing 5-16 Dog class – an instance method calling another instance method
Project: thiskeyword
Source location: src\thiskeyword\Dog.java
1 package thiskeyword;
2
3 public class Dog {
4 .....
5 public void run() {
6 run(100);
7 }
8
9 public void run(int time) { ..... }
10 .....
11 }
The run() method calls the run(int time) method without using the this keyword. It is implied that the run(int
time) method of the current object needs to be called.This means, run(100) method call on line #6 is
equivalent to this.run(100) .
The concept of ‘pass by value’ is at the heart of Java programs. Let’s look at this concept in the
context of examples.
5-6 ‘Pass by value’
A Java program uses the heap and stack areas of computer memory during execution. The local
variables (that is, variables defined inside a method or constructor) and method (or constructor)
arguments are stored in the stack memory area. The objects that are created during program execution
are stored in the heap memory area. During program execution, a primitive type variable holds the
actual value of the primitive type, and a class type variable holds memory address (also called as
reference) of the object in the heap memory.
In Java, primitive and class types are ‘passed by value’, which means:
when you pass a primitive type to a method or constructor, the value of the primitive type
(and not the primitive type itself) is passed
when you pass a class type to a method or constructor, the memory address of the object (and
not the actual object) is passed
Let’s look at an example that shows how ‘pass by value’ works in Java.
IMPORTIt is recommended that you import the pass_by_value project into your Eclipse IDE.
The following listing shows the Employee class of pass_by_value project that defines both primitive and
class types attributes:
Listing 5-17 Employee class
Project: pass_by_value
Source location: src\com\sample\Employee.java
1 package com.sample;
2
3 public class Employee {
4 private int id; primitive type
5 private Department department; class type
6
7 public Employee(int id, Department department) {
8 this.id = id;
9 this.department = department;
10 }
11
12 public void changeId(int id) { ..... }
13
14 public void changeDepartmentName(Department department) { ..... }
15
16 public void changeDepartmentObject(Department department) { ..... }
17 }

Employee class represents an employee in an organization. The id attribute uniquely identifies an


employee in the organization, and the department attribute represents the department to which the
employee belongs. Employee class also defines changeId , changeDepartmentName and changeDepartmentObject
methods. Later in this section, we’ll look at what these methods do.
The following listing shows the Department class whose name attribute represents the department name:
Listing 5-18 Department class
Project: pass_by_value
Source location: src\com\sample\Department.java
1 package com.sample;
2
3 public class Department {
4 private String name;
5
6 public Department(String name) {
7 this.name = name;
8 }
9
10 public String getName() {
11 return name;
12 }
13
14 public void setName(String name) {
15 this.name = name;
16 }
17 }
The following listing shows the EmployeeTest class of pass_by_value project whose main method createsan
instance of Employee object, as shown here:
Listing 5-19 EmployeeTest class
Project: pass_by_value
Source location: src\com\sample\EmployeeTest.java
1 package com.sample;
2
3 public class EmployeeTest {
4 public static void main(String args[]) {
5 String str = "DepartmentOne";
6 Department deptOne = new Department(str);
7 int id = 1;
8 Employee emp = new Employee(id, deptOne);
9 .....
10 }
11 }
In the context of EmployeeTest class, figure 5-9 shows how objects and primitive types are stored in the
computer memory. As localvariables are stored in the stack memory, the figure shows
that emp , id , deptOne and str variables are stored in the stack memory. As objects and their
instancevariables are stored in the heap memory, the figure shows that Department , Employee and String
objects and their instance variables (if any) are stored in the heap memory.
The above figure also shows that primitive type variables store the actual value, and class type
variables stores memory address of the object in heap. For instance, the str , emp and deptOne variables
store memory addressesof "DepartmentOne" , Employee and Department objects (refer lines labeled ❶, ❷
and ❸ ), respectively.And, the id variable (of type int ) stores the actual value.
NOTE A class type variable is also called as a ‘reference to an object’ because it holds memory
address of the object but not the actual object.
When you pass variables as arguments to methods and constructors, this is what happens behind the
scenes:
if the argument is a primitive type, a copy of the variable’s value is passed. For instance, in
listing 5-19, value of id variable (that is, 1 ) is passed when you call Employee ’s constructor
(line #8).
if the argument is a class type, a copy of the object’s address in heap memory is passed. For
instance, in listing 5-19, heap memoryaddress of "DepartmentOne" String object is passed to
Department ’s constructor (line #6).

When Department ’s constructor is called (refer line #6 in listing 5-19), the memory address
of "DepartmentOne" String object is passed as the value for name constructor argument. As Department ’s
constructor assigns the value of name constructor argument to name instance variable (line #7 in listing
5-18), the memory address of "DepartmentOne" String object is assigned to the name instance variable
(refer line labelled ❺ in figure 5-9).
As id variable’s value is 1 (line #7 in listing 5-19) and deptOne variable’s value is the memory address
of the Department object (line #6 in listing 5-19), they are passed to Employee ’s constructor (line #8 in
listing 5-19).As Employee ’s constructor assigns value of deptOne to its department instance variable (line
#9 in listing 5-17), the memory address of Department objectis assigned to the department instance
variable (refer line labeled ❹ in figure 5-9).As Employee ’s constructor assigns the passed id value to
its id instance variable (line #8 in listing 5-17), value 1 is assigned to the id instance variable.
Let’s look at what happens when a called method (or constructor) modifies the primitive or class type
supplied as an argument.
Called method changes value of the passed primitive type
As shown in the following figure, Employee class defines a changeId method that is called
by EmployeeTest ’s main method:

Figure 5-10 EmployeeTest ’s main method calls Employee ’s changeId method with argument value 1
In the above figure, id variable is passed to Employee object’s changeId method. As the value
of id variable is 1 , a copyof 1 is made andsent to the changeId method.The changeId method changes the
value of the received id argument to 10 . So, what will be the output printed by System.out.println("After call to
changeId: " + id) statement in the EmployeeTest ’s main method ?

As a copyof id variable’s value was sent to the changeId method, the original value of id variable
remains unchanged. For this reason, System.out.println("After call to changeId: " + id) statement prints ‘After call
to changeId: 1’. This shows that a called method (or constructor) can’t change the original value of
the primitive type passed as an argument.
Called method modifies the passed object’s attributes
Figure 5-11shows that EmployeeTest ’s main method calls Employee object’s changeDepartmentName methodto
change the name of the passed Department object.The changeDepartmentName method calls
the setName method of the passed Department object to change the department name from "DepartmentOne"
to "DepartmentTwo" .So, what is printed by the statement System.out.println("After call to changeDepartment: " +
deptOne.getName()) in the EmployeeTest ’s main method?

Let’s first understand what happens behind the scenes.

Figure 5-11shows that the deptOne variable refers to the Department object (refer line labeled ❶)
whose name instance variable refers to the "DepartmentOne" String object (refer line labeled ❷ ).
When changeDepartmentName method is called, copyof the memory address held by deptOne variable is
passed as method argument. This means the changeDepartmentName method’s department argument holds
memory address of the same Department object as the deptOne variable (refer line labeled ❸ ).
The changeDepartmentName method calls the setName method on the referenced Department object that sets
the Department object’s name instance variable to the memory address of "DepartmentTwo" String object
(refer line labeled ❹ ).

Figure 5-11 EmployeeTes t’s main method calls Employee object’s changeDepartmentName with deptOne as
argument

The broken line labeled ❷ and the solid line labeled ❹ depict thatafter the changeDepartmentName
method is executed, Department object’s name instance variable refers to "DepartmentTwo" String object and
notto "DepartmentOne" String object. As deptOne variable in EmployeeTest class holds memory address of the
same Department object that is modified by the changeDepartmentName method, the System.out.println("After call to
changeDepartment: " + deptOne.getName()) statement prints the following message on the output:
After call to changeDepartment: DepartmentTwo

This shows that a called method (or constructor) can modify the attributes of an object passed as an
argument. And, such changes are visible to the calling method (or constructor).
Called method modifies the passed memory address
Figure 5-12shows that EmployeeTest ’s main method calls Employee object’s changeDepartmentObject method.
The changeDepartmentObject method creates a new instance of Department object and assigns it to the passed
department argument.So, what is printed by the statement System.out.println("After call to changeDepartmentObject: " +
deptOne.getName()) in the EmployeeTest ’s main method?

After the changeDepartmentName method call, the Department object referenced by deptOne variable holds
memory address of "DepartmentTwo" String object (refer line labeled ❶ ). Now, when
the changeDepartmentObject method is called, copyof Department object’s memory address referenced
by deptOne variable is passed. This means the changeDepartmentObject method’s department argument holds
memory address of the same Department object as the deptOne variable. The changeDepartmentObject creates a
new Department object whose name attribute refers to "DepartmentThree" String object, and assigns it to
the department method argument (refer line labeled ❷ ). As a copyof the memory address held
by deptOne variable was sent to the changeDepartmentObject method, the memory address held
by deptOne variable remains unchanged. For this reason, System.out.println("After call to changeDepartmentObject: " +
deptOne.getName()) statement prints the following message on the output:
After call to changeDepartmentObject: DepartmentTwo

Figure 5-12 EmployeeTes t’s main method calls Employee object’s changeDepartmentObject with deptOne as
argument
Instead of using ‘pass by value’ approach, a programming language may choose to follow ‘pass by
reference’. In ‘pass by value’ approach, a copy of the memory address (in the case of objects) or the
copy of the variable (in the case of primitive types) is passed. If variables are passed ‘by reference’,
then the memory address (and not its copy) or the actual variable (and not its copy) is passed to the
called method or constructor.
QUIZ
5-1: Which of the following statements about Java packages are true?
a) packages help organize classes in the project
b) a package is represented by a folder structure in the file system
c) you can define multiple classes with the same name in a package
d) a class can refer to classes in other packages by importing them using the import statement
e) a class can refer to classes in other packages by using their fully-qualified name
5-2: Which of the following statements are true about access modifiers?
a) a private method cannot be called from other classes
b) a package-private method cannot be called from classes in the same package
c) a public method can only be called from classes in the same package
d) a class can be defined private
e) a constructor can be defined private
5-3: Which of the following statements are true about usage of static keyword?
a) a static method can be called without creating an object of the class
b) a static method can be used to change the value of an instance variable
c) a non-static method can be used to change the value of a static variable
d) a static method can call a non-static method
e) a non-static method can call a static method
f) a constructor can be defined static
5-4: Which of the following statements are true about the this keyword?
a) this keyword refers to the current object
b) this keyword is used by non-static methods for accessing instance variables
c) this keyword is used by static methods for accessing instance variables
d) this keyword can be used by a constructor to call another constructor of the current object
e) this keyword can be used by a static method to call another static method of the current
object
5-5: Consider the following Airplane class that defines currentSpeed , distanceCovered and maxSpeed attributes:
1 public class Airplane {
2 public float currentSpeed;
3 public float distanceCovered;
4 public static float maxSpeed;
5
6 public Airplane(int currentSpeed, float distanceCovered, float maxSpeed) {
7 currentSpeed = currentSpeed;
8 this.distanceCovered = distanceCovered;
9 Airplane.maxSpeed = maxSpeed;
10 }
11 }

What wouldbe the output from running the following main method?
1 public static void main(String args[]) {
2 Airplane airplane = new Airplane(10, 100, 50);
3 System.out.println("Distance covered: " + airplane.distanceCovered);
4 System.out.println("Current speed: " + airplane.currentSpeed);
5 System.out.println("Max speed: " + airplane.maxSpeed);
6 }

5-6: Which of the following statements are true?


a) objects are stored in the stack memory area of computer
b) local variables are stored in the heap memory area of computer
c) a reference type variable holds the memory address of the object
d) when you pass a class (or a reference) type to a method, the actual object is passed to the
method
e) when you pass a primitive type to a method, a copy of the primitive type's value is passed
5-7 Summary
In this chapter, we looked at how to create packages and use them to organize Java classes. We
looked at access modifiers that are used for controlling access to classes, attributes, methods and
constructors. We saw that static keyword can be used to define an attribute or a method that can be
accessed without creating an instance of the class. We also saw that the this keyword is useful when it
comes to accessing instance variables and calling one constructor from another. We wrapped the
chapter up by looking at an example that showed variables in Java are passed ‘by value’. In the next
chapter, we’ll look at different object-oriented programming concepts, like inheritance,
polymorphism, and so on.
Chapter 6 – Object-oriented programming
concepts
6-1 Introduction
In this chapter, we’ll look at the following object-oriented programming concepts that are central to
the Java programming language:
encapsulation
inheritance
polymorphism
A good understanding of the above mentioned concepts is required to write real-world Java
applications. We’ll wrap this chapter up by looking at Java’s built-in java.lang.Object class.
Let’s begin this chapter by looking at what encapsulation is, and how it is achieved in Java.
a-2 Encapsulation
Encapsulation refers to defining a class such that the methods that access or modify attributes of the
class are defined in the same class. And, the only way to access or modify the attributes is through the
methods defined in the class.
Encapsulation is achieved by defining attributes of a class as private , and the methods that access or
modify thoseattributes as public . The following listing shows the Car class that follows the concept of
encapsulation:
Listing 6-1 Car class
public class Car {
private float currentAcceleration;
private int currentSpeed;
.....
public Car(float currentAcceleration, int currentSpeed) {
this.currentAcceleration = currentAcceleration;
this.currentSpeed = currentAcceleration;
}
public void accelerate(int timeInSeconds) {.....}
public void decelerate(int timeInSeconds) {.....}
public float getCurrentAcceleration() {.....}
public int getCurrentSpeed() {.....}
}
The currentAcceleration and currentSpeed attribute are
defined private ,and accelerate , decelerate , getCurrentAcceleration and getCurrentSpeed methods that access or
modify these attributes are defined public .So, if a Car object is created, the only way to modify its
attributes (or state)is through the public methods.
If a class defines all its attributes as private and the only way to access them is through public methods,
then the class is called a fully-encapsulated class.As private attributes in a fully-encapsulated class
are not directly accessible to other objects, they are protected from being changed accidentally by
other objects.
NOTE Encapsulation is also referred to as data hiding because it hides the attributes (or state) of an
object from direct access.
Let’s now look at what is inheritance, and how it is achieved in Java.
6-3 Inheritance
While writing a program you may find that some of the classes share a common set of attributes and
methods. The following figure shows SavingsAccount (represents a savings bank account)
and CurrentAccount (represents a business account) classes defined in a banking application:

The attributes defined in SavingsAccount and CurrentAccount classes are:


accountNumber – the unique bank account number
currentBalance – the current balance in the bank account
interestRate – the interest rate provided by bank for the money deposited in the savings account
isBusinessAccount – tells whether the current account is a business account or not
overdraftLimit – the overdraft limit for the account
The methods defined in SavingsAccount and CurrentAccount classes are:
credit(int amount) – adds the given amount to the currentBalance
debit(int amount) – subtracts the given amount from the currentBalance
addInterest(int period) – adds interest for the given period to the currentBalance
increaseOverdraftLimit(int amount) – increases the overdraft limit of the current account by the
given amount
Both SavingsAccount and CurrentAccount classes define accountNumber and currentBalance attributes,
and credit and debit methods. In such a scenario, you can move common set of attributes and
methodsinto a new class and let SavingsAccount and CurrentAccount classes inherit from it.

The above figure shows that the attributes and methods common to
both SavingsAccount and CurrentAccount classes are moved to a
new Account class. SavingsAccount and CurrentAccount classes now define attributes and methods that are
specific to the account types they represent, and inherit the common attributes and methods from
the Account class. Account class is referred to as a superclass (or parent class)
and SavingsAccount and CurrentAccount classes are referred to as subclasses (or child classes).
This brings us to the definition of inheritance - Inheritance is a mechanism by which a class inherits
attributes and methods from another class.In Java, extends keyword is used by a class to inherit from
another class.
Let’s see how a class inherits from another class using the extends keyword.
NOTE In Java, inheritance can be of two types: class inheritance and interface inheritance. In class
inheritance, a class inherits from another class. In interface inheritance, a class inherits from an
interface (discussed in chapter 7). In chapter 7, we’ll look at what an interface is, and how a class
inherits from an interface.
extends keyword
A class uses the extends keyword in its definition to specify that it is a subclass of another class.
IMPORTIt is recommended that you import the bankapp-inheritance project into your Eclipse IDE.
The following listing shows the Account class that defines attributes and methods common to both
SavingsAccount and CurrentAccount classes (refer figure 6-2):

Listing 6-2 Account class – defines common attributes and methods


Project: bankapp-inheritance
Source location: src\com\mybank\Account.java
1 package com.mybank;
2
3 public class Account {
4 protected int accountNumber;
5 protected int currentBalance;
6
7 public Account() {
8 System.out.println("Account's constructor");
9 }
10
11 public int credit(int amount) {
12 return currentBalance = currentBalance + amount;
13 }
14
15 public int debit(int amount) {
16 return currentBalance = currentBalance - amount;
17 }
18
19 public void setAccountNumber(int accountNumber) {
20 this.accountNumber = accountNumber;
21 }
22
23 public void setCurrentBalance(int currentBalance) {
24 this.currentBalance = currentBalance;
25 }
26 .....
27 }
The accountNumber (line #4) and currentBalance (line #5) attributes are defined with protected access. The
methods debit (line #15) and credit (line #11) are defined with public access. To set values
of accountNumber and currentBalance attributes, setAccountNumber (line #19) and setCurrentBalance (line #23)
methods have been defined with public access.A public no-argument constructor (line #7) is also
defined that prints ‘Account’s constructor’.
NOTE The attributes, methods and constructors defined with protected access are accessible only to
the subclasses or to the classes in the same package.

The following listing shows the SavingsAccount class that inherits from Account class:
Listing 6-3 SavingsAccount class – subclass of Account class
Project: bankapp-inheritance
Source location: src\com\mybank\SavingsAccount.java
1 package com.mybank;
2
3 public class SavingsAccount extends Account {
4 private int interestRate;
5
6 public SavingsAccount() {
7 System.out.println("SavingsAccount's constructor");
8 }
9
10 public void addInterest(int period) {
11 currentBalance = currentBalance + period * interestRate;
12 }
13
14 public void setInterestRate(int interestRate) {
15 this.interestRate = interestRate;
16 }
17
18 public void printValues() {
19 System.out.println("accountNumber: " + accountNumber
20 + ", currentBalance: " + currentBalance
21 + ", interestRate: " + interestRate);
22 }
23 }
The extends keyword (line #3) specifies that the SavingsAccount class inherits from the Account class.
SavingsAccount class defines an interestRate attribute, and addInterest , setInterestRate and printValues methods.

So, what gets inherited from the superclass? The following attributes and methods of a superclass are
inherited by subclasses:
public and protected attributes and methods
if the subclass is in the same package as the superclass, the package-private attributes and
methods are inherited
NOTE The static and instance variables, and methods are inherited by subclasses. The constructor is
not inherited by subclasses.
The inherited attributes and methods are accessed by the subclass as if they belong to the subclass
itself. As the Account class defines protected attributes and public methods, all the attributes and methods
are inherited by the SavingsAccount subclass. For this reason, accountNumber (line #19) and currentBalance
(line #11 and line #20) attributes of Account class are accessed in the SavingsAccount class as if they
belong to the SavingsAccount class itself.
NOTE You should note that inheritance doesn’t mean that attributes and methods are copied from the
superclass to the subclass. They just become accessible to the subclass as if they were defined in the
subclass itself.
SavingsAccount also defines a public no-argument constructor that prints 'SavingsAccount’s constructor'
(line #7). The printValues method (line #18) prints the values of accountNumber , currentBalance and interestRate
attributes.
Similar to SavingsAccount class, CurrentAccount class also inherits from the Account class:
Listing 6-4 CurrentAccount class – subclass of Account class
Project: bankapp-inheritance
Source location: src\com\mybank\CurrentAccount.java
1 package com.mybank;
2
3 public class CurrentAccount extends Account {
4 private boolean isBusinessAccount;
5 private int overdraftLimit;
6
7 public CurrentAccount() {
8 System.out.println("CurrentAccount's constructor");
9 }
10 .....
11 public void printValues() {
12 System.out.println("accountNumber: " + accountNumber
13 + ", currentBalance: " + currentBalance
14 + ", overdraftLimit: " + overdraftLimit
15 + ", isBusinessAccount: " + isBusinessAccount);
16 }
17 }

The above listing shows that CurrentAccount class defines isBusinessAccount (line #4) and overdraftLimit (line
#5) attributes, and printValues method (line #11), and a no-argument constructor (line #7) that prints
'CurrentAccount’s constructor'. As CurrentAccount class inherits from Account class, it accesses
inherited accountNumber and currentBalance attributes (line #12 and #13) as if they are defined in
the CurrentAccount class itself. The printValues method prints the values
of accountNumber , currentBalance , overdraftLimit and isBusinessAccount attributes.

The following listing shows the BankApp class whose main method creates instances of SavingsAccount
and CurrentAccount classes and calls their methods:
Listing 6-5 BankApp class
Project: bankapp-inheritance
Source location: src\com\mybank\BankApp.java
1 package com.mybank;
2
3 public class BankApp {
4 public static void main(String args[]) {
5 SavingsAccount sa = new SavingsAccount();
6 sa.setAccountNumber(1234567890);
7 sa.setCurrentBalance(1000);
8 sa.setInterestRate(10);
9 .....
10 sa.printValues();
11
12 CurrentAccount ca = new CurrentAccount();
13 ca.setAccountNumber(987654321);
14 .....
15 ca.printValues();
16 }
17 }
BankApp ’s main method creates instances of SavingsAccount and CurrentAccount classes and
calls setAccountNumber , setCurrentBalance , setInterestRate , debit , and so on, methods.The printValues
methodof SavingsAccount and CurrentAccount objects are called to print the values of their attributes.If you
run BankApp ’s main method, you’ll see the following output:

Figure 6-3 The output from running BankApp ’s main method


The output shows that 'Account’s constructor' is printed first, followed by 'SavingsAccount’s
constructor' or 'CurrentAccount’s constructor'. This means that when SavingsAccount ’s
(or CurrentAccount ’s)constructor is called, the Account ’s constructor is called first,followed
by SavingAccount ’s (or CurrentAccount ’s) constructor. This means that when you call a subclass’s
constructor, Java runtime first calls the superclass’s constructor, and then calls the subclass’s
constructor. This also means that when you create an object of a subclass, an object of the superclass
is also created.
The call to the superclass’s constructor is required because it initializes attributes of the superclass
object, which are then used by methods of the superclass object and may be accessed by methods of
the subclass object. For instance, the Account ’s currentBalance and accountNumber attributes are initialized
when SavingsAccount ’s or CurrentAccount ’s constructor is called.The currentBalance attribute is used
by credit and debit methods (refer listing 6-2) of Account object, and is also accessed by methods
of SavingsAccount and CurrentAccount objects.
The following figure summarizes what happens when the SavingsAccount ’s constructor is called:

Figure 6-4Call to SavingsAccount ’sconstructor first creates the Account object followed by creation of
the SavingsAccount object

The figure shows that call to SavingsAccount constructor (represented by ① ) first results in invocation
of Account ’s constructor (represented by ②) followed by invocation of SavingsAccount constructor
(represented by ③ ). This means, there exists a superclass object corresponding to each subclass
object. As with any other class, SavingsAccount and Account objectscan use the this keyword to refer to the
currentobject of SavingsAccount and Account objects, respectively. A subclass object can use the super
keyword (explained later in this section) to refer to the superclass object that was created
corresponding to the subclass object. In the above figure, the super keyword is used by
the SavingsAccount subclass object to refer to the corresponding Account superclass object.
NOTE A superclass object cannot access members or constructors of the subclass object
We saw that calling SavingsAccount (or CurrentAccount ) no-argumentconstructor results in calling
the Account class’s no-argument constructor. We also saw
that Account ’s setAccountNumber and setCurrentBalance methods are used to set the values
of accountNumber and currentBalance attributes. What would have happened if Account class had defined
only a single constructor that accepted accountNumber and currentBalance as arguments? Let’s look at this
by doing some hands-on activity.
Hands-on Replace Account ’s no-argument constructor with a constructor that
accepts accountNumber and currentBalance arguments
The following listing shows the modified Account class that defines a single constructor that
accepts accountNumber and currentBalance arguments:
Listing 6-6 Account class – constructor accepts accountNumber and currentBalance as arguments
1 package com.mybank;
2
3 public class Account {
4 protected int accountNumber;
5 protected int currentBalance;
6
7 public Account(int accountNumber, int currentBalance) {
8 this.accountNumber = accountNumber;
9 this.currentBalance = currentBalance;
10 System.out.println("Account's constructor");
11 }
12 .....
13 }

As the constructor sets the values for accountNumber and currentBalance attributes, remove
the setAccountNumber and setCurrentBalance methods from the Account class.
If you now look at the SavingsAccount (or CurrentAccount ) class in the Eclipse IDE, you’ll see that it shows
compilation error:

Figure 6-5 SavingsAccount class shows compilation error because the Account ’s no-argument
constructor is no longer available
If you hover your mouse over x symbol, it’ll show you the following error message 'Implicit super
constructor Account() is undefined. Must explicitly invoke another constructor'. When Account class
had a no-argument constructor, it was called by Java runtime when SavingsAccount ’s constructor was
called. Now that we’ve replaced the no-argument constructor in Account ’s class with a custom
constructor, the no-argument constructor is no longer available. For this reason, you must explicitly
call the Account ’s constructor from the SavingsAccount ’s (or CurrentAccount ’s) constructor to create the
Account object.

The following listing shows the modified SavingsAccount ’s constructor that explicitly calls the Account
class’s constructor:
Listing 6-7 SavingsAccount class – subclass of Account class
1 package com.mybank;
2
3 public class SavingsAccount extends Account {
4 private int interestRate;
5
6 public SavingsAccount(int accountNumber, int currentBalance) {
7 super(accountNumber, currentBalance);
8 System.out.println("SavingsAccount's constructor");
9 }
10 .....
11 }

As the Account class’s constructor accepts accountNumber and currentBalance arguments, we’ve
modifiedthe SavingsAccount ’s constructor to accept them as arguments. SavingsAccount ’sconstructor
calls Account ’s constructor using the super keyword. The syntax for calling the superclass’s constructor
from the subclass’s constructor is:
super (<constructor-arguments>)
here, <constructor-arguments> is the comma-separated list of constructor arguments that
you want to pass to the superclass’s constructor. super is a keyword in Java that is used for
calling superclass’s constructors and methods, and for accessing superclass’s instance
variables.
The statement super(accountNumber, currentBalance) in SavingsAccount ’s constructor (refer line #7 in listing 6-
7) calls Account ’s constructorthat accepts accountNumber and currentBalance arguments. You should note that
call to the superclass’s constructor must be the first statement in the subclass’s constructor.
NOTE If you want to explicitly call the no-argument constructor of the superclass, simplycall super()
from the subclass’s constructor.

As in the case of SavingsAccount class, the following listing shows the modified constructor
of CurrentAccount class that explicitly calls the Account class’s constructor:
Listing 6-8 CurrentAccount class– subclass of Account class
1 package com.mybank;
2
3 public class CurrentAccount extends Account {
4 .....
5 public CurrentAccount(int accountNumber, int currentBalance) {
6 super(accountNumber, currentBalance);
7 System.out.println("CurrentAccount's constructor");
8 }
9 .....
10 }
As SavingsAccount ’sand CurrentAccount ’sconstructors have changed, and we’ve
removed setAccountNumber and setCurrentBalance methods from the Account class, the following listing shows
the modified BankApp class:
Listing 6-9 BankApp class
1 package com.mybank;
2
3 public class BankApp {
4 public static void main(String args[]) {
5 SavingsAccount sa = new SavingsAccount(1234567890, 1000);
6 sa.setInterestRate(10);
7 sa.addInterest(2);
8 sa.credit(2000);
9 sa.debit(100);
10 sa.printValues();
11
12 CurrentAccount ca = new CurrentAccount(987654321, 9000);
13 ca.credit(300);
14 ca.debit(900);
15 ca.printValues();
16 }
17 }
The above listing shows that the BankApp class now uses the new constructors of
SavingsAccount and CurrentAccount classes to create their objects.
Let’s look at how super keyword is used for invoking superclass’s instance methods and accessing
superclass’s instance variables.
IMPORTIt is recommended that you import the bankapp-super-keyword project into your Eclipse IDE.
super keyword
We saw that the super keyword is used by the subclass’s constructor for calling superclass’s
constructor. The super keyword is also used by a subclass object for calling instance methods and
accessing instance variables of the corresponding superclass object.
NOTE The super keyword only allows you to access superclass’s constructors and class members
that are defined public , package-private or protected . private constructors and class members of a
superclass are not accessible to subclasses.
The use of super keyword to access superclass object’s instance methods and instance variables is
optional. You should use the super keyword only when you want to clearly indicate that a given
instance method or instance variable belongs to the superclass object. The following listing shows
the SavingsAccount class that uses the super keyword to access currentBalance and accountNumber variables
of Account superclass and to call its credit method:
Listing 6-10 SavingsAccount class
Project: bankapp-super-keyword
Source location: src\com\mybank\SavingsAccount.java
1 package com.mybank;
2
3 public class SavingsAccount extends Account {
4 private int interestRate;
5 .....
6 public void addInterest(int period) {
7 super.credit(period * interestRate);
8 }
9 .....
10 public void printValues() {
11 System.out.println("accountNumber: " + super.accountNumber
12 + ", currentBalance: " + super.currentBalance
13 + ", interestRate: " + interestRate);
14 }
15 }

In the above listing, the printValues method (line #10) uses the super keyword to access accountNumber
(line #11) and currentBalance (line #12) instance variables of the Account superclass object. Similarly,
the addInterest method (line #6) uses the super keyword to call the credit method (line #7) defined in
the Account superclass to credit the interest amount into the bank account.
Let’s now look at the concept of method overriding that comes into picture when using inheritance.
IMPORTIt is recommended that you import the bankapp-method-overriding project into your Eclipse IDE.
Method overriding
Method overriding feature of Java allows you to override the behavior of an inherited instance
method by redefining that method in the subclass.
NOTEAs private methods are not inherited by subclasses, method overriding feature doesn’tapply
to private methods
The following listing shows the Account class of bankapp-method-overriding projectthat defines the debit
method for subtracting the givenamount from the currentBalance attribute:
Listing 6-11 Account class– debit method
Project: bankapp-method-overriding
Source location: src\com\mybank\Account.java
1 package com.mybank;
2
3 public class Account {
4 protected int currentBalance;
5 .....
6 public int debit(int amount) {
7 if(currentBalance - amount < 0) {
8 System.out.println("Can't debit because the current balance will become < 0");
9 } else {
10 currentBalance = currentBalance - amount;
11 }
12 return currentBalance;
13 }
14 }

The currentBalance attribute represents the current balance in the bank account. The debit method deducts
the given amount from the currentBalance and returns the remaining balance. Note that debit method
deducts money from currentBalance only if the deductiondoesn’t make the currentBalance negative.
SavingsAccount and CurrentAccount subclasses inherit the above shown debit method. The above
implementation of debit method is fine fora SavingsAccount object, but not for a CurrentAccount object. A
current account has an overdraft limit, which means you can withdraw money up to the overdraft
limit.For this reason, we need to change the implementation of debit method for CurrentAccount to
consider the overdraft limit.
CurrentAccountsubclass changes the implementation of debit method inherited from Account class by
redefining the debit method, as shown in the following listing:
Listing 6-12 CurrentAccount class – overriding debit method
Project: bankapp-method-overriding
Source location: src\com\mybank\CurrentAccount.java
1 package com.mybank;
2
3 public class CurrentAccount extends Account {
4 private int overdraftLimit;
5 .....
6 public int debit(int amount) {
7 int newBalance = super.currentBalance - amount;
8 if (newBalance – overdraftLimit < 0) {
9 System.out.println(
10 "Debit of " + amount
11 + " is not allowed. Your overdraft limit is "
12 + overdraftLimit);
13 return super.currentBalance;
14 } else {
15 super.currentBalance = newBalance;
16 return newBalance;
17 }
18 }
19 .....
20 }

The debit method of CurrentAccount class overridesthe debit method of the Account superclass to consider
the overdraft limit. The debit method in the Account superclass is referred to as the overriddenmethod,
and the debit method in the CurrentAccount subclass is referred to as the overriding method.
You should note that the signature of an overriding method must be same as that of the overridden
method. Two methods are said to have the same signature, if they have the same name, accept same
number and type of arguments, and have the same return type.
NOTE You can’t define two methods with the same signature in the same class, but they can exist in
both superclass and subclass.
The following listing shows the BankApp class of bankapp-method-overriding project whose main
methodcalls debit methods of both SavingsAccount and CurrentAccount objects:
Listing 6-13 BankApp class
Project: bankapp-method-overriding
Source location: src\com\mybank\BankApp.java
1 package com.mybank;
2
3 public class BankApp {
4 public static void main(String args[]) {
5 SavingsAccount sa = new SavingsAccount(1234567890, 1000);
6 System.out.println("Saving's account current balance: " + sa.debit(1200));
7
8 CurrentAccount ca = new CurrentAccount(987654321, 9000);
9 ca.setOverdraftLimit(500);
10 System.out.println("Current account's current balance: " + ca.debit(10000));
11 }
12 }

On line #5, we create an instance of SavingsAccount with currentBalance as 1000 . On line


#6, SavingsAccount ’s debit method is called to debit 1200 from the account, and the result is written to the
output. On line #8, we create an instance of CurrentAccount with currentBalance as 9000 . On line #9, we set
the overdraftlimit of CurrentAccount object to 500 . On line #10, we call the debit method of CurrentAccount
object to debit 10000 from the account, and write the returned result to the output.
If you run BankApp ’s main method, you’ll get the output shown in figure 6-6. As SavingsAccount class
inherits the Account ’s debit method, call to SavingsAccount ’s debit method (line #6 in listing 6-13) prints
the message 'Can't debit because the current balance will become < 0' (line #8 in listing 6-11). This
isbecause the account balance is 1000 and we are trying to debit 1200 from the account.
Figure 6-6 Output from running BankApp ’s main method
As CurrentAccount overrides Account ’s debit method, call to CurrentAccount ’s debit method (refer line #10 in
listing 6-13) prints the message 'Debit of 10000 is not allowed. Your overdraft limit is 500'(refer line
#10, #11 and #12 in listing 6-12). This is because the account balance is 9000 , overdraft limit is 500 ,
and we are trying to debit 10000 from the account.
The output shows:
call to SavingsAccount ’s debit method executes the debit method inherited from the Account class
call to CurrentAccount ’s debit method executes the debit method defined in the CurrentAccount class
Let’s now look at restrictions that apply to the overriding method.
Restrictions on the overriding method
The following restrictions apply to the overriding method defined in the subclass:
the access modifier of the overriding method must not be more restrictive than the access
modifier of the overridden method
the return type of the overriding method must be same (or a subtype) as the return type of the
overridden method.
NOTE In the case of class types, the subclass type is referred to as a subtype and superclass type is
referred to as supertype. For instance, in the bankapp-method-
overriding project, SavingsAccount and CurrentAccount are subtypesof Account type, and Account is a
supertypeof CurrentAccount and SavingsAccount types.
If the above restrictions are not followed, compilation errors are reported by the Java compiler.
Let’s look at examples that demonstrate the above mentioned restrictions.
Access modifier restriction
Figure 6-7 shows relative restrictiveness of access modifiers. The public access modifier is the least
restrictive access modifier because public class members and constructors can be accessed by all
other classes. The private access modifier is the most restrictive access modifier because private class
members and constructors cannot be accessed outside the class.

Figure 6-7 Relative restrictiveness of different access modifiers


This means:
if a method is defined public in the superclass, the overriding method must be defined public
if a method is defined protected in the superclass, the overriding method must be
defined protected or public
if a method is defined to have package-private access in the superclass, the overriding
method must be defined public or protected or having package-private access
The following listing shows the Animal class that defines a makeSound methodwith protected access:
Listing 6-14 Animal class
1 public class Animal {
2 .....
3 protected void makeSound() {
4 System.out.println("None");
5 }
6 }

The following listing shows Dog subclass of Animal class that overrides the makeSound method:
Listing 6-15 Dog class
1 public class Dog extends Animal {
2 .....
3 void makeSound() {
4 System.out.println("Bow wow");
5 }
6 }

As the makeSound method is defined protected in Animal class, the overriding method mustbe
defined public or protected . As Dog ’s makeSound method is defined with package-private access, the Dog
class fails to compile.
Return type restriction
The return type of an overriding method must be:
same as the return type of the overridden method, or
subtype of the return type of the overridden method
The following listing shows the Person class that represents a person who owns a pet:
Listing 6-16 Person class
1 public class Person {
2 private Animal animal;
3 .....
4 public Animal getPet() {
5 return animal;
6 }
7 }

Person ’s getPet method returns the pet owned by the person. Notice that the return type of getPet method
is Animal (refer listing 6-14).
The following listing shows the DogOwner subclass of Person class that represents a person who owns
a dog as a pet:
Listing 6-17 DogOwner class
1 public class DogOwner extends Person {
2 private Dog dog;
3 .....
4 public Dog getPet() {
5 return dog;
6 }
7 }

DogOwner overrides Person ’s getPet method and returns an object of type Dog (refer listing 6-15). Dog is a
subclass of Animal , which means Dog is a subtypeof Animal . DogOwner class compiles successfully
because the overriding getPet method returns Dog type (a subtype of Animal ).If Dog class was not a
subtypeof Animal , the DogOwner class would have failed to compile.
Let’s now look at the concepts of upcasting and downcasting that are closely related to inheritance.
Upcasting and downcasting
Upcasting refers to converting a subclass object to the superclass type. Upcasting is performed when:
a subclass object is assigned to a variable of superclass type, or
a subclass object is passed to a method or constructor where the superclass type is expected
For instance, if Dog is a subclass of Animal , then the following assignment is an example of upcasting:
Animal animal = new Dog(); //-- no compilation error

As subclasses define more methods and attributes than their superclass, a subclass object can easily
take the place of its superclass. For this reason, the Java compiler doesn’t complain when it sees the
above assignment.
NOTE Upcasting is performed automatically; you don’t need to explicitly convert a subclass object
to superclass type
Upcasting is also performed when you pass a subclass object to a method or constructor that accepts
the superclass type. For instance, consider the following method:
public void doSomething(Animal animal) { }
The doSomething method specifies that it accepts an Animal type argument. If Dog class is a subclass
of Animal , a Dog object passed to the doSomething method is automatically upcastedto Animal type, as
shown here:
doSomething(new Dog());

As subclasses typically have more attributes and methods than their superclass, upcasting restricts
you from accessing extra attributes and methods defined in the subclass. Let’s say that Dog subclass
of Animal defines a public attribute breed and a public method run . If you assign a Dog object to an Animal
type variable, as shown here, you can’taccess Dog ’s breed attribute or call Dog ’s run method:

In the above assignment, Animal is referred to as the declared typebecause we’ve


declared animal variable of type Animal , and Dog is referred to as the runtime type because the actual
object that is assigned to the animal variable during program execution is a Dog object.
As the declared type doesn’t know about additional attributes and methods defined by the runtime
type, you can only access methods and attributes defined by the declared type. This means that you
can’taccess breed attribute or call run method of the Dog object using the animal variable. For this reason,
the following method call will result in compilation error:
animal.run();

Downcasting refers to converting a superclass object to subclass type. Downcasting is performed


when:
a superclass object is assigned to a variable of subclass type, or
a superclass object is passed to a method or constructor where the subclass type is expected
If Dog is a subclass of Animal , then the following assignment is an example of downcasting:
Dog dog = new Animal(); //-- compilation error
As superclass defines less number of methods and attributes than its subclasses, a superclass object
can’t take the place of its subclasses. For this reason, the above assignment will result in compilation
error. You can tell the compiler that the above assignment is fine by explicitlyconverting
the Animal object to Dog type, as shown here:
Dog dog = (Dog) new Animal(); //-- no compilation error

In the above assignment, (Dog) tells the compiler that the Animal object is converted to Dog type before
it is assigned to the dog variable. As we’ve explicitly specified the conversion of Animal object to Dog
type, the compiler no longer complains about the assignment. Later in this chapter, we’ll see that the
above statement results in an exception (which results in abrupt termination of the program) when the
program is executed. This shows that you can change your program to make compiler happy, but that
doesn’t mean your program will work correctly when executed.
Downcasting also needs to be performed when passing a superclass object to a method or constructor
that accepts the subclass type. For instance, consider the following method:
public void doMore(Dog dog) { }

The doMore method accepts Dog type, but you can pass the Animal superclass object to it, as shown here:
Dog dog = (Dog) new Animal();
doMore(dog);

Notice that you need to explicitly downcast the Animal object to Dog type before passing it tothe doMore
method. Later in this chapter, we’ll see that downcastingof Animal object to Dog type results in
exception when the program is executed.
NOTE The concepts of upcasting and downcasting are similar to widening and narrowing
conversions (refer chapter 2), respectively. The (<type>) operator used for performing narrowing
conversions and downcasting is referred as a cast operator.
Method return type and upcasting
If a method’s return type is X, then the method must return an object of X or its subclass (that is,
subtype). For instance, consider the following method:
public Animal getPet() {
return animal;
}

The getPet method must return an object of Animal class or its subclass. If the returned object is a
subtype of Animal , the returned object is upcastedto Animal type.
You can make any class as a subclass or superclass of another class. But, the inheritance relationship
is deemed correct only if superclass and its subclasses satisfy the is-a relationship.
Inheritance and is-a relationship
In inheritance, a superclass and its subclasses should satisfy is-a relationship. If you can say, X is-a
Y (where X is thesubclass and Y is the superclass), it means the inheritance relationship is correct.
Otherwise, you are creating an incorrect inheritance relationship in your program.
For instance, consider the following inheritance examples that we’ve seen so far in this chapter:
Dog (subclass) is-a Animal (superclass)
CurrentAccount (subclass) is-a Account (superclass)
SavingsAccount (subclass) is-a Account (superclass)
RedCar (subclass) is-a Car (superclass)
DogOwner (subclass) is-a Person (superclass)
As the above examples show, you can easily identify is-a relationship between a superclass and its
subclasses.
Let’s now look at inheritance examples that don’t represent an is-a relationship:
Animal (subclass) is-a Dog (superclass) – incorrect because Animal represents all animals not
just Dog
Car (subclass) is-a Dog (superclass) – incorrect because Car and Dog have no relationship
Java supports multi-level inheritance. Let’s look at some examples of multi-level inheritance.
IMPORTIt is recommended that you import the multilevel-inheritance project into your Eclipse IDE.
Multi-level inheritance
So far we’ve only seen examples of single-level inheritance, that is, a class inherits from another
class. In Java, inheritance can span multiple levels. For instance, the following diagram shows
that Bulldog class inherits from Dog class,which in turn inherits from Animal class:

Animal ’s
class members are inherited by Dog class, and Dog ’s class members (including the inherited
class members of Animal class) are inherited by Bulldog class.This means, Bulldog implicitly inherits class
members of Animal class. As in the case of single-level inheritance, creating a Bulldog object first
creates a Dog object, which in turn first creates an Animal object.
The following listing shows the Animal class that represents an animal:
Listing 6-18 Animal class
Project: multilevel-inheritance
Source location: src\com\sample\Animal.java
1 package com.sample;
2
3 public class Animal {
4 private String category;
5
6 public Animal(String category) {
7 this.category = category;
8 System.out.println("Animal's constructor called");
9 }
10
11 public String getCategory() {
12 return category;
13 }
14 }

The category attribute (line #4) represents the category (dog, cat, bird, and so on) to which the Animal
belongs. The value for the category attribute is supplied as an argument to Animal ’s constructor (line
#6).The getCategory method (line #11) returns thevalue of category attribute.
The following listing shows the Dog subclass of Animal :
Listing 6-19 Dog class
Project: multilevel-inheritance
Source location: src\com\sample\Dog.java
1 package com.sample;
2
3 public class Dog extends Animal {
4 private String breed;
5
6 public Dog(String breed) {
7 super("Dog");
8 this.breed = breed;
9 System.out.println("Dog's constructor called");
10 }
11
12 public String getBreed() {
13 return breed;
14 }
15 }
As Dog class is a subclass of Animal , it inherits getCategory method of Animal class. The breed attribute
(line #4) specifies the breedof the Dog . The value for the breed attribute is supplied as an argument
to Dog ’s constructor (line #6). Dog ’s constructor calls Animal ’s constructor (line #7) to create an Animal
object whose category attribute value is "Dog" .
The following listing shows the Bulldog class that inherits from Dog class:
Listing 6-20 Bulldog class
Project: multilevel-inheritance
Source location: src\com\sample\Bulldog.java
1 package com.sample;
2
3 public class Bulldog extends Dog {
4 private String dogName;
5 private float dogWeight;
6 private float lifespan;
7
8 public Bulldog(String dogName, float dogWeight, float lifespan) {
9 super("Bulldog");
10 this.dogName = dogName;
11 this.dogWeight = dogWeight;
12 this.lifespan = lifespan;
13 System.out.println("Bulldog's constructor called");
14 }
15
16 public String getDogName() {
17 return dogName;
18 }
19
20 public void printValues() {
21 System.out.println("Animal " + super.getCategory() + ", breed "
22 + super.getBreed() + ", dogName " + dogName + ", dogWeight "
23 + dogWeight + ", lifespan " + lifespan);
24 }
25 }
Bulldog defines dogName , dogWeight and lifespan attributes
that are set by Bulldog ’s constructor. Bulldog ’s
constructor calls Dog ’s constructor (line #9) that creates a Dog object with "Bulldog" as breed.
Bulldog class inherits getBreed method of Dog class and also the getCategory method of Animal grandparent
class. The printValues method prints Bulldog ’s attributes apart from category (line #21) and breed (line
#22) information.
The following listing shows the BulldogTest class whose main method creates an instance of Bulldog and
calls its printValues method:
Listing 6-21 BulldogTest class
Project: multilevel-inheritance
Source location: src\com\sample\BulldogTest.java
1 package com.sample;
2
3 public class BulldogTest {
4 public static void main(String args[]) {
5 Bulldog dog = new Bulldog("Max", 12.2f, 14.5f);
6 dog.printValues();
7 }
8 }

If you execute BulldogTest ’s main method, you’ll get the following output:
Animal's constructor called
Dog's constructor called
Bulldog's constructor called
Animal Dog, breed Bulldog, dogName Max, dogWeight 12.2, lifespan 14.5

As in the case of single-level inheritance, constructors of all the classes involved in multi-level
inheritance are called, starting from the top-most class in the inheritance hierarchy. The above output
shows that call to Bulldog ’s constructor first invokes Animal ’s constructor, followed by Dog ’s
constructor, and in the end Bulldog ’s constructor is called. The following figure shows what
happenswhen BulldogTest ’s main method createsa Bulldog object:

The above figure shows that a Dog object is created corresponding to the Bulldog object, and
an Animal object is created corresponding to the Dog object. Animal ’s category attribute is set to "Dog" and
Dog ’s breed attribute is set to "Bulldog" . As in the case of single-level inheritance, super keyword is used
by classes in multi-level inheritance hierarchy to access their superclass’s constructors and class
members.
Let’s now look at another important object-oriented programming concept - polymorphism.
IMPORTIt is recommended that you import the polymorphism project into your Eclipse IDE.
6-4 Polymorphism
Polymorphism means an object can take 'multiple forms'. Polymorphism is possible in Java because
subclasses can override instance methods defined in the superclass, and
an object of a subtype can be assigned to a variable of supertype
Let’s look at an example that demonstrates the effect of assigning an object of subtype to a variable of
supertype or vice versa, and along the way learn about polymorphism.
The following listing shows the Animal class:
Listing 6-22 Animal class
Project: polymorphism
Source location: src\com\sample\Animal.java
1 package com.sample;
2
3 public class Animal {
4 public String name = "someAnimal";
5 public static String breed = "ANIMAL";
6
7 public void makeSound() {
8 System.out.println("None");
9 }
10
11 public static void makeMoreSound() {
12 System.out.println("Animal is making more sound");
13 }
14 }
Animal class defines following attributes and methods:
name instance variable (line #4) with value "someAnimal"
breed static variable (line #5) with value "ANIMAL"
makeSound instance method (line #7) – prints "None" on the console
makeMoreSound static method (line #11) – prints "Animal is making more sound" on the console
The following listing shows the Dog class that inherits from Animal class:
Listing 6-23 Dog class
Project: polymorphism
Source location: src\com\sample\Dog.java
1 package com.sample;
2
3 public class Dog extends Animal {
4 public String name = "Max";
5 public static String breed = "Andalusian Hound";
6
7 public void makeSound() {
8 System.out.println("Bow wow");
9 }
10
11 public static void makeMoreSound() {
12 System.out.println("Bow wow Bow wow Bow wow Bow wow");
13 }
14 }

Dog class defines the same set of attributes and methods as the Animal class but the attributes have
different values and methods print different messages on the console.
Listing 6-24 shows PolymorphismTest class whose main method performs the following tasks:
creates a Dog object and assigns it to a variable of type Animal (line #5)
creates an Animal object and assigns it to a variable of type Dog (line #13)
access attributes and call methods of the objects
Listing 6-24 PolymorphismTest class
Project: polymorphism
Source location: src\com\sample\PolymorphismTest.java
1 package com.sample;
2
3 public class PolymorphismTest {
4 public static void main(String args[]) {
5 Animal animal = new Dog();
6 System.out.println("animal.name: --> " + animal.name);
7 System.out.println("animal.breed: --> " + animal.breed);
8 System.out.println("animal.makeSound(): --> ");
9 animal.makeSound();
10 System.out.println("animal.makeMoreSound(): --> ");
11 animal.makeMoreSound();
12
13 Dog dog = (Dog) new Animal(); terminates the program abruptly
14 System.out.println("dog.name: --> " + dog.name);
15 .....
16 }
17 }

On line #5, a Dog object (the runtime type) is created and assigned to a variable of type Animal (the
declared type). The attributes and methods of the Dog object are then accessed on line #6, #7, #9 and
#11. Similarly, on line #13, an Animal object (the runtime type) is created and assigned (that is,
downcasted) to a variable of type Dog (the declared type), and later its attributes and methods are
accessed.
If you execute PolymorphismTest ’s main method, you’ll get the following output:
The output shows that if a Dog object is assigned to a variable named animal (of type Animal ), then:
accessing name (an instance variable) and breed (a static variable) attributes using the animal
variable returnsthe values of name and breed attributes of the Animal object (refer listing 6-22)
and not that of the Dog object. This means, accessing instance and static variables of a
declared type returns values from the declared type and not from the runtime type.
calling makeSound instance methodon the animal variable invokes Dog object’s makeSound method.
This means, calling an instance method on a declared type invokes the instance method of the
runtime type and not that of the declared type.
calling makeMoreSound static method on the animal variable invokes Animal object’s makeMoreSound
method and notthe makeMoreSound method of Dog object. This means, calling a static method on
a declared type invokes the method of the declared type and not that of the runtime type.
The output also shows that the statement Dog dog = (Dog) new Animal() (refer line #13 in listing 6-24)
throws an exception during program execution. The exception is thrown because Animal is nota
subtype of Dog , and we attempted to downcast an Animal object to Dog type. The output shows the
following exception message:
"com.sample.Animal cannot be cast to com.sample.Dog"
An exception represents a problem with the program that abruptly ends the program. For instance,
when an exception occurs while executing line #13 of PolymorphismTest ’s main method (refer listing 6-
24), none of the remaining statements in the program are executed. When an exception occurs, Java
creates an exception object with an appropriate exception message. For instance, when Animal object
is assigned to Dog type variable, Java creates a java.lang.ClassCastException object with the following
exception message: "com.sample.Animal cannot be cast to com.sample.Dog". java.lang is a pre-defined
package in Java that contains the ClassCastException class.
NOTE Exception classes in Java follow *Exception naming
convention. ClassCastException , NullPointerException and IllegalArgumentException are examples of pre-defined
exception classes in Java. In chapter 8, we’ll take an in-depth look at exceptions.
The following figure shows that Dog , Cat and Lion are subclasses of Animal class and each subclass
overrides the makeSound instance method:
Figure 6-10 Dog , Cat and Lion subclasses override the makeSound instance method
Dog ’s makeSound method prints "Bow wow", Cat ’s makeSound prints "meow" and Lion ’s makeSound prints
"roar". If an instance of Dog is assigned to a variable of type Animal , calling the makeSound method will
invoke Dog object’s makeSound method and print "Bow wow" on the output. This means, the Animal will
behave like a Dog . Similarly, if a Cat object is assigned to a variable of type Animal , calling
the makeSound method will invoke Cat object’s makeSound method and print "meow" on the output. This
means, the Animal will behave like a Cat . This is polymorphism– the Animal takes 'multiple forms'
(like, Dog , Cat and Lion ) depending upon which object is referenced bythe Animal type variable at the
time of program execution.
NOTE You should note that polymorphic nature is only depicted by instance methods. The instance
and static variables, and static methods are not polymorphic in nature.
Hiding superclass’s instance (or static) variables and static methods
If a subclass redefines a superclass instance (or static) variable or static method, it is referred to as
hiding (and not overriding). The subclass hides the instance (or static) variable or static method
defined in the superclass. If a subclass redefines a superclass instance method, it is referred to as
overriding (and not hiding). As we saw in the Animal - Dog example, overriding is polymorphic in
nature (that is, the runtime type matters) and hiding is non-polymorphic in nature (that is, the declared
type matters).
Let’s look at how superclass’s instance variables are hidden in subclasses.
Hiding instance variables
If a subclass instance variable has the same nameas a superclass instance variable, the superclass
instance variable is hidden from the subclass. In such cases, the only way to access the superclass
instance variable is via the super keyword.
Consider the following Car class that defines a color instance variable:
1 public class Car {
2 protected String color = "BLACK";
3 .....
4 }
The following listing shows the RedCar class that represents a "RED" colored car:
Listing 6-25 RedCar class – instance variable hiding
1 public class RedCar extends Car {
2 protected String color = "RED";
3 .....
4 public void printColor() {
5 System.out.println("Parent car color : " + super.color);
6 System.out.println("Child car color " + this.color);
7 }
8 }

As the RedCar class extends Car class, the color instance variable is inherited by RedCar . In
the RedCar class, the color instance variable is redefined and its value is set to "RED". As
the RedCar ’s color instance variable hides the superclass’s color instance variable, the only way to
access the superclass’s color variable is by using the super keyword (line #5).
Hiding static variables and methods
A static variable defined in the subclass hides the static variable with the same name in the
superclass. Similarly, a static method defined in the subclass hides the static method with the same
signature in the superclass. In such cases, subclasses can use the name of the superclass to access the
static variable or static method defined in the superclass.
Let’s now look at method and constructor overloading.
IMPORTIt is recommended that you import the overloading project into your Eclipse IDE.
6-5 Method and constructor overloading
Method overloading refers to defining multiple methods with the same name in a class. The methods
differ only in the number and/or types of arguments. Similarly, constructor overloading refers to
defining multiple constructors of a class that differ in the number and/or types of arguments.
The following listing shows the Dog class of overloading project that uses both method and constructor
overloading:
Listing 6-26 Dog class – method and constructor overloading
Project: overloading
Source location: src\com\sample\Dog.java
1 package com.sample;
2
3 public class Dog {
4 private int totalDistance;
5 private int defaultSpeed;
6
7 public Dog(int defaultSpeed) {
8 this.defaultSpeed = defaultSpeed;
9 }
10
11 public Dog(int defaultSpeed, int initialDistance) {
12 this.defaultSpeed = defaultSpeed;
13 this.totalDistance = initialDistance;
14 }
15
16 public void run(int time) {
17 totalDistance = totalDistance + defaultSpeed * time;
18 }
19
20 public void run(float time) {
21 totalDistance = totalDistance + defaultSpeed * time;
22 }
23 }

Dog class defines two constructors that differ in the number of arguments – the constructor on line #7
accepts defaultSpeed argument, and the constructor on line #11 accepts defaultSpeed and initialDistance as
arguments. Dog class also defines two run methods that differ in the typeof their argument – the run
method on line #16 accept an int type argument, and the run method on line #20 accepts a float type
argument.
You can’t overload a method by simply defining another method with a different return type. For
instance, consider the following two methods in a class:
public int run(int time) { ..... }
public float run(int time) { ..... }

The first run method returns an int type and the second one returns a float type. If you call run(100) , Java
won’t know which run method to call; therefore, these two methods are considered duplicate and
can’t be defined in the same class.
NOTE We’veused System.out.println method to write strings and primitive types to the output. This was
possible because the out staticvariable of System class is an instance of PrintWriter class that defines
multiple overloaded println methods that accept different argument types.For instance, println(int) writes
an int type, println(float) writes a float type, println(String) writes a String type, and so on.
Let’s now look at the java.lang.Object class of Java that each class implicitly inherits from.
IMPORTIt is recommended that you import the objectclass project into your Eclipse IDE.
6-6 java.lang.Object class
A Java class cannot explicitly inherit from more than one class. For instance, consider the following
class definition:
public class X extends Y, Z { ..... }
The class X inherits from both Y and Z classes. As a class cannot explicitly inherit from multiple
classes, the above class definition results in compilation error.
Java’s java.lang.Object class is implicitly inherited by all the classes in Java. For instance, the following
class X inherits from both Y and java.lang.Object classes:
public class X extends Y { ..... }
NOTEAs Object class is implicitly inherited by all the Java classes, all Java classes are
subtypeof Object .
As an Object class is a superclass of all the classes in Java, you can assign anyobject to an Object type
variable. For instance, the following assignments are correct:
Object objDog = new Dog();
Object objAccount = new SavingsAccount();

The Dog and SavingsAccount objects are automatically upcastedto Object type.
Similarly, if you specify a constructor or method argument to be of Object type, you can pass any
object as argument. For instance, you can pass Dog or SavingsAccount object as argument to the
following doSomething method:
public void doSomething(Object obj) { }

The object passed tothe doSomething method is automatically upcastedto Object type.
If you specify Object as the return type of a method, then any object can be returned by the method. For
instance, the following method can return any object:
public Object didSomething() { }

The object returned by didSomething method is automatically upcastedto the Object type.
NOTE As Java classes cannot explicitly inherit from multiple classes, it is often said that Java
doesn’t support multiple inheritance
Object class defines the following methods that are inherited by all the classes in Java:
– this method checks if the current object is 'equal to'the object
public boolean equals(Object object)
passed as argument. As the equals method accepts an argument of type Object , and all the
classes in Java implicitly inherit from the Object class, you can pass any object to the equals
method.
– this method returns the class of the object. The final keyword used in
public final Class getClass()
this method definition is explained in chapter 7.
– this method returns the hash code value for the object. The hash code for
public int hashCode()
an object doesn’t change during the execution of the program. But, it may change if the
program is executed again.
public String toString() – this method returns a string (or textual) representation of the object
NOTE Object class defines half-a-dozen more methods, but we’ll not be covering all of them in this
book
Let’s look at the usage of above mentioned methods.
The following listing shows the Dog class of objectclass project that defines a name instance variable and
a getName instance method:

Listing 6-27 Dog class


Project: objectclass
Source location: src\com\sample\Dog.java
1 package com.sample;
2
3 public class Dog {
4 private String name;
5
6 public Dog(String name) {
7 this.name = name;
8 }
9
10 public String getName() {
11 return name;
12 }
13 }

As the Dog class implicitly inherits from the Object class, it inherits hashCode , getClass , toString and equals
instance methodsof the Object class. The following listing shows the ObjectTest class’s main method that
creates two instances of Dog class and calls the methods inherited from the Object class:
Listing 6-28 ObjectTest class– calling inherited methods of Object class
Project: objectclass
Source location: src\com\sample\ObjectTest.java
1 package com.sample;
2
3 public class ObjectTest {
4 public static void main(String args[]) {
5 Dog dogMax = new Dog("Max");
6 Dog dogBuddy = new Dog("Buddy");
7
8 System.out.println("dogMax.hashCode() --> " + dogMax.hashCode());
9 System.out.println("dogBuddy.hashCode() --> " + dogBuddy.hashCode());
10
11 System.out.println("dogMax.getClass() --> " + dogMax.getClass());
12 System.out.println("dogBuddy.getClass() --> " + dogBuddy.getClass());
13
14 System.out.println("dogMax.toString() --> " + dogMax.toString());
15 System.out.println("dogBuddy.toString() --> " + dogBuddy.toString());
16
17 System.out.println("dogMax.equals(dogBuddy) --> " + dogMax.equals(dogBuddy));
18 }
19 }
On line #5 and #6, we create two Dog objects – dogMax and dogBuddy . And, later we
call hashCode , getClass and toString methods these Dog objects inherited from the Object class. On line #17,
we call dogMax ’s equals method to check if dogMax object is 'equal to' dogBuddy object.
If you run ObjectTest ’s main method, you’ll get the following output:
dogMax.hashCode() --> 31168322
dogBuddy.hashCode() --> 17225372
dogMax.getClass() --> class com.sample.Dog
dogBuddy.getClass() --> class com.sample.Dog
dogMax.toString() --> com.sample.Dog@1db9742
dogBuddy.toString() --> com.sample.Dog@106d69c
dogMax.equals(dogBuddy) --> false

The above output shows:


hashCodemethod returns an integer value. This value is guaranteed to remain same till the
program ends.
getClass methodreturns a Class object that represents the class of the object
toString method returns a textual representation of the object. The toString method in
the Object class is defined to return a String object with the following text:
<class-name>@<hash-code-in-hex>
here, <class-name> is the fully-qualified name of the class of the object, and <hash-
code-in-hex> is the hash code of the object in hexadecimal format. In hexadecimal
format, a number is represented usingdigits from 0-9 and alphabets from a-f .
equals methodreturns false when dogMax is compared to dogBuddy object.This means, dogMax is
not 'equal to' dogBuddy . The equals method in the Object class compares the two objects using ==
operator (explained in chapter 2), which works fine for comparing primitive types but not for
comparing objects. As classtype variables hold memory address of the object, the ==
compares the memory addresses of the objects. For this reason, the equals method returns true
only if objects being compared have the same memory address. As there is only a single
object at a given memory address, equals method returns true only if the objects being
compared are same.
Let’s take an in-depth look at the equals method of Object class.
equals method
A class canoverride the equals methodof the Object class to provide custom logic for determining
equality of objects. For instance, the java.lang.String class in Java overrides the equals method and treats
two String objects as equal if they contain the same textual value.
The following listing showsthe StringEquality class of objectclass project thatcreates multiple String objects
and compares them using the equals method and == operator:
Listing 6-29 StringEquality class – comparing String objects
Project: objectclass
Source location: src\com\sample\StringEquality.java
1 package com.sample;
2
3 public class StringEquality {
4 public static void main(String args[]) {
5 String str1 = "some text";
6 String str2 = "some text";
7 String str3 = new String("some text");
8 String str4 = "some more text";
9
10 if(str1.equals(str2)) {
11 System.out.println("str1.equals(str2) is true");
12 }
13 if(str1 == str2) {
14 System.out.println("str1==str2 is true");
15 }
16 if(str2.equals(str3)) {
17 System.out.println("str2 and str3 are equal");
18 }
19 if(str2 == str3) {
20 System.out.println("str2==str3 is true");
21 }
22 if(str3.equals(str4)) {
23 System.out.println("str3 and str4 are equal");
24 }
25 }
26 }

In Java, any text in double quotes represents a String object. When you assign a textual value (also
referred to as a String literal) in double quotes to a String type variable, a String object is created and
its memory address is assigned to the variable. For instance, on line #5, a String object with text "some
text" is created and its memory address isassigned to str1 variable. Another approach to creating String
objectsis to use the String class’s constructor, as shown on line #7.
The following figure shows how the String objects created on line #5, #6, #7 and #8 are represented in
computer memory:

The above figure shows that String objects created using literals are placed into a special memory
area called as String literal pool. And, String objects created using String class’s constructor are placed
outside the literal pool.
Stringobjects in the literal pool are reused by the JVM. For instance, if two or more String variables
are assigned the same literal, they refer to the same String object in the literal pool. In the above
example, str1 and str2 variables are assigned the same literal "some text" ; therefore, they refer to the
same String object in the literal pool. String objects created via the constructor are not put in the literal
pool, and are also not reused. For this reason, str3 variable refers to a String object outside the literal
pool.
String class overrides the equals method such that it compares contents (that is, the textual value)
of String objects and not their memory addresses.For instance, str1.equals(str2) on line #10 returns true
only if str1 String object contains the same textual valueas str2 String object. Let’s look at the result of
evaluation of different String comparison expressions used in listing 6-29:
– returns true . As str1 and str2 refer to the same "some
str1.equals(str2) text" String object in the
literal pool, they have the same textual value.
str1 == str2 – returns true because both str1 and str2 refer to the same String object in the literal
pool
str2.equals(str3) – returns true because both str2 and str3 refer to String objects with same "some
text" value
str2 == str3 – returns false because str2 and str3 refer to different String objects in memory
str3.equals(str4) –returns false because str3 refers to a String object with value "some text" ,
and str4 refers to a String object with value "some more text"
Let’s now look at an example that shows how Object ’s equals method is typically overridden in classes.
Overriding equals method
The following example listing shows the Cat class of objectclass project that overrides
the Object class’s equals method:
Listing 6-30 Cat class – overriding equals method
Project: objectclass
Source location: src\com\sample\Cat.java
1 package com.sample;
2
3 public class Cat {
4 private String name;
5 .....
6 public String getName() {
7 return name;
8 }
9
10 public boolean equals(Object object) {
11 Cat cat = (Cat) object;
12 if(this.getName().equals(cat.getName())) {
13 return true;
14 } else {
15 return false;
16 }
17 }
18 }
Cat class defines a name instance variable (of type String ) that represents the name of thecat.
The getName method returns the name instance variable. Cat class overrides the equals method inherited
from Object class such that a Cat object is considered 'equal to'another Cat object if they have the same
name.The equals method’s object argument (refer line #10) represents the Cat object with which we
want to compare the current Cat object. On line #11, the object argument (of type Object ) is
downcastedto Cat typeso that we can call the getName method of the passed Cat object for comparison.
On line #12, this.getName() returns the name of the current Cat object, and cat.getName() returns the name
of the Cat objectthat was passed as argument to equals method. The equals method of String is then used
to compare the cat names.
The following listing shows the CatEquality class of objectclass project whose main methodcreates Cat
objects and comparesthem using equals method:
Listing 6-31 CatEquality class – comparing Cat objects
Project: objectclass
Source location: src\com\sample\CatEquality.java
1 package com.sample;
2
3 public class CatEquality {
4 public static void main(String args[]) {
5 Cat misty = new Cat("misty");
6 Cat kitty = new Cat("kitty");
7 Cat misty2 = new Cat("misty");
8
9 System.out.println("misty.equals(kitty) --> " + misty.equals(kitty));
10 System.out.println("misty.equals(misty2) --> " + misty.equals(misty2));
11 }
12 }

Cat objects are created on line #5, #6 and #7. Cat objects are then compared using the equals method
defined in the Cat class. If you run CatEquality ’s main method, you’ll get the following output:
misty.equals(kitty) --> false
misty.equals(misty2) --> true

As both misty and misty2 cats have the same name, misty.equals(misty2) expression evaluates to true .
Downcasting and exception
We saw in section 6-3 that when an object of Animal (the superclass) was downcasted to the Dog type
(the subclass), it resulted in exception during program execution. In listing 6-30, we
downcasted Object type (the superclass) to Cat type (the subclass) but that didn’tresult in any
exception during execution of equals method. This is because the actualobject passed to the equals
method is a Cat object (refer listing 6-31). While performing downcastingfrom Object to Cat type, JVM
finds that the actual object is indeed a Cat object; therefore, it doesn’t throw an exception and allows
the downcasting to happen.
Let’s now look at situations in which you should override the toString method of Object class.
toString method
As mentioned earlier, Object ’s toString method returns a String that contains object’s class and hash code
information. As this information is not of much use, you should override the toString method to return
a String that contains relevant information about the object.For instance, the following listing shows
the Person class of objectclass project whose toString method returns details of its attributes:
Listing 6-32 Person class – overriding toString method
Project: objectclass
Source location: src\com\sample\Person.java
1 package com.sample;
2
3 public class Person {
4 private String firstName;
5 private String lastName;
6 private int age;
7 private int numberOfChildren;
8 private boolean isMarried;
9 private char gender;
10 private boolean isWorking;
11 .....
12 public String toString() {
13 return "Person [firstName=" + firstName + ", lastName=" + lastName
14 + ", age=" + age + ", numberOfChildren=" + numberOfChildren
15 + ", isMarried=" + isMarried + ", gender=" + gender + ", isWorking=" + isWorking
16 + "]";
17 }
18 }

The toString method returns a String containing names and valuesof all the attributes of the Person class.
The following listing shows the PersonTest class of objectclass project whose main method creates a Person
object and prints the string returned by Person ’s toString method:
Listing 6-33 PersonTest class
Project: objectclass
Source location: src\com\sample\PersonTest.java
1 package com.sample;
2
3 public class PersonTest {
4 public static void main(String args[]) {
5 Person person = new Person("John", "J", 20, 0, false, 'M', false);
6 System.out.println(person);
7 }
8 }
The call to System.out.println(person) method (line #6) invokes the println(Object) method of PrintWriter class
thatcalls the toString method of the person object and writes the returned string to the output.If you
run PersonTest ’s main method, you’ll get the following output:
Person [firstName=John, lastName=J, age=20, numberOfChildren=0, isMarried=false, gender=M, isWorking=false]

The output shows that System.out.println(person) writes the String returned bycalling person object’s toString
method.
QUIZ
6-1: Which of the following statements are true about encapsulation in Java?
a) encapsulation refers to bundling together of attributes and the methods that operate on
those attributes
b) encapsulation is also referred to as data hiding
c) a fully-encapsulated class may define public attributes
d) a fully-encapsulated class must not be defined public methods
6-2: Consider the following Shape and Rectangle classes:
1 public class Shape {
2 private String name;
3
4 public Shape() {
5 }
6
7 public Shape(String name) {
8 this.name = name;
9 }
10
11 public String getName() {
12 return name;
13 }
14 }

1 public class Rectangle extends Shape {


2 public Rectangle() {
3 super("Rectangle");
4 }
5
6 public Rectangle(String name) {
7 super();
8 }
9 }

What would be the output from running the following main method?
1 public static void main(String args[]) {
2 Rectangle rectangle = new Rectangle();
3 Rectangle anotherRectangle = new Rectangle("A rectangle");
4
5 System.out.println("rectangle's name : " + rectangle.getName());
6 System.out.println("anotherRectangle's name : " + anotherRectangle.getName());
7 }

6-3: Consider the following Shape and Rectangle classes:


1 public class Shape {
2 protected String name;
3
4 public String getName() {
5 return name;
6 }
7 }
1 public class Rectangle extends Shape {
2
3 public Rectangle(String name) {
4 super.name = name;
5 }
6
7 protected String getName() {
8 return name;
9 }
10 }

Which of the following statements are true about the above classes?
a) Rectangle ’s constructor sets the value of Shape ’s name instance variable
b) Rectangle class will fail to compile because Shape class doesn’t define a constructor that
accepts a String type argument
c) Rectangle ’s getName method returns the Shape ’s name instance variable
d) Rectangle ’s getName method overrides Shape ’s getName method

6-4: Consider the following getSomething method of a class:


String getSomething() { ..... }

Which of the following methods correctly override the getSomething method?


a) String getSomething(String str) { ..... }
b) private String getSomething() { ..... }
c) protected String getSomething() { ..... }
d) public String getSomething() { ..... }
e) void getSomething() { ..... }

6-5: Let’s say the rectangle variable refers to a Rectangle object and the shape variable refers to
a Shape object. If Rectangle is a subclass of Shape , which of the following statements will compile
successfully?
a) rectangle = shape;
b) shape = rectangle;
c) rectangle = (Rectangle)shape;
d) shape = (Shape)rectangle;

6-6: Consider the following Shape class and its Rectangle and Circle subclasses:
1 public class Shape {
2 protected static int shapeObjectsCounter; static variable
3
4 public Shape() {
5 shapeObjectsCounter++; increments shapeObjectsCounter variable
6 }
7
8 public void draw() { instance method
9 System.out.println("Do nothing");
10 }
11
12 public static void getCounter() { static method
13 System.out.println(shapeObjectsCounter);
14 }
15 }

1 public class Rectangle extends Shape {


2 protected int length;
3 protected int breadth;
4 protected static int rectangleObjectsCounter; static variable
5
6 public Rectangle(int length, int breadth) {
7 this.length = length;
8 this.breadth = breadth;
9 rectangleObjectsCounter++; increments rectangleObjectsCounter variable
10 }
11
12 public void draw() { instance method
13 System.out.println("Drawing a rectangle");
14 }
15
16 public static void getCounter() { static method
17 System.out.println(rectangleObjectsCounter);
18 }
19 }

1 public class Circle extends Shape {


2 protected int radius;
3 protected static int circleObjectsCounter; static variable
4
5 public Circle(int radius) {
6 circleObjectsCounter++; increments circleObjectsCounter variable
7 this.radius = radius;
8 }
9
10 public void draw() { instance method
11 System.out.println("Drawing a circle");
12 }
13
14 public static void getCounter() { static method
15 System.out.println(circleObjectsCounter);
16 }
17 }

The following main method creates Rectangle and Circle objects and calls their methods:
1 public static void main(String args[]) {
2 Shape shape_1 = new Rectangle(10, 10);
3 Rectangle rectangle = new Rectangle(20, 30);
4
5 Circle circle = new Circle(5);
6
7 shape_1.draw();
8 rectangle.draw();
9 circle.draw();
10
11 shape_1.getCounter();
12 rectangle.getCounter();
13 circle.getCounter();
14 }

Which of the following statements are true?


a) shape_1.draw() method call on line #7 prints "Do nothing"
b) rectangle.draw() method call on line #8 prints "Do nothing"
c) circle.draw() method call on line #9 prints "Do nothing"
d) shape_1.getCounter() method call on line #11 prints 2
e) rectangle.getCounter() method call on line #12 prints 2
f) circle.getCounter() method call on line #13 prints 1

6-7: Which of the following combinations of method definitions are examples of method
overloading?
a) public Shape getShape() { ..... } and public Rectangle getShape() { ..... } – you can assume that Rectangle is
a subclass of Shape
b) public Shape getShape() { ..... } and public int getShape() { ..... }

c) public Shape getShape(int x, int y) { ..... } and public Shape getShape(int y, int x) { ..... }
d) public Shape getShape(int x) { ..... } and public Shape getShape(float x) { ..... }
e) public Shape getShape(int x, float y) and public Shape getShape(float y, int x) { ..... }

6-8: Consider the following main method that compares two String objects:
1 String str_1 = "xyz";
2 String str_2 = "xyz";
3
4 if(str_1 == str_2) {
5 System.out.println("same");
6 } else {
7 System.out.println("different");
8 }
What would be the output from running the above program?
6-9: Which of the following statements are trueabout java.lang.Object class?
a) Object ’s hashCode method returns an integer value that remains unchanged even if you run
the program multiple times
b) Object ’s toString method returns a textual representation of an object
c) Object ’s equals method compares two objects using == operator
d) All classes implicitly inherit from the Object class
6-7 Summary
In this chapter, we saw how concepts of encapsulation, inheritance and polymorphism are applied in
the Java programming language.We also looked at some of the methods defined by the Object class that
are implicitly inherited by all the Java classes. We also looked at how JVM reuses String objects by
using a literal pool. In the next chapter, we’ll look at how to separate a method definition from its
implementation by using abstract classes and interfaces.
Chapter 7 – Abstract classes and interfaces
7-1 Introduction
In the context of inheritance, we saw that a superclass defines common attributes and methods that are
inherited by subclasses. The superclass provides default implementation for the methods, which may
be overridden by the subclasses.For instance, in chapter 6, the Account superclass defined a debit
method, which was overridden by the CurrentAccount subclass. There are some drawbacks associated
with using a superclass to define common methods and attributes:
any class can create an instance of the superclass and call its methods or access its attributes,
which may not be desirable. For instance, the Account class (refer listing 6-2) of chapter 6
was only meant to define common methods and attributes for SavingsAccount and CurrentAccount
subclasses. But, it was possible for aclass to create an instance of Account and directly call its
methods and access its attributes.
the superclass must provide default implementations for methods. For instance, Account (refer
listing 6-2 of chapter 6) class provided default implementations for credit and debit methods.
you can’t force subclasses to override specific methods of the superclass. For instance, there
is no way to force SavingsAccount and CurrentAccount subclassesto override debit and credit
methodsof Account superclass (refer listing 6-2 of chapter 6).
The above drawbacks are addressed in Java by using abstract classes and interfaces.
In this chapter, we’ll look at how abstract classes and interfaces are used to separate method
definition from its implementation. We’ll also look at the final keyword in Java that is used for
restricting inheritance of classes and overriding of methods.
Let’s begin by looking at abstract classes.
7-2 Abstract classes
An abstract class is a class that defines one or more abstract methodsusing the abstract keyword. An
abstract class represents an incomplete class, and is meant to be inherited by other classes. A class
inherits from an abstract class using the extends keyword.
NOTE A class that isn’t defined abstract, is referred to as a concrete class. The classes that we’ve
seen so far in this book are examples of concrete classes. You can create an instance of the concrete
class, but you can’t create an instance of an abstract class.
IMPORTIt is recommended that you import the shapes project into your Eclipse IDE.
Let’s look at an example that shows pitfalls of using concrete classes as superclasses.
Using a concrete class as a superclass
Let’s say that you have to write a program that calculates area and circumference of 2-dimensional
shapes like rectangle, circle, square, pentagon, and so on. The way area and circumference is
calculated depends on the shape. For instance, in the case of rectangle, area is length x breadth and
circumference is 2 x (length + breadth).
As each shape (rectangle, square, and so on) needs area and circumference methods, we create a Shape
class that defines area and circumference methods. The shape-specific classes like Rectangle , Circle , and so
on, inherit from the Shape class and override the area and circumference methods to provide shape-
specific implementation of these methods.
The following listing shows the Shape classof shapes project:
Listing 7-1 Shape class
Project: shapes
Source location: src\com\shape\Shape.java
1 package com.shape;
2
3 public class Shape {
4 private String name;
5
6 public Shape(String name) {
7 this.name = name;
8 }
9
10 public String getName() {
11 return name;
12 }
13
14 public int area( ) {
15 return 0;
16 }
17
18 public int circumference( ) {
19 return 0;
20 }
21
22 public String toString( ) {
23 return "Shape named " + name + " has area " + area()
24 + " and circumference " + circumference();
25 }
26 }

Shape class’s name instance variable is the name of the shape, which is set by the subclasses.The area
(line #14) and circumference (line #18) methods simplyreturn 0 . Shape class overrides the toString method
(line #22) to return name, area and circumference of the shape.
The following listing shows the Rectangle class that inherits from the Shape class:
Listing 7-2 Rectangle class – subclass of Shape class
Project: shapes
Source location: src\com\shape\Rectangle.java
1 package com.shape;
2
3 public class Rectangle extends Shape {
4 private int length;
5 private int breadth;
6
7 public Rectangle(int length, int breadth) {
8 super("Rectangle");
9 this.length = length;
10 this.breadth = breadth;
11 }
12 public int area( ) {
13 return length * breadth;
14 }
15 public int circumference( ) {
16 return 2*(length + breadth);
17 }
18 }
Rectangle class inherits from the Shape class and overrides the area and circumference methods.
The length and breadth instance variables representthe two sides of the rectangle. Rectangle ’s constructor
calls Shape ’s constructor (refer line #8) to set the value of Shape ’s name instance variable to
"Rectangle". If the Rectangle class does not override area and circumference methods, there is no way to
force Rectangle class (or any subclass of Shape class) to override these methods.
The following example listing shows the ShapeTest class whose main method creates a Rectangle and
a Shape object, and writes their string representation to the output:
Listing 7-3 ShapeTest class
Project: shapes
Source location: src\com\shape\ShapeTest.java
1 package com.shape;
2
3 public class ShapeTest {
4 public static void main(String args[]) {
5 Rectangle rectangle = new Rectangle(20, 10);
6 System.out.println(rectangle);
7
8 Shape shape = new Shape("Square");
9 System.out.println(shape);
10 }
11 }

We createdthe Shape class only to define common methods, area and circumference , that a shape-specific
subclass (like Rectangle , Square , and so on) must implement. But, we directly created a Shape object on
line #8 and used it in the program. Shape class is incomplete in itself because it doesn’t represent any
shape; it is meant only to act as a superclass for different shape classes.
If you run ShapeTest ’s main method, you’ll get the following output:
Shape named Rectangle has area 200 and circumference 60
Shape named Square has area 0 and circumference 0

The output shows that using Shape object directly resulted in showing incorrect area and
circumference for a square shape.
Let’s now look at how the drawbacks with the Shape concrete class can be addressed by defining it as
an abstract (or incomplete) class.
Using an abstract class as a superclass
Listing 7-4 shows the Shape class of shapes project that defines abstract area (line #14)
and circumference (line #16) methods. The abstract keyword is used to specify that a method is abstract.
As abstract methods don’t have a body, no opening and closing braces have been specified
for area and circumference methods. If a class contains one or more abstract methods, then the class itself
must be defined as abstractusing the abstract keyword. As Shape class contains abstract methods,
the Shape class has been defined as abstract (line #3).
NOTE An abstract method tells what needs to be done, but leaves it to the subclasses to tell howit is
done. For instance, area and circumference methods in the Shape class tell that a shape has area and
circumference, but how it is calculated is left up to the subclasses. For this reason, it is said that
abstract classes are used to separate method definitions from their implementations. You should also
note that abstract methods are meant to be implemented by subclasses; therefore, you can’t define an
abstract method as private .

Listing 7-4 abstract Shape class


Project: shapes
Source location: src\com\sample\Shape.java
The following listing shows the Rectangle class that inherits from the abstract Shape class:
Listing 7-5 Rectangle class
Project: shapes
Source location: src\com\sample\Rectangle.java
1 package com.sample;
2
3 public class Rectangle extends Shape {
4 private int length;
5 private int breadth;
6
7 public Rectangle(int length, int breadth) {
8 super("Rectangle");
9 this.length = length;
10 this.breadth = breadth;
11 }
12 public int area() {
13 return length * breadth;
14 }
15 public int circumference() {
16 return 2*(length + breadth);
17 }
18 }

Rectangleclass inherits from the Shape class and provides implementations for area and circumference
methods.As area and circumference methods are defined abstract in the Shape superclass, Rectangle subclass
must provide their implementations.Notice that Rectangle ’s constructor calls Shape superclass’s
constructor (line #8) explicitly to set the value of Shape ’s name instance variable to
"Rectangle".As Rectangle class inherits from Shape class, Rectangle class is a subtypeof Shape .
NOTE If a subclass of an abstract class doesn’t provide implementation for an abstract method, then
the subclass must also be declared as abstract. Also, inheritance relationship between abstract class
and its subclasses is deemed correct only if the abstract class and its subclasses satisfy the is-a
relationship (refer section 6-3 of chapter 6 for more information).
The following listing shows the modified ShapeTest class that creates a Rectangle object and prints its
string representation to the output:
Listing 7-6 ShapeTest class
Project: shapes
Source location: src\com\sample\ShapeTest.java
1 package com.sample;
2
3 public class ShapeTest {
4 public static void main(String args[]) {
5 Rectangle rectangle = new Rectangle(20, 10);
6 System.out.println(rectangle);
7
8 //Shape shape = new Shape("Rectangle"); compilation error
9 //System.out.println(shape);
10 }
11 }

We’ve commented out line #8 because Shape class is an abstract class and Java doesn’t allow creating
an object of an abstract class. If you attempt to create an object of an abstract classusing the new
keyword, it’ll result in compilation error. This shows that if you define a class as abstract, other
classes can’t inadvertently create an object of that class.
NOTE Even though you can’t create an object of an abstract class, an abstract class can define one or
more constructors and instance variables. The abstract superclass’s constructor is called by the Java
runtime when the subclass’s constructor is called. The call to abstract superclass’s constructor is
required to initialize any instance variables defined in the abstract superclass. By default, abstract
superclass’s no-argument constructor is called. If a no-argument constructor is not available, the
subclass needs to explicitly call abstract superclass’s constructor. For instance, the Rectangle class
calls Shape ’s constructor using the super keyword to ensure thatthe name instance variabledefined in
the Shape abstract class is initialized.
Abstract classes and upcasting
We saw earlier that you can define a variable of superclass type and assign it a subclass object
(referred to as upcasting). Similarly, you can define a variable of abstract class type and assign it an
object of its concrete subclass. For instance, you can rewrite line #5 in listing 7-6 as shown here:
Shape shape = new Rectangle(20, 10);
You can also pass a subclass object to methods or constructors that accept the abstract superclass
type. For instance, consider the following method that accepts an argument of type Shape :
public void doSomething(Shape shape) { ..... }

As Rectangle is a subclass of Shape abstract class, we can pass an object of Rectangle to doSomething
method.The Rectangle object is upcastedto the Shape type.
If a method’s return type is an abstract superclass type, you can return a subclass object from the
method. For instance, consider the following method that returns Shape type:
public Shape didSomething() {
return new Rectangle(10, 20);
}

As Rectangle class is a subclass of Shape abstract class, didSomething method can returna Rectangle object.
The returned Rectangle object is upcastedto the Shape type.
Let’s look at some more features of abstract classes.
Abstract class with no abstract methods
A class can be defined as abstract even if it doesn’t contain an abstract method. This approach is
useful when you want to provide default implementations for methods in the abstract class, and let the
subclasses choose to reuse or override inherited method implementations.
IMPORTIt is recommended that you import the bankapp-abstract project into your Eclipse IDE. bankapp-
abstract project is a modified version of bankapp-method-overriding project (refer chapter 6) that
defines Account superclass as abstract.
The following listing shows the Account class of bankapp-abstract project that contains only concrete (that
is, non-abstract) methods but is still defined as abstract:
Listing 7-7 Account class
Project: bankapp-abstract
Source location: src\com\mybank\Account.java
1 package com.mybank;
2
3 public abstract class Account {
4 .....
5 public Account(int accountNumber, int currentBalance) {
6 .....
7 }
8
9 public int credit(int amount) {
10 return currentBalance = currentBalance + amount;
11 }
12
13 public int debit(int amount) {
14 if(currentBalance - amount < 0) {
15 System.out.println("Can't debit because the current balance will become < 0");
16 }
17 .....
18 }
19 }
Account class defines credit and debit methods that subclasses can either reuse or override. The
following listing shows the CurrentAccount subclass of Account that overrides the debit method butreuses
the credit method:
Listing 7-8 CurrentAccount class
Project: bankapp-abstract
Source location: src\com\mybank\CurrentAccount.java
1 package com.mybank;
2
3 public class CurrentAccount extends Account {
4 .....
5 public int debit(int amount) {
6 int newBalance = super.currentBalance - amount;
7 if (newBalance - overdraftLimit < 0) {
8 .....
9 }

In the above listing, debit method overrides the debit method defined in the Account abstract superclass to
include the overdraft limit set for the account.
Abstract classes and static variables and methods
As static methods and variables are accessed without creating an object of a class, you can define
static variables and methods inside an abstract class. A static method must have an implementation;
therefore, a static method must not be defined as abstract. For instance, the following method
definition will result in compilation error:
public static abstract doSomething();
Let’s now look at how interfaces are used for separating method definitions from their
implementations.
7-3 Interfaces
An interface is like an abstract class that contains only abstract methods. A class that inherits the
interface provides implementations for all the methods defined in the interface. As an interface
defines abstract methods whose implementations are provided by inheriting classes, interfaces are
useful for separating method definitions from their implementations.
NOTE An interface cannot inherit from other classes; therefore, an interface doesn’timplicitly inherit
from java.lang.Object class.
Let’s look at how to define an interface and inherit from it.
IMPORTIt is recommended that you import the shapes-interface project into your Eclipse IDE.
The shapes-interface project is a modified version of shapes project that uses a Shape interface instead of
a Shape abstract class.
The following listing shows the Shape interface of shapes-interface project that
defines area and circumference methods:
Listing 7-9 Shape interface
Project: shapes-interface
Source location: src\com\sample\Shape.java

The syntax for defining an interface is:


<access-modifier> interface <interface-name> { ..... }
here, <access-modifier> is the access modifier assigned to the interface, and <interface-
name> is the name of the interface
The following are the important points to note about interfaces:
as in the case of classes, interfaces can either have public or package-private access
the methods defined in an interface are always public and abstract. You don’t need to
explicitly specify that a method is public and abstract; it is assumed by default. You should
note that if you don’t specify the access modifier for a method, the method is considered
to have public access.
an interface can only contain static variables; you can’t define instance variables in an
interface. Any variable defined in an interface is considered static and final . A final variable
(explained later in this chapter) is a variable whose value (in the case of primitive types)
or reference (in the case of class types) can’t be changed.
as interfaces can’t define instance variables, constructors are not required. For this
reason, you can’t define a constructor in an interface. On the other hand, abstract classes
can define instance variables and constructors.
Shape interface tells that each shape should be able to tell its area and circumference, but leaves it up
to the inheriting classes to tell how area and circumference is calculated. If you compare the Shape
interface in listing 7-9 with Shape abstract class in listing 7-4, the Shape interface only defines the
abstract area and circumference methods. The remaining attributes and methods that the Shape abstract
class defined must now be definedby the classes that inherit from the Shape interface.This means, the
classes that inherit from the Shape interface must take care of defining name instance variable
and getName and toString methods.
The following listing shows the Rectangle class that inherits fromthe Shape interface:
Listing 7-10 Rectangle classthat implements Shape interface
Project: shapes-interface
Source location: src\com\sample\Rectangle.java
1 package com.sample;
2
3 public class Rectangle implements Shape {
4 private int length;
5 private int breadth;
6 private String name;
7
8 public Rectangle(int length, int breadth) {
9 this.name = "Rectangle";
10 this.length = length;
11 this.breadth = breadth;
12 }
13 public int area() {
14 return length * breadth;
15 }
16 public int circumference() {
17 return 2 * (length + breadth);
18 }
19 public String toString() {
20 return "Shape named " + name + " has area " + area()
21 + " and circumference " + circumference();
22 }
23 public String getName() {
24 return name;
25 }
26 }

As shown in the above listing, the implements keyword (line #3) specifies that the Rectangle class inherits
fromthe Shape interface. A class that inherits from an interface must provide implementations for all
the methods defined in the interface; therefore, the Rectangle class provides implementations for
area and circumference methods defined inthe Shape interface.

NOTE If the class that inherits from the interface doesn’t provide implementation for all the methods
defined in the interface, then the class must be defined as abstract.
classdefines a name instance variable (refer line #6) that represents the shape name (that is,
Rectangle
"Rectangle"), overrides Object ’s toString method (refer line #19) to returna String containing shape
name, area and circumference, and defines a getName method (line #23) that returns the name attribute.
NOTEAs implements keyword is used to specify that a class inherits from an interface, if a class A
inherits from an interface B, we say that class A implements interface B. The class A is referred to as
the implementing class, and interface B is referred to as the interface implemented by class A.
The following listing shows the ShapeTest class of shapes-interface project whose main method creates
a Rectangle object and prints the String representation of the Rectangle object to the output:
Listing 7-11 ShapeTest class
Project: shapes-interface
Source location: src\com\sample\ShapeTest.java
1 package com.sample;
2
3 public class ShapeTest {
4 public static void main(String args[]) {
5 Shape shape = new Rectangle(20, 10);
6 System.out.println(shape);
7 }
8 }

A class that implements an interface is considered as the subtype of the interface. As Rectangle class
implements Shape interface, Rectangle is a subtype of Shape . We saw earlier that you can create an object
of subtype and assign it to a supertype variable; therefore, you can define a variable of interface type
and assign it an object of a class that implements the interface. For instance, on line #5, we create
a Rectangle object (the subtype) and assign it to a variable named shape of type Shape (the supertype).
NOTE Like a class type variable, an interface type variable (likethe shape variable in listing 7-11) is
also referred to as a reference type variable because it holds reference to an object.
An interface doesn’timplicitly inherit from java.lang.Object class but it is treated as a subtype
of java.lang.Object . This means, you can pass an interface type variable to any method or constructor that
accepts java.lang.Object type. On line #6, we pass the shape variable to System.out.println method.As Shape
type is a subtype of java.lang.Object , println(Object) overloaded method of PrintWriter class is called. As
mentioned in section 6-6of chapter 6, println(Object) method calls the toString method of the passed object
and writes the returned String to the output.As the shape variable refers to an instance of a
Rectangle object, the toString method of Rectangle object is calledand the returned String is written to the
output.
NOTE As the implementing class is considered subtype of the interface, the interface and its
implementing class should satisfy the is-arelationship. For instance, Rectangle (the implementing class
shown in listing 7-10) is-a Shape (the interface shown in listing 7-9).
Java language provides many interfaces out-of-the-box that you can use in your programs. For
instance, classes can implement java.lang.Comparable interface for comparing objects. Comparable interface
defines a compareTo method for comparing the current object with the object passed as argument. A
class can implement the Comparable interface and provide an appropriateimplementation for
the compareTo method.
NOTEThe equals method is used to determine if two objects are equal or not. The Comparable interface
is used when you want to sort objects in ascending or descending order by comparing their attributes.
Let’s look at how a class can inherit from multiple interfaces.
Multiple inheritance and interfaces
A class cannot inherit from multiple classes but it can inherit from multiple interfaces. For this
reason, you can say that classes support multiple inheritance of interfaces.

Let’s say that you have to create a drawing board program that allows users to draw shapes (like
rectangle, circle, ellipse, square, line, arc, and so on). Figure 7-1 shows how the drawing board
looks like.
A user selects a shape from the shapes palette and draws the shape in the drawing area. 2-
dimensional shapes (like square and rectangle) have area and circumference, but 1-dimensional
shapes (like straight line and arc) only have length.
IMPORTIt is recommended that you import the interfaces-multiple-inheritance project into your Eclipse
IDE.
To develop the drawing board program, we create the following three interfaces:
TwoDShape – defines area and circumference methods that return area and circumference of the
shape. This interface is implemented by classes that represent 2-dimensional shapes.
OneDShape – defines length method that returns the length of the 1-dimensional shape. This
interface is implemented by classes that represent 1-dimensional shapes.
Drawable – defines draw method that draws the shape. This interface is implemented by classes
that represent shapes that can be drawn on the drawing board.
NOTE An interface defines related behaviors; therefore, you should create separate interfaces for
unrelated behaviors. For instance, 1-dimensional shapes don’t have area and circumference;
therefore, we have created separate interfaces for 1-dimensional and 2-dimensional shapes.
Similarly, shapes have nothing to do with how they are draw on the drawing board; therefore, we
have created a separate Drawable interface.
The following listing shows the Rectangle class that implements TwoDShape and Drawable interfaces:
Listing 7-12 Rectangle class
Project: interfaces-multiple-inheritance
Source location: src\com\sample\Rectangle.java
1 package com.sample;
2
3 public class Rectangle implements TwoDShape, Drawable {
4 private int length;
5 private int breadth;
6 private String name;
7
8 public Rectangle(int length, int breadth) {
9 this.name = "Rectangle";
10 this.length = length;
11 this.breadth = breadth;
12 }
13
14 public int area() {
15 return length * breadth;
16 }
17
18 public void draw() {
19 System.out.println("Drawing the rectangle with length " + length
20 + ", and breadth " + breadth);
21 }
22 .....
23 }

As shown on line #3, a class implements multiple interfaces by specifying their names (separated by
commas) after the implements keyword.As Rectangle class implements TwoDShape and Drawable interfaces, it
must implement area and circumference methods defined in TwoDShape interface, and draw method defined
in Drawable interface.
If a class implements multiple interfaces, the class is a subtype of all the interfaces it implements. So,
if a class X implements interfaces A, B and C, then you can define a variable of either A, B or C type
(the supertypes) and assign it an object of X (the subtype). For example, the following assignments
are correct in the context of Rectangle class shown in listing 7-12:
Rectangle rectangle = new Rectangle();
TwoDShape rectangle = new Rectangle();
Drawable rectangle = new Rectangle();

As you can pass a subtype object where the supertype is expected, you can pass the implementing
class’s object where the interface type is expected.For instance, consider the following method that
accepts Drawable type:
public void doSomething(Drawable drawable) { ..... }

As Rectangle class implements Drawable , you can pass an object of Rectangle to doSomething method.
We saw earlier that if a method’s return type is X, then the method can return an object of X’s subtype.
So, if a method specifies an interface as its return type, the method can return an object of aclass that
implements the interface. For instance, consider the following method that returns Drawable :
public Drawable didSomething() {
return new Rectangle(10, 20);
}

As Rectangle class implements Drawable interface, the didSomething method can return Rectangle object.
The following listing shows the ShapeTest class that creates an instance of Rectangle and calls its draw
method:
Listing 7-13 ShapeTest class
Project: interfaces-multiple-inheritance
Source location: src\com\sample\ShapeTest.java
1 package com.sample;
2
3 public class ShapeTest {
4 public static void main(String args[]) {
5 Drawable rectangle = new Rectangle(10, 20);
6 rectangle.draw();
7 }
8 }

On line #5, we create a Rectangle object and assign it to a Drawable type variable. If you
run ShapeTest ’s main method, you’ll get the following output:
Drawing the rectangle with length 10, and breadth 20

The output shows that Rectangle ’s draw method (refer listing 7-12) was called at runtime.
Let’s see how an interface can inherit from other interfaces.
Interface inheritance
An interface can inherit from one or more interfaces. You typically do this when you want to combine
behaviors from different interfaces. We saw that Drawable interface is implemented by shapes that can
be drawn on the drawing board, and TwoDShape interface is implemented by 2-dimensional shapes. We
can combine Drawable and TwoDShape interfaces to form a new interface(let’s say DrawableTwoDShape ) that
is implemented by 2-dimensional shapes that can be drawn on the drawing board.
The following listing shows the DrawableTwoDShape interface that extends from
both TwoDShape and Drawable interfaces:
Listing 7-14 DrawableTwoDShape interface – combining multiple interfaces
1 package com.sample;
2
3 public interface DrawableTwoDShape extends TwoDShape, Drawable {
4 }

In the above listing, DrawableTwoDShape interface inherits from both TwoDShape and Drawable interfaces.
The extends keyword is used to specify that an interface inherits from one or more interfaces.
DrawableTwoDShape interface inherits area and circumference methods from TwoDShape interface
and draw method from Drawable interface. DrawableTwoDShape doesn’t define any abstract method, but a
class that implements the DrawableTwoDShape interface must provide implementationsfor the
inherited area , circumference and draw methods.
Let’s now look at how interfaces are different from abstract classes.
Interfaces vs abstract classes
We saw earlier that an abstract class defines common attributes and methods required by subclasses.
On the other hand, an interface defines only abstract methods. If you come across a situation in which
the concrete methods defined in the abstract class are hardly reused by the subclasses, it’s an
indication that you should use an interface instead of an abstract class.
The following table summarizes differences between interfaces and abstract classes:
Table 7-1 – Abstract classes vs interfaces
Interface Abstract class
aclass inherits from an aclass inherits from an abstract class
interface using implements using extends keyword
keyword
an interface can only define an abstract class can contain both
abstract methods concrete and abstract methods
an interface can’t contain an an abstract class can define instance
instance variable variables
an interface doesn’t have a an abstract class is associated with a
constructor default no-argument constructor. You
can define additional constructors in
the abstract class. When you call
subclass’s constructor, the abstract
superclass’s constructor is also
called to initialize instance variables.
a class can inherit from a class can only inherit from a single
multiple interfaces abstract class
Let’s now look at how Java’s instanceof operator is used at runtime for determining if an object is of a
specified type.
7-4 instanceof operator
In many scenarios, the runtime type of an object is notknown until program execution. The instanceof
operator is useful when you want to determine the runtime type of an object. Once you know the
runtime type, you can confidently perform upcasting or downcasting of the object.
Let’s look at a scenario in which using instanceof operator is useful.
Figure 7-2 showsa banking application in which SavingsAccount and CurrentAccount are subclasses
of Account abstract class. Account abstract class defines credit and debit methods that are inherited
by SavingsAccount and CurrentAccount subclasses. SavingsAccount defines an additional addInterest method,
and CurrentAccount defines an additional increaseOverdraftLimit method. SavingsAccount reuses the
inherited credit and debit methods. CurrentAccount overrides the debit method but reuses the credit method.

IMPORTIt is recommended that you import the instanceof project into your Eclipse IDE.
Let’s say it’s an end of financial year and the bank needs to credit interest into all
the SavingsAccount s.This means, we need to write a program that goes over all the bank accounts and if
it finds a SavingsAccount , then calls SavingsAccount ’s addInterest method to credit the interest into that
account. Listing 7-15 shows a simplified version of such a program that assumes there are only
twobank accounts (one SavingsAccount and one CurrentAccount ), and that an even account number
represents a CurrentAccount and an oddaccount number represents a SavingsAccount .
In listing 7-15, on line #4 and #5, we create and assign instances of SavingsAccount and CurrentAccount to
static variables sa and ca . As sa and ca variables are defined static, they are initialized when
the SimpleTest class is loaded. This means, the SavingsAccount and CurrentAccount objects are created and
assigned to sa and ca variables when SimpleTest class is loaded. The getAccount method on line #16
accepts an account number and returns the corresponding SavingsAccount or CurrentAccount object. For the
sake of simplicity, we’ve assumed that an evenaccount number represents a CurrentAccount and an
oddaccount number represents a SavingsAccount . On line #15, the expression number % 2 == 0 evaluates
to true only if number is an evennumber. We’ve defined the return type of getAccount method
as Account because both SavingsAccount and CurrentAccount are subclasses of Account abstract class.
NOTEIf SavingsAccount and CurrentAccount classes were notsubclasses of Account ,we could have
specified Object as the return type of getAccount method because Java classes implicitly inherit
from Object class.
On line #8 and #9, the SimpleTest ’s main method calls the getAccount method to get bank accounts with
numbers 123 and 456 . As we don’t know the actual objects referenced by account1 and account2 variables,
we downcast them to SavingsAccount type on line #10 and #12 and then call their addInterest method on
line #11 and #13. As discussed in chapter 6, downcasting works only if the runtime object is of the
sametype as the downcasted type. If the runtime object referenced by account1 or account2 is
nota SavingsAccount object, the downcast on line #10 or #12 will throw an exception during program
execution.
Listing 7-15 SimpleTest class
Project: instanceof
Source location: src\com\test\SimpleTest.java

If you run SimpleTest ’s main method, you’ll get java.lang.ClassCastException exception on line #12. For
account number 456 (an evennumber), getAccount method returnsa CurrentAccount object (and
nota SavingsAccount object); therefore, the downcast on line #12 resultsin ClassCastException . We could
have avoided the exception if we had some mechanism to determine the runtime type of an object
before performing downcast. This is where instanceof operator comes into picture.
The following listing shows InstanceofTest ’s main method that is similar to SimpleTest ’s main method but
uses instanceof operator to determine the runtime type of the object returned from getAccount method
before attempting to downcast to SavingsAccount type:
Listing 7-16 InstanceofTest class
Project: instanceof
Source location: src\com\test\InstanceofTest.java
1 package com.test;
2 .....
3 public class InstanceofTest {
4 .....
5 public static void main(String args[]) {
6 Account account1 = getAccount(123);
7 Account account2 = getAccount(456);
8 if(account1 instanceof SavingsAccount) { instanceof operator
9 SavingsAccount sa1 = (SavingsAccount)account1;
10 sa1.addInterest(3);
11 System.out.println("Performed downcasting of account1 and added interest");
12 }
13 if(account2 instanceof SavingsAccount) { instanceof operator
14 SavingsAccount sa2 = (SavingsAccount)account2;
15 sa2.addInterest(3);
16 System.out.println("Performed downcasting of account2 and added interest");
17 }
18 }
19 .....
20 }

On line #8 and #13, the instanceof operator is used to check if the runtime type of objects referenced
by account1 and account2 variables is SavingsAccount . Only if the runtime type is SavingsAccount , downcasting
is performed to SavingsAccount typeand the SavingsAccount ’s addInterest method is called.
The syntax for using instanceof operator is:
<variable-name> instanceof <type>
here, <variable-name> is the name of a reference type variable, and <type> is the runtime
type of an object.
The above expression evaluates to true only if the runtime type of the object referenced by <variable-
name> is:
same as the runtime type specified by <type> variable, or
subtype of the runtime type specified by <type> variable
If you execute InstanceofTest ’s main method, you’ll get the following output:
Performed downcasting of account1 and added interest

The output shows that ' account1 instanceof SavingsAccount' expression on line #8 evaluates to true but the
expression ' account2 instanceof SavingsAccount' on line #13 evaluates to false.As account2 variable refers to
an instance of CurrentAccount object, the expression ' account2 instanceof SavingsAccount' evaluates to false.
The instanceof operator is also used to check if the runtime type of an object is a subtype of an
interface, that is, the object’s class implements the specified interface. Let’s look at an example that
shows usage of instanceof operator to determine if an object is a subtype of an interface.
The following figure shows that the Rectangle class implements TwoDShape and Drawable interfaces, and
the StraightLine class implements OneDShape and Drawable interfaces:

The following listing shows the InstanceofTestForInterfaces class whose main method uses instanceof operator
to determine what all interfaces are implemented by Rectangle and StraightLine objects:
Listing 7-17 InstanceofTestForInterfaces class
Project: instanceof
Source location: src\com\test\InstanceofTestForInterfaces.java
1 package com.test;
2 .....
3 public class InstanceofTestForInterfaces {
4 private static Rectangle rectangle = new Rectangle(10, 20);
5 private static StraightLine line = new StraightLine("0,0", "10,10");
6
7 public static void main(String args[]) {
8 Drawable shape1 = getShape(100);
9 Drawable shape2 = getShape(101);
10
11 if(shape1 instanceof Rectangle) {
12 System.out.println("shape1 holds reference to a Rectangle type");
13 Rectangle rectangle = (Rectangle)shape1;
14 System.out.println("Area of rectangle : " + rectangle.area());
15 }
16 if(shape1 instanceof TwoDShape) {
17 System.out.println("shape1 holds reference to a TwoDShape type");
18 }
19 if(shape1 instanceof Object) {
20 System.out.println("shape1 holds reference to an Object type");
21 }
22 if(shape2 instanceof OneDShape) {
23 System.out.println("shape2 holds reference to a OneDShape type");
24 }
25 }
26
27 private static Drawable getShape(int shapeIdentifier) {
28 if(shapeIdentifier % 2 == 0) {
29 return rectangle;
30 } else {
31 return line;
32 }
33 }
34 }

Line #4 and #5 define static variables that are initialized with Rectangle and StraightLine
objects.The getShape method on line #27 returns a Rectangle or StraightLine object depending on whether
the shapeIdentifier argument passed is an even or odd number.As both Rectangle and StraightLine classes
implement Drawable interface, we’ve specified Drawable as the return type of getShape
method.The getShape method is called on line #8 and #9 and the returned objects are assigned
to shape1 and shape2 variables of Drawable type.The shape1 variable holds reference to a Rectangle object
because the getShape(100) call returns a Rectangle object.The shape2 variable holds reference to
a StraightLine object because the getShape(101) call returns a StraightLine object.
The expression ' shape1 instanceof Rectangle' on line #11 evaluates to true because shape1 holds reference to
a Rectangle object. The expression ' shape1 instanceof TwoDShape' on line #16 evaluates to true
because Rectangle implements TwoDShape interface. The expression ' shape1 instanceof Object' on line #19
evaluates to true because Rectangle class implicitly extends Object class(that is, Rectangle is a subtype
of Object ). The expression ' shape2 instanceof OneDShape' evaluates to true on line #22
because shape2 variable holds reference to a StraightLine object that implements OneDShape interface.
If you run InstanceofTestForInterfaces ’s main method, you’ll get the following output:
shape1 holds reference to a Rectangle type
Area of rectangle : 200
shape1 holds reference to a TwoDShape type
shape1 holds reference to an Object type
shape2 holds reference to a OneDShape type

The output shows that all the expressions involving instanceof operator evaluated to true.
Let’s now look at how the final keyword in Java is used to restrict subclassing and overriding of
methods, and to define constants.
7-5 final keyword
You can use the final keyword when defining:
classes
instance and static variables, and local variables
instance and static methods
method and constructor arguments
Let’s look at the implications of using the final keyword.
final classes
If a class is defined as final , it can’t be subclassed. For instance, the following Car class can’t be
subclassed:
public final class Car { ..... }

If you attempt to subclass Car , you’ll get compilation error. For instance, the following class will not
compile:
public class RedCar extends Car { ..... }

If you compile the RedCar , you’ll get the following compilation error: 'The type RedCar cannot
subclass the final class Car'.
NOTE String and System classes are examples of built-in classes in Java that are defined final . For this
reason, you can’t subclass String and System classes.
final methods
If you define an instancemethod as final , then the subclasses can’t override it.For instance, the credit
method in the following Account class can’t be overridden by subclasses:
public class Account {
public final int credit(int amount) { ..... }
}
If you attempt to override the credit method in a subclass of Account , it’ll result in compilation error.
If the superclass defines a staticmethod as final , the subclasses can’t hide the method by redefining it.
For instance, the following doSomething method can’t be redefined in subclassesof class X :
public class X {
public static final void doSomething() { ..... }
}
If you redefine the doSomething method in a subclass of X , it’ll result in compilation error.
final variables
A final variable is initialized only once. This restriction protects final variables from being
accidentally modified in the program.
The following rules apply to final variables:
a final instance variable must be initialized at the time of declaration or in the constructor or
in an instance initializer block (explained later in this chapter)
a final static variable must be initialized at the time of declaration or in a static initializer
block (explained later in this chapter)
a final local variable must be initialized either at the time of declaration or later within the
method
once a value is assigned to a primitive type final variable, it can’t be changed
once an object is assigned to a reference type final variable, you can’t assign another object to
that variable or set it to null.
NOTE If the Java compiler finds that you are attempting to change the value (or reference)of a final
variable, it’ll show a compilation error
The following listing shows the Car class thatdefines final variables:
Listing 7-18 Car class – final variables

In the above listing:


mileagefinal instance variable (line #2) is assigned the value 10.1f in the constructor (line #7).
As the value is assigned to mileage variable in the constructor, no compilation error is
reported.
model final instancevariable (line #3) is assigned the String object with value "someModel" at the
time of declaration. We assign it a new String object with value "someOtherModel" (line #8)in the
constructor. As model variable is defined as final , you can assign it an object reference only
once. For this reason, compilation error is reported on line #8.
topSpeed final
static variable (line #4) is assigned the value 220 in the constructor (line #10).
As static variables are accessed without creating an object of the class, static final variables
must be initialized at the time of declaration or by static initializer blocks. For this reason,
compilation errors are reported on line #4 and #10.
x final local variable defined on line #12 is assigned value 1 on line #13. As variable x is
initialized only once, the compiler doesn’t report any problem.
str variable on line #14 is assigned reference to a String object.The str variable is then assigned
to make final local variable.On line #16, make variable is once again assigned str variable.As
multiple assignments to a final variable are not allowed, compilation error is reported on line
#16.
Constants
A variable that is declared static and final is referred to as a constant. A constant is associated with a
class and notwith an object; therefore, it is declared as static . A constant’s value must notchange after
it’s initialized; therefore, it is declared as final . The following variables are examples of constants:
public static final int MAX_STUDENTS = 2000;
private static final double PI = 3.14159;

MAX_STUDENTS and PI are constants because they are defined static and final .
NOTE Java constants are typically defined in uppercase to clearly distinguish them from other
variables.
As mentioned in section 7-3, variables defined in an interface are always static and final . This means
all variables defined in an interface are constants. Even if you don’t declare a variable in an interface
as static and final ,it is implicitly considered static and final . For instance, the MAX_STUDENTS variable
defined in the following interface is a constant:
public interface School {
int MAX_STUDENTS = 2000;
int getCourses();
}

final arguments
You can also define a method or constructor argument as final . If the final argument is a primitive type,
you can’t change its value. If the final argument is a reference type, you can’t change the reference.The
following listing shows the Car constructor whose arguments are defined as final :
Listing 7-19 Car class – final arguments
1 public class Car {
3 .....
3 public Car(final String make, final int topSpeed) {
4 make = "make"; compilation error
5 topSpeed = 200; compilation error
6 }
7 }

As make and topSpeed arguments are defined as final , compilation errors are reported on line #4 and #5.
This shows that if a method (or constructor) argument is defined as final , it is protected from being
accidentally modified by the method (or constructor).
7-6 static and instance initializer blocks
A static initializer block is used for initializing static variables and to take certain actions when the
class is loaded by the JVM. An instance initializer block is used for initializing instance variables
and to take certain actions when an object of the class is created. The initializer blocks are
particularly useful when a number of steps are involved for initializing variables.
NOTE A class can contain any number of static and instance initialization blocks
A static initialization block has the following syntax:
static {
//-- initialization code goes here
}
And, an instance initialization block has the following syntax:
{
//-- initialization code goes here
}

Notice that the static keyword appears before the opening brace of a static initialization block.
IMPORTIt is recommended that you import the initializer-blocks project into your Eclipse IDE.

The following listing shows the Customer class that represents a bank customer:
Listing 7-20 Customer class – static and instance initializer blocks
Project: initializer-blocks
Source location: src\com\sample\Customer.java
1 package com.sample;
2
3 import java.text.SimpleDateFormat;
4 import java.util.Date;
5
6 public class Customer {
7 private static String branchDetails;
8 private String lastAccessedOn;
9 private int accountId;
10
11 static {
12 branchDetails = Bank.ADDRESS_FIRST_LINE + ", " + Bank.ADDRESS_SECOND_LINE
13 + ", " + Bank.CITY + ", " + Bank.ZIP
14 + " " + "IFSC Code " + Bank.IFSC_CODE;
15 System.out.println(branchDetails);
16 }
17
18 {
19 Date date = new Date();
20 SimpleDateFormat sdf = new SimpleDateFormat("MMM-dd-yyyy");
21 lastAccessedOn = sdf.format(date);
22 System.out.println("Last time account was accessed on " + lastAccessedOn);
23 }
24
25 public Customer(int accountId) {
26 this.accountId = accountId;
27 System.out.println("Customer created with accountId : " + this.accountId);
28 }
29 }

Customer class defines branchDetails static variable, and lastAccessedOn and accountId instance variables.
The branchDetails (line #7) static variable contains details of the branch in which the customer has
account, lastAccessedOn (line #8) instance variable holds the last date on which the customer accessed
his bank account, and accountId (line #9) instance variable uniquely identifies customer’s bank
account.
The static initialization block (refer line #11 to #16) initializes branchDetails static variable by
obtaining branch details from the Bank class. Bank class
defines ADDRESS_FIRST_LINE , ADDRESS_SECOND_LINE , CITY , and so on, constants (that is, static final
variables) that are used by the static initialization block to set the value of branchDetails variable.Once
the value of branchDetails variable is set, its value is written to the output (line #15) by the static
initialization block.
The instance initialization block (refer line #18 to #23) initializes the value of lastAccessedOn instance
variable. Java provides java.util.Date class that represents date and time. To get the current date and
time, we create an object of Date on line #19. Java also provides java.text.SimpleDateFormat class that
converts a date in text format (like, "May-12-2016") into a Date object and vice versa.We create an
instance of SimpleDateFormat on line #20. The String argument "MMM-dd-yyyy" passed
to SimpleDateFormat constructor specifies the format of the date and time. MMM represents the month
(like, Feb, Mar, Nov), dd represents the day of the month (like, 10, 20, 15), and yyyy represents the
year (like 2016). So, if the current date is 1st March 2015, SimpleDateFormat will format the date to
"Mar-01-2015".On line #21, we call SimpleDateFormat ’s format(Date) method that formats the date
represented by Date object into the MMM-dd-yyyy format and returns the formatted date as String . On line
#22, we write the String returned by the format(Date) method to the output.
As the accountId instance variable’s value depends on the accountId argument passed to Customer ’s
constructor, the accountId is initialized inside the constructor itself (refer line #26).
The following code shows the CustomerTest ’s main method that simply creates a Customer object:
Listing 7-21 CustomerTest class
Project: initializer-blocks
Source location: src\com\sample\CustomerTest.java
1 package com.sample;
2
3 public class CustomerTest {
4 public static void main(String args[]) {
5 new Customer(1234567890);
6 }
7 }
If you run CustomerTest ’s main method, you’ll get the following output:
street number, location, someCity, 1234567890 IFSC Code XYZ
Last time account was accessed on Nov-16-2016
Customer created with accountId : 1234567890

The output shows that static initialization block is executed first, followed by execution of instance
initialization block, and finally the constructor is executed.
NOTE When a class is compiled, the compiler adds the instance initialization block at the beginning
of the constructor. For this reason, it looks like instance initialization block is executed before the
execution of constructor.
The use of instance initialization block is also useful if a class defines multiple constructors and each
constructor requires some common initialization logic. At the time of compilation, the instance
initialization block is added to each of the constructors defined in the class. This saves the effort for
adding same initialization logic to multiple constructors.
Alternatives to using static initialization blocks
Instead of using a static initialization block to execute complex initialization logic, you can define a
static method and call it, as shown in the following listing:
Listing 7-22 Customer class – using static method instead of static initialization block
1 public class Customer {
2 private static String branchDetails = getBranchDetails();
3 .....
4 private static String getBranchDetails() {
5 return Bank.ADDRESS_FIRST_LINE + ", " + Bank.ADDRESS_SECOND_LINE + ", "
6 + Bank.CITY + ", " + Bank.ZIP
7 + " " + "IFSC Code " + Bank.IFSC_CODE;
8 }
9 .....
10 }
In listing 7-20, the branchDetails static variable was initialized by the static initialization block. In the
above listing, the branchDetails static variable is initialized by calling getBranchDetails static method.
Alternatives to using instance initialization blocks
Instead of using an instance initialization block, you can write initialization logic either inside the
constructor itself or in a final instance method. The following listing shows how a final method is used
to initialize Customer ’s lastAccessedOn instance variable:
Listing 7-23 Customer class – using final instance method instead of instance initialization block
1 public class Customer {
2 private String lastAccessedOn = getLastAccessedOn();
3 .....
4 protected final String getLastAccessedOn() {
5 Date date = new Date();
6 SimpleDateFormat sdf = new SimpleDateFormat("MMM-dd-yyyy");
7 lastAccessedOn = sdf.format(date);
8 return lastAccessedOn;
9 }
10 }

The above listing shows that lastAccessedOn variable is initialized by calling getLastAccessedOn instance
method. It is not mandatory todefine getLastAccessedOn as final , but it is recommended.
Let’s understand why defining getLastAccessedOn method as final is important.
When a class is compiled, the compiler adds instance variable initialization statements to the
constructor(s) defined in the class. For instance, compiling the Customer class of listing 7-23will
add lastAccessedOn = getLastAccessedOn() statement (line #2) to the Customer ’s constructor.
If Customer ’s getLastAccessedOn method was not final , a subclass of Customer would have overridden it,
resulting in undesirable behavior.
The following listing shows PrivilegedCustomer subclass of Customer that overrides getLastAccessedOn
method:
Listing 7-24 PrivilegedCustomer class – overriding
1 public class PrivilegedCustomer extends Customer {
2 private String date = "Dec-25-2015";
2 protected String getLastAccessedOn() {
3 return date;
4 }
5 }
The overridden getLastAccessedOn method simply returns "Dec-25-2015" string.
We saw earlier that when a subclass’s constructor is called, the superclass’s constructor is executed
first, followed by execution of the subclass’s constructor. When wecall PrivilegedCustomer ’s
constructor, Customer ’s constructor is invoked first, which calls the getLastAccessedOn method (refer line
#2 in listing 7-23). As the getLastAccessedOn method is overriddenby PrivilegedCustomer class,
the PrivilegedCustomer ’s getLastAccessedOn method is called. At this time, the date instance variable
of PrivilegedCustomer (refer line #2 in listing 7-24) is not initialized, so the value returned by
calling PrivilegedCustomer ’s getLastAccessedOn method is null . This sets the value of Customer ’s lastAccessedOn
variable to null . This shows that overridden getLastAccessedOn method may result in accessing un-
initialized instance variables of the subclass’s object.For this reason, Customer ’s getLastAccessedOn
method should be defined final so that it can’t be overridden by subclasses.
QUIZ
7-1: Which of the following statements are true about abstract classes?
a) an abstract class must not define concrete methods
b) an abstract class must not extend from a concrete class
c) an abstract class must not define a constructor
d) you can't create an instance of an abstract class
e) an abstract class must contain one or more abstract methods
f) an abstract class can define one or more static methods and variables
7-2: Consider thefollowing Shape class and its Rectangle subclass:
1 public abstract class Shape { abstract class
2 protected int counter;
3
4 public void increment() {
5 counter++;
6 moreIncrement(); abstract moreIncrement method is called
7 }
8
9 public int getCounter() {
10 return counter;
11 }
12
13 public abstract void moreIncrement(); abstract method
14 }

1 public class Rectangle extends Shape {


2 public void moreIncrement() { implementation of moreIncrement abstract method
3 counter = counter + 2;
4 }
5 }

What would be the output from executing the following main method?
1 public static void main(String args[]) {
2 Shape shape = new Rectangle();
3 shape.increment();
4 shape.increment();
5 System.out.println(shape.getCounter());
6 }

7-3: Which of the following statements about interfaces are true?


a) an interface can define one or more concrete methods
b) a class can implement multiple interfaces
c) an interface can inherit from multiple interfaces
d) like abstract classes, an interface can define one or more constructors
7-4: Consider the following Shape , Rectangle , RedRectangle classes and Drawable interface:
public abstract class Shape { ..... }
public interface Drawable { ..... }
public class Rectangle extends Shape implements Drawable { ..... }
public class RedRectangle extends Rectangle { ..... }

Let’s say the following two methods are defined by a class:


public void doSomething(Shape shape) { ..... }
public void doMore(Drawable drawable) { ..... }

If rectangle and redRectangle variables hold reference to Rectangle and RedRectangle objects, respectively, then
which of the following statements are correct?
a) doSomething(rectangle) method call will result in compilation error
b) doMore(rectangle) method call will result in compilation error
c) doSomething(redRectangle) method call will result in compilation error
d) doMore(redRectangle) method call will result in compilation error
e) Shape shape = rectangle; - this statement will result in compilation error
f) Drawable drawable = redRectangle; - this statement will result in compilation error
7-5: Which of the following statements are true about the use of final keyword?
a) a final class cannot be subclassed
b) a final method can’t be overloaded
c) a final primitive type variable’s value can’t be changed
d) the object referenced by a final reference type variable can’t be modified
e) a final constructor cannot be overridden
7-6: Which of the following statements are true?
a) a static initializer block is used for initializing static variables
b) an instance initializer block is used for initializing instance variables
c) a constructor can be used instead of a static initializer block
d) an instance initializer block can be used instead of static initializer block to initialize
static variables
7-7 Summary
In this chapter, we looked at the concepts of abstract classes and interfaces in Java. We saw the
restrictions that apply when you define a class, method or variable as final . We also saw how
the instanceof operator can be used to determine the runtime type of an object. We saw that static and
instance initializer blocks are helpful when it comes to executing complex initialization logic for
static and instance variables, respectively.
This chapter completes the basic object-oriented concepts that you need to know to build applications
in Java. In the next chapter, we’ll look at how exceptions are handled in real-world Java
applications.
Chapter 8 – Exception handling
8-1 Introduction
We saw in chapter 6 that an exception represents a problem with the program that results in
immediate termination of the program. In this chapter, we’ll look at:
exceptions that you’ll normally come across while writing Java programs
checked and unchecked exceptions
how to create custom exceptions
how to catch exceptions and handle them gracefully
Let’s look at what are exception classes and how they are used in programs.
8-2 Exception classes
In Java, an exception is represented by a class. Java defines built-in exception classes representing
common exception conditions.For instance, java.lang.NullPointerException represents an exception condition
that occurs when you access attributes and methods of a reference type variable set to null .
When an exception occurs during program execution, following things happen:
the program execution is halted
an appropriate exception object representing the exception condition is created (also referred
to as thrown), and
the newly created exception object is returned to the calling method
All exception classes in Java directly or indirectly inherit from java.lang.Throwable class. The following
figure shows some of the important direct and indirect subclasses of Throwable class:

Figure 8-1 The direct and indirect subclasses of Throwable class


The above figure shows that java.lang.Error and java.lang.Exception are subclasses of Throwable . The Error and
its subclasses represent unrecoverable exceptions; that is, exceptions that a program can’t recover
from. For instance, an object of java.lang.OutOfMemoryError class (a subclass of Error ) is thrown if JVM
cannot create an object in the heap memory area because there is no memory space left in the heap
memory area. A program can’t recover from java.lang.OutOfMemoryError exception.
The Exception and its subclasses represent exceptions that a program can recover from.For instance, an
object of java.lang.NullPointerException class (a subclass of Exception ) is thrown when a method is called on a
reference type variable set to null .A program can recover from java.lang.NullPointerException .
Exception ’s subclasses are divided into two categories:
checked exception classes – a checked exception must be handled in the program.
Excluding java.lang.RuntimeException , the remaining subclasses of Exception class represent checked
exceptions.For instance, java.lang.ClassNotFoundException is an example of checked exception.
unchecked exception classes – an unchecked exception is not required to be handled in the
program. An unchecked exception is represented by java.lang.RuntimeException and its
subclasses.For instance, java.lang.NullPointerException is an example of unchecked exception.
NOTEYou can create new checked and unchecked exceptions by
subclassing Exception and RuntimeException classes, respectively.
Let’s look at some common exceptions that are thrown by Java programs.
IMPORTIt is recommended that you import the exceptions project into your Eclipse IDE.
java.lang.NullPointerException
The following listing shows the NullReference class whose main method calls area method of Rectangle
object:
Listing 8-1 NullReference class – throws NullPointerException
Project: exceptions
Source location: src\com\sample\NullReference.java
1 package com.sample;
2
3 public class NullReference {
4 private static Rectangle rectangle;
5
6 public static void main(String args[]) {
7 int area = rectangle.area(); java.lang.NullPointerException
8 System.out.println("Area: " + area); not executed
9 }
10 }

On line #4, rectangle static variable of type Rectangle is defined.And, on line #7, Rectangle object’s area
method is called.If you run NullReference ’s main method, you’ll get the following output:
Exception in thread "main" java.lang.NullPointerException
at com.sample.NullReference.main(NullReference.java:7)

The output showsthat an exception occurred on line #7 of NullReference class, and the exception
is java.lang.NullPointerException . As " Area: " was not shown in the output, it means the
statement System.out.println("Area: " + area) of NullReference class (refer line #8) was not executed.
A NullPointerException is thrown when you call methods or access attributes using a reference type
variablethat is set to null . As we didn’t create and assign a Rectangle object to the rectangle
variable,the rectangle variable was set to null at the time area method was called on line #7.
Let’s now modify the NullReference class’s main method such that it doesn’t throw NullPointerException when
the rectangle variable is set to null .
Hands-on Modify NullReference ’s main method to avoid NullPointerException
To avoid NullPointerException , check if the reference type variable is set to null or not before calling any
methods or accessing any attributes.
The following listing shows the modified NullReference class whose main method calls area method only if
the rectangle variable is notset to null :
Listing 8-2 NullReference class – doesn’t throw NullPointerException
1 package com.sample;
2
3 public class NullReference {
4 private static Rectangle rectangle;
5
6 public static void main(String args[]) {
7 if(rectangle == null) {
8 System.out.println("rectangle variable doesn’t refer to a Rectangle object");
9 } else {
10 int area = rectangle.area();
11 System.out.println("Area: " + area);
12 }
13 }
14 }

On line #7, we check if the rectangle variable is set to null . As rectangle variable is set to null , the
statements on line #10 and #11 are notexecuted. So, if you now run the main method of NullReference
class, you’ll get the following output:
rectangle variable doesn’t refer to a Rectangle object

java.lang.ClassCastException
The following listing shows WrongCasting class whose main method performs upcasting and
downcasting of objects:
Listing 8-3 WrongCasting class – throws ClassCastException
Project: exceptions
Source location: src\com\sample\WrongCasting.java
1 package com.sample;
2
3 public class WrongCasting {
4 public static void main(String args[]) {
5 Object rectangle = new Rectangle(10, 10);
6 String str = (String) rectangle; throws java.lang.ClassCastException
7 System.out.println("String str : " + str); not executed
8 }
9 }

On line #5, an object of Rectangle class is created and assigned to Object type variable.On line
#6, rectangle variable that holds reference to the Rectangle object is assigned to a String type variable. If
you run WrongCasting ’s main method, you’ll get the following output:
Exception in thread "main" java.lang.ClassCastException: com.sample.Rectangle cannot be cast to java.lang.String
at com.sample.WrongCasting.main(WrongCasting.java:6)

The output shows that an exception occurred on line #6 of WrongCasting class, and the exception
is java.lang.ClassCastException . As " String str: " was not printed, this means thatstatement System.out.println("String
str: " + str) of WrongCasting class (refer line #7) was not executed. Notice that the cause of exception is
also printed: " com.sample.Rectangle cannot be cast to java.lang.String" .
A ClassCastException is not thrown if you cast an object to a type which is either of the same type as the
object or it is supertype of the object. In all other cases, a ClassCastException is thrown. As String is nota
supertype of Rectangle , the assignment fails on line #6 and ClassCastException is thrown.
NOTE As explained in section 7-4 of chapter 7, you can use the instanceof operator to check the
runtime type of an object before performing downcasting or upcasting of the object. This means, you
can use the instanceof operator to avoid java.lang.ClassCastException .
java.lang.ArithmeticException
The following listing shows DivisionByZero class whose main method divides an integer number by 0 :
Listing 8-4 DivisionByZero class – throws ArithmeticException
Project: exceptions
Source location: src\com\sample\DivisionByZero.java
1 package com.sample;
2
3 public class DivisionByZero {
4 public static void main(String args[]) {
5 int i = 1/0; throws java.lang.ArithmeticException
6 System.out.println("Value of i is " + i); not executed
7 }
8 }
On line #5, integer 1 is divided by 0 and the result is assigned to i .If you run DivisionByZero ’s main
method, you’ll get the following output:
Exception in thread "main" java.lang.ArithmeticException: / by zero
at com.sample.DivisionByZero.main(DivisionByZero.java:5)

The output shows that an exception occurred on line #5 of DivisionByZero class, and the exception
is java.lang.ArithmeticException . As " Value of i is " was not printed, this means that
statement System.out.println("Value of i is " + i) of DivisionByZero class (line #6) was not executed. Notice that the
cause of exception is also printed as " / by zero ".
Now that we’ve seen some of the built-in exception types in Java, let’s look at what happens when an
exception is thrown by a method.
8-3 Exception propagation and handling
In Java applications, a method typically calls one or more methods of other objects in the application.
When an exception occurs, an exception object is returned to the calling method. A method is said to
handle an exception, if it catches the exception and stops it from propagating to the calling method.
Let’s say that the main method (which acts as the entry point into a Java application) calls method x of
object X , and method x calls method y of object Y, and method y calls method z of object Z .

Figure 8-2 An example method call chain


If an exception occurs in method z , the exception is returnedto method y if method z can’t handle it. If
method y can’t handle the exception, it is returned to method x . If method x can’t handle the
exception, it is returned to the main method. If the main method can’t handle the exception, it is handled
by the JVM. The JVM catches the exception and writes the exception details (which include
exception type, object which caused the exception, and the line number on which the exception
occurred) to the output.
Let’s look at an example that shows how unhandled exceptions propagate to the calling method.
The following figure shows objects and methods that are responsible for performing fund transfer in a
banking application:

Figure 8-3 A banking application’s objects and their methods


In the above figure, FundTransfer class defines transferFunds method that transfers money from one account
to another, and Account class represents a bank accountthat defines credit and debit methods. The steps
followed for transferring funds from account xAcc to account yAcc are:
InternetBanking ’s main method calls FundTransfer ’s transferFunds method (represented by line
labelled ❶) to transfer amt amount from xAcc to yAcc account. xAcc and yAcc are Account
objects representing the bank accounts involved in the fund transfer.

method calls xAcc ’s debit method (represented by line labelled ❷)


FundTransfer ’s transferFunds
to debit the amt amount from it, and calls yAcc ’s credit method (represented by line labelled
❸) to credit amt amount to it.
IMPORTIt is recommended that you import the exception-propagation project into your Eclipse IDE.
The following listing shows the FundTransfer class:
Listing 8-5 FundTransfer class
Project: exception-propagation
Source location: src\com\sample\FundTransfer.java
1 package com.sample;
2
3 public class FundTransfer {
4 public static boolean transferFunds(Account xAcc, Account yAcc, int amt) {
5 xAcc.debit(amt);
6 yAcc.credit(amt);
7 System.out.println("Completed fund transfer");
8 return true;
9 }
10 }
The transferFunds method is a static method that debits amt amount from xAcc account and
credits amt amount to yAcc account. After successful transfer, the method prints the message
"Completed fund transfer" and returns true in the end.

The following listing shows the Account class that represents a bank account:
Listing 8-6 Account class
Project: exception-propagation
Source location: src\com\sample\Account.java
1 package com.sample;
2
3 public class Account {
4 private int accountNumber;
5 private int currentBalance;
6 .....
7 public void credit(int amt) {
8 currentBalance = currentBalance + amt;
9 }
10
11 public void debit(int amt) {
12 int tempBalance = currentBalance - amt;
13 if (tempBalance < 0) {
14 int i = 1 / 0; throws java.lang.ArithmeticException
15 System.out.println(i); never executed
16 }
17 currentBalance = tempBalance;
18 }
19 .....
20 }

The accountNumber and currentBalance instance variables represent the unique bank account number and the
current account balance, respectively. The credit method (line #7) adds the given amt amount
to currentBalance . The debit method (line #11) needs to meet the following requirements:
As the bank account can’t have negative balance, the debit method subtracts amt amount (the
amount to be debited) from currentBalance only if it doesn’t lead to negative balance.For this
reason, tempBalance variable is defined on line #12 to temporarily holdaccount balance after
subtracting amt from currentBalance .If tempBalance < 0 condition evaluates to false on line #13,
the tempBalance value is assigned to currentBalance on line #17.
If debiting amt amount can lead to negative balance, the execution of debit method must stop.
To achieve this requirement, if tempBalance <0 (refer line #13) condition evaluates to true, we
divide 1 by 0 (refer line #14).We saw earlier that division by 0 results
in java.lang.ArithmeticException (refer listing 8-4).This means, if tempBalance < 0 evaluates to
true, ArithmeticException will be thrown online #14 and the execution of debit method will
stop.This also means that the statement System.out.println(i) on line #15 will never be executed.
The following listing shows InternetBanking class whose main method calls FundTransfer ’s transferFunds
method:
Listing 8-7 InternetBanking class
Project: exception-propagation
Source location: src\com\sample\InternetBanking.java
1 package com.sample;
2
3 public class InternetBanking {
4 public static void main(String args[]) {
5 Account xAcc = new Account(1, 1000);
6 Account yAcc = new Account(2, 1200);
7
8 FundTransfer.transferFunds(xAcc, yAcc, 1400);
9 System.out.println("xAcc’s current balance " + xAcc.getCurrentBalance());
10 System.out.println("yAcc’s current balance " + yAcc.getCurrentBalance());
11 System.out.println("Completed execution of main method");
12 }
13 }

At first, main method creates two bank accounts xAcc and yAcc with current balances as 1000 and 1200 ,
respectively.It then calls FundTransfer ’s transferFunds method (line #8) to transfer 1400 from xAcc account
to yAcc account. If you run InternetBanking ’s main method, you’ll get the following output:
Exception in thread "main" java.lang.ArithmeticException: / by zero
at com.sample.Account.debit(Account.java:19)
at com.sample.FundTransfer.transferFunds(FundTransfer.java:6)
at com.sample.InternetBanking.main(InternetBanking.java:8)

NOTE The above output is referred to as exception stack trace. An exception stack trace provides
details of methods (and their classes) that were being executed when the exception occurred.
As xAcc account’s balance is 1000 and we are trying to transfer 1400 , call to xAcc ’s debit method
throws ArithmeticException (refer line #14 in listing 8-6). The output shows:
Account object’s debit method throws ArithmeticException . As the debit method doesn’t handle the
exception, it is returned to the calling transferFunds method.
As FundTransfer ’s transferFunds method doesn’thandle the ArithmeticException , it is returned to the
calling main method.
As InternetBanking ’s main method doesn’t handle the ArithmeticException , it is handled by the JVM.
The above output is written by the JVM, which includes the exception thrown and the
methods that were in the call chain when the exception occurred.
Notice that "xAcc’s current balance" , "yAcc’s current balance" , "Completed execution of main method" (refer InternetBanking
class in listing 8-7) and "Completed fund transfer" (refer FundTransfer class in listing 8-5) messages are not
printed on the output. This is because the ArithmeticException thrown by debit method not only stops
execution of the debit method but also stops execution of calling methods(that is, transferFunds and main
methods).
Figure 8-4 shows how the executionsof main , transferFunds and debit methods are effected
when ArithmeticException occurs. The figure uses numbered balls to represent flow of program control.
At ❶, InternetBanking ’s main method calls FundTransfer ’s transferFunds method. At
❷ , FundTransfer ’s transferFunds method calls Account ’s debit
method. At ❸ , ArithmeticException is thrown by
the debit method which results in transferof control back to the statement of transferFunds method that
called the debit method.As transferFunds method can’t handle the ArithmeticException , control is returned to
the statement of main method that called the transferFunds method (refer ❹ ). As the main method can’t
handle the ArithmeticException , the control is returned to the JVM for handling the exception (refer ❺).

Figure 8-4 Flow of program control when ArithmeticException is thrown by Account ’s debit method
The greyed-out statements shown in the above figure are notexecuted because the exception stops
execution of debit , transferFunds and main methods.
Let’s now look at how tocatch the ArithmeticException thrown by Account ’s debit method.
Catching exceptions
To catch exceptions, you need to do the following:
enclose statements that may throw an exception in a try statement block
immediately following the try statement block, specify one or more catch statement blocks that
contain statements to be executed when an exception occurs
The following is the syntax forspecifying try - catch block:
1 try {
2 <statement-1>;
3 <statement-2>;
4 .....
5 }
6 catch(<exception-type> <name>) {
b) <catch-statement1>;
c) .....
9 }
10 catch(<exception-type> <name>) {
11 <catch-statement2>;
12 .....
13 }

The try block encloses the statements that may throw an exception during execution. The catch
statement blocks are executed only when an exception is thrown by a statement in the try block. The
<exception-type> specifies the exception type (like, NullPointerException and ClassCastException ) for which
the catch block is executed, and <name>specifies the name with which the exception object is
available in the catch block. The statements contained in the catch block specify how the exception is
handled.
Let’s add try - catch blockto Account ’s debit method (refer listing 8-6) to handle ArithmeticException .
Hands-on Add try-catch block
As shown in the following listing, add try - catch block to the Account class of exception-propagation project:
Listing 8-8 Account class– try - catch blockfor catching ArithmeticException
1 package com.sample;
2
3 public class Account {
4 .....
5 public void debit(int amt) {
6 try {
7 int tempBalance = currentBalance - amt;
8 if (tempBalance < 0) {
9 int i = 1 / 0; throws java.lang.ArithmeticException
10 System.out.println(i);
11 }
12 currentBalance = tempBalance;
13 } catch (ArithmeticException ae) { catches ArithmeticException
14 System.out.println(ae); calls toString method of ArithmeticException object
15 }
16 }
17 .....
18 }

In the above listing, try block encloses statements that debit amt amount from currentBalance .
If tempBalance < 0 evaluates to true (line #8), ArithmeticException is thrown on line #9.The catch block (line
#13) specifies that it is executed when ArithmeticException is thrownby any of the statements in the try
block.The catch block contains a single statement that prints the string returned by calling
the toString method of the ArithmeticException object.
If you now run InternetBanking ’s main method, you’ll get the following output:
java.lang.ArithmeticException: / by zero
Completed fund transfer
xAcc’s current balance 1000
yAcc’s current balance 2600
Completed execution of main method

The "java.lang.ArithmeticException: / by zero" message is written by System.out.println(ae) statementinside the catch


block (refer line #14 in listing 8-8). The "Completed fund transfer" message is written
by FundTransfer ’s transferFunds method (refer line #7 in listing 8-4). The rest of the messages are printed
by InternetBanking ’s main method (refer listing 8-6).
Figure 8-5 shows the flow of program control when ArithmeticException thrown by Account ’s debit method
is caught in the debit method itself.

At ❶ , InternetBanking ’s main method calls FundTransfer ’s transferFunds method. At ❷ , transferFunds method


calls Account ’s debit method. At ❸ , ArithmeticException results in execution of
the catch block’s System.out.println(ae) statement. ArithmeticException transfers program control directly to
the catch block; therefore, System.out.println(i) and currentBalance = tempBalance statements are not executed. At
❹ , debit method completes execution and the program control returns to the transferFunds method. At
❺ , the transferFunds method completes execution and the program control returns to the main method. As
both transferFunds and main methods execute successfully, all of their statements are executed.

Figure 8-5 Flow of program control when ArithmeticException is caught in the debit method
NOTE Figure 8-5 shows that the statement contained in the catch block isexecuted only
when ArithmeticException is thrown by int i = 1/0 statement in the try block.
We caught the ArithmeticException thrown in debit method so that the program doesn’t terminate abruptly.
But, it doesn’t mean that the program did what it was intended to do. Figure 8-5 shows
that currentBalance = tempBalance statement is not executed. So, when we transferred 1400 from xAcc to yAcc
account, the current balance of xAcc account remained unchanged at 1000 but the current balance
of yAcc increased to 2600 .
Hands-on Modify placement of try-catch block
You should note that the placement of try - catch block has an impact on the program behavior. For
instance, modify the Account ’s debit method such that the try - catch block is placed as shown in the
following listing:
Listing 8-9 Account class – try - catch block with a different placement
1 package com.sample;
2
3 public class Account {
4 private int currentBalance;
5 .....
6 public void debit(int amt) {
7 int tempBalance = currentBalance - amt;
8 if (tempBalance < 0) {
9 try {
10 int i = 1 / 0; throws ArithmeticException
11 System.out.println(i); this statement is never executed
12 } catch (ArithmeticException ae) {
13 System.out.println(ae);
14 }
15 }
16 currentBalance = tempBalance; executedeven when ArithmeticException occurs
17 }
18 .....
19 }

The try - catch block in the above listing only encloses the following two statements:
int i = 1/0;
System.out.println(i);
And, the following statement is now after the try - catch block:
currentBalance = tempBalance;

The statement(s) that follow afterthe try - catch block are executed in the following scenarios:
no exception is thrown by the statements in the try block
exception thrown by the statements in the try block is caught by the catch block
As ArithmeticException thrown in the try block is caught by the catch block, the currentBalance =
tempBalance statement is executed. This means that even if ArithmeticException occurs, the amt amount is
subtracted from currentBalance .If you now execute the InternetBanking ’s main method, you’ll see the
following output:
java.lang.ArithmeticException: / by zero
Completed fund transfer
xAcc’s current balance -400
yAcc’s current balance 2600
Completed execution of main method

The output shows that when 1400 is transferred from xAcc to yAcc account, 1400 is debited
from xAcc account and 1400 is credited to yAcc account. This program behavior is incorrect
because 1400 was debited from xAcc account even when its current balance was only 1000 .
Figure 8-6 shows the program behavior when try - catch block is placed as shown in listing 8-9.
Figure 8-6 The statement currentBalance = tempBalance is executed even when ArithmeticException is thrown
NOTEA statement inside a catch block can also throw an exception. If an exception is thrown from
the catch block, the program execution stops and the exception is returned to the calling method.
If the statements enclosed within the try block can throw more than one type of exception, then you can
use multiple catch blocks to catch those exceptions.
IMPORT It is recommended that you import the multiple-catch project into your Eclipse IDE.
The following listing shows Sample class that uses multiple catch blocks:
Listing 8-10 Sample class – multiple catch blocks
Project: multiple-catch
Source location: src\com\sample\Sample.java
1 package com.sample;
2
3 public class Sample {
4 private int x;
5 private Car car;
6
7 public void doSomething() {
8 try {
9 int i = 1 / x; can throw java.lang.ArithmeticException
10 car.getColor(); can throw java.lang.NullPointerException
11 } catch (ArithmeticException ae) {
12 System.out.println("exception : " + ae); executed when ArithmeticException is thrown
13 } catch (NullPointerException npe) {
14 System.out.println("exception : " + npe); executed when NullPointerException is thrown
15 }
16 }
17 public void setX(int x) {
18 this.x = x;
19 }
20 public void setCar(Car car) {
21 this.car = car;
22 }
23 }

The values of x (of type int ) and car (of type Car ) attributes are set via setX (line #17) and setCar (line
#20) methods, respectively. The doSomething method assigns value of 1/x to variable i (line #9) and
calls Car ’s getColor method (line #10).
If we create an instance of Sample and set value of x to 0 , java.lang.ArithmeticException is thrown on line #7
when the doSomething method is executed. Similarly, if create an instance of Sample and set car attribute
to null , java.lang.NullPointerException is thrown on line #8when the doSomething method is executed. As we
want to catch both the exceptions, a catch block has been defined for each exception type (refer line
#11 and #13).
NOTE As only one exception is thrown at a time by a program, only one catch block is executed.
The following listing shows the SampleTest class whose main method creates objectsof Sample class and
calls their doSomething method:
Listing 8-11 SampleTest class
Project: multiple-catch
Source location: src\com\sample\SampleTest.java
1 package com.sample;
2
3 public class SampleTest {
4 public static void main(String args[]) {
5 Sample sample_1 = new Sample();
6 sample_1.setX(1);
7 sample_1.doSomething();
8
9 Sample sample_2 = new Sample();
10 sample_2.setCar(new Car("someMake"));
11 sample_2.doSomething();
12 }
13 }

In the above listing, we create two instances, sample_1 and sample_2 ,of Sample class. When a Sample
object is createdby calling Sample class’s default constructor, the value of x is initialized to 0 and the
car attribute is initialized to null . We call sample_1 ’s setX method (line #6) to set its value of x to 1 and
we call sample_2 ’s setCar method (line #10) to set its car attribute to a Car object.
As sample_1 ’s car attribute is set to null , call to sample_1 ’s doSomething method results in NullPointerException
(refer line #10 in listing 8-10). Similarly, as sample_2 ’s x attribute is set to 0 ,call
to sample_2 ’s doSomething method results in ArithmeticException (refer line #9 in listing 8-10).
If you run SampleTest ’s main method, you’ll get the following output:
exception java.lang.NullPointerException
exception java.lang.ArithmeticException: / by zero
The output corresponds to the System.out.println statement contained in each catch block defined
in Sample ’s doSomething method (refer line #12 and #14 in listing 8-10).
Catching multiple exceptionsin a single catch block
Instead of defining a catch block corresponding to each exception type, you can define a single catch
block that catches multiple exception types.The following listing shows the
modified doSomething method of Sample class that uses a single catch block to catch
both NullPointerException and ArithmeticException types:
Listing 8-12 Catching multiple exceptions in a single catch block
1 public void doSomething() {
2 try {
3 int i = 1 / x;
4 car.getColor();
5 } catch (ArithmeticException | NullPointerException ex) { | separates exception types
6 System.out.println("exception " + ex);
7 }
8 }

In the above listing, catch block specifies that it catches


both ArithmeticException and NullPointerException types. The vertical bar | is used to separate different
exception types caught by the catch block.
NOTEUsing a single catch block for catching exceptions is useful only if you want to execute same
set of statements for the caught exceptions

Catching exceptions related by inheritance


By default,a catch block catches all exceptions of the specified exception type and its subtypes. For
instance, the following listing shows the modified version of Sample ’s doSomething method that
catches java.lang.Exception typeinstead of NullPointerException and ArithmeticException types:
Listing 8-13 Catching multiple exceptions
1 public void doSomething() {
2 try {
3 int i = 1 / x; can throw java.lang.ArithmeticException
4 car.getColor(); can throw java.lang.NullPointerException
5 } catch (Exception ex) {
6 System.out.println("exception " + ex);
7 }
8 }
The catch block specifies that it catches java.lang.Exception type. As
both ArithmeticException and NullPointerException are subtypes of java.lang.Exception , the catch block catches
both ArithmeticException and NullPointerException exceptions.
NOTEBoth java.lang.ArithmeticException and java.lang.NullPointerException classes inherit
from java.lang.RuntimeException , which in turn inherits from java.lang.Exception . This
means, ArithmeticException and NullPointerException classes are subtypesof Exception .
When an exception occurs, the first catch block that matches the thrown exception is responsible for
handling the exception. In the following listing, if an ArithmeticException is thrown on line #3, it is
handled by the first catch block (line #5):
Listing 8-14 The first catch block handles the exception
1 public void doSomething() {
2 try {
3 int i = 1 / x; can throw java.lang.ArithmeticException
4 car.getColor(); can throw java.lang.NullPointerException
5 } catch (ArithmeticException ex) {
6 System.out.println("exception " + ex);
7 } catch (Exception ex) {
8 System.out.println("exception " + ex);
9 }
10 }
The catch block corresponding to java.lang.Exception type (line #7) is executed only when an exception
other than ArithmeticException (or its subtype) is thrown.
Now, consider the following listing in which the catch block for java.lang.Exception comes
beforethe catch block for java.lang.ArithmeticException :
Listing 8-15 Exception is caughtbefore ArithmeticException
1 public void doSomething() {
2 try {
3 int i = 1 / x; can throw java.lang.ArithmeticException
4 car.getColor(); can throw java.lang.NullPointerException
5 } catch (Exception ex) {
6 System.out.println("exception " + ex);
7 } catch (ArithmeticException ex) { compilation error
8 System.out.println("exception " + ex);
9 }
10 }

If an ArithmeticException is thrown on line #3, it’ll be caught by the first catch block (line #5)that
catches java.lang.Exception . This means, the catch block for ArithmeticException (line #7) will never be
executed. As the Java compiler figures outthat the catch block for ArithmeticException will never be
executed, it reports compilation error on line #7. This shows that the catch blocks must be ordered
such that a more generalexception (like java.lang.Exception ) comes after a more specificexception
(like java.lang.ArithmeticException ).
Let’s nowlook at the finally statement block that comes afterthe catch block.
IMPORTIt is recommended that you import finally-block project into your Eclipse IDE.
finally block
The finally block comes after the catch block(s) and is guaranteed to be executed. This means,
the finally block is executed when no exception occurs and also when the try or catch block throws an
exception.
The following listing shows the Sample class whose doSomething method uses the finally block:
Listing 8-16 Sample class - finally block
Project: finally-block
Source location: src\com\sample\Sample.java
1 package com.sample;
2
3 public class Sample {
4 private int x;
5
6 public void doSomething() {
7 int i = 10;
8 try { =
9 i = 100 / x; throws ArithmeticException if x is 0
10 } catch (ArithmeticException ae) {
11 System.out.println("exception " + ae);
12 } finally {
13 System.out.println("value of i " + i); guaranteed to be executed
14 }
15 }
16
17 public void setX(int x) {
18 this.x = x;
19 }
20 }

Sample class defines an instance variable x (of type int ) whose value is set using setX method (line
#17). The doSomething methoddefines an int variable i and initializesit to 10 (refer line #7). Thevalue
of i is then changed to 100/x (line #9). If x is 0 , then the statement i = 100/x will
throw java.lang.ArithmeticException . For this reason, the statement i = 100/x is enclosed within the try block.
The catch block on line #10 catches the ArithmeticException and writes the exception details to the
output.The catch block is followed by a finally block (line #12) which simply writes the value of i to the
output.
The following listing shows the SampleTest class whose main method creates two instances
( sample_1 and sample_2 ) of Sample class and calls their doSomething method:
Listing 8-17 SampleTest class
Project: finally-block
Source location: src\com\sample\SampleTest.java
1 package com.sample;
2
3 public class SampleTest {
4 public static void main(String args[]) {
5 Sample sample_1 = new Sample();
6 System.out.println("calling sample_1's doSomething");
7 sample_1.doSomething();
8
9 Sample sample_2 = new Sample();
10 sample_2.setX(2);
11 System.out.println("calling sample_2's doSomething");
12 sample_2.doSomething();
13 }
14 }
We call sample_1 ’s doSomething method without setting the value of attribute x . As the default value
of x is 0 , call to sample_1 ’s doSomething method throws java.lang.ArithmeticException (refer line #9 in listing 8-
16).We call sample_2 ’s doSomething method after setting the value of x to 2 . As the value of x is 2 ,
calling sample_2 ’s doSomething method doesn’t throw any exception.
If you run SampleTest ’s main method, you’ll see the following output:
calling sample_1's doSomething
exception java.lang.ArithmeticException: / by zero
value of i 10
calling sample_2's doSomething
value of i 50
The output shows that calling sample_1 ’s doSomething method results in execution of both catch and finally
blocks. And, even though calling sample_2 ’s doSomething method doesn’t result in an exception, the finally
block is still executed.
NOTEA statement inside a finally block can also throw an exception. If an exception is thrown from
the finally block, the program execution stops and the exception is returned to the calling method.
Let’s now look at how to create custom exception types and throw them.
8-4 Custom exception types
You can create a checkedexception type by extending java.lang.Exception , and you can create an
uncheckedexception type by extending java.lang.RuntimeException .
NOTE You can create an exception type by directly extending java.lang.Throwable . An exception type
created by extending java.lang.Throwable is treated as an unchecked exception. It is recommended that
you don’t create a customexception type by directly extending java.lang.Throwable class.Instead,
use java.lang.Exception (for checked exceptions) or java.lang.RuntimeException (for unchecked exceptions).
Let’s now look at a modified version of internet banking application that throws a
custom InsufficientBalanceException exception type when the bank account doesn’t have sufficient balance
for performing fund transfer.
IMPORTIt is recommended that you import the custom-exception project into your Eclipse IDE.
The following listing shows the InsufficientBalanceException class that represents insufficient balance in a
bank account:
Listing 8-18 InsufficientBalanceException class
Project: custom-exception
Source location: src\com\sample\InsufficientBalanceException.java
1 package com.sample;
2
3 public class InsufficientBalanceException extends RuntimeException {
4 public InsufficientBalanceException(int accountNumber, int balance) {
5 super("The bank account " + accountNumber + " has balance " + balance);
6 }
7 }
InsufficientBalanceException extends java.lang.RuntimeException ;
therefore, it’s an unchecked exception
type. InsufficientBalanceException ’s constructor accepts accountNumber (the bank account number) and balance
(current balance in the bank account) as arguments. InsufficientBalanceException ’sconstructor
calls RuntimeException ’s constructor (line #5) and passes the exception message. The exception message
is stored as an instance variablein the RuntimeException object, and can be accessed by calling the
inherited getMessage method of RuntimeException .
The following listing shows the Account class that throws InsufficientBalanceException if the current balance
(represented by currentBalance instance variable) is less than the amount being transferred(represented
by amt argument passed to debit method):
Listing 8-19 Account class – throwing custom exception
Project: custom-exception
Source location: src\com\sample\Account.java
1 package com.sample;
2
3 public class Account {
4 private int accountNumber;
5 private int currentBalance;
6 .....
7 public void debit(int amt) {
8 int tempBalance = currentBalance - amt;
9 if (tempBalance < 0) {
10 throw new InsufficientBalanceException(accountNumber, currentBalance);
11 }
12 currentBalance = tempBalance;
13 }
14 .....
15 }

On line #8, the debit method stores the result of subtracting amt amount from currentBalance into tempBalance
variable. If tempBalance < 0 condition evaluates to true , it means that subtracting amt amount
from currentBalance results in negative account balance.For this reason, if tempBalance < 0 evaluates to true ,
an object of InsufficientBalanceException class is created using the new keyword and thrown using the throw
statement (refer line #10).
A throw statement has the following syntax:
throw <a-Throwable-object>;
here, <a-Throwable-object>is any object that extends directly or indirectly java.lang.Throwable
If you now open the InternetBanking class (which is same as shown in listing 8-7) of custom-
exception project and run its main method, you’ll get the following output:
Exception in thread "main" com.sample.InsufficientBalanceException: The bank account 1 has balance 1000
at com.sample.Account.debit(Account.java:19)
at com.sample.FundTransfer.transferFunds(FundTransfer.java:5)
at com.sample.InternetBanking.main(InternetBanking.java:8)

The output shows that an attempt to transfer 1400 from xAcc to yAcc resulted
in InsufficientBalanceException thrown by the Account ’s debit method. The exception message "The bank account 1
has balance 1000" was set while creating the InsufficientBalanceException object (refer line #5 of listing 8-
18).The JVM obtains the exception message associated with the InsufficientBalanceException object by
calling its getMessage method and writes it to the output.
NOTE You can use throw statement inside catch and finally blocks also to throw exceptions.
Let’s look at how the program wouldhave looked if we had defined InsufficientBalanceException as a
checked exception.
Hands-on Modify InsufficientBalanceException class to extend java.lang.Exception
The following listing shows the modified InsufficientBalanceException class that extends
from java.lang.Exception :
Listing 8-20 InsufficientBalanceException class – a checked exception
1 package com.sample;
2
3 public class InsufficientBalanceException extends Exception {
4 public InsufficientBalanceException(int accountNumber, int balance) {
5 super("The bank account " + accountNumber + " has balance " + balance);
6 }
7 }
As the InsufficientBalanceException class nowinherits from java.lang.Exception class, it represents a checked
exception. As shown in figure 8-7, you’ll now notice that the Account class shows compilation error on
the line where we throw InsufficientBalanceException . Account class shows compilation error because
its debit method throws InsufficientBalanceException – a checked exception. The compilation error message
is 'Unhandled exception type InsufficientBalanceException'.
We saw in earlier examples that if you don’t catch an unchecked exception, it is simply propagated to
the calling method. On the other hand, a checked exception must be caught in the method or
specifiedin the method definition using the throws clause.

Figure 8-7 Account class fails to compile because InsufficientBalanceException is a checked exception
So, for successfully compiling the Account class we must specify that the debit method
throws InsufficientBalanceException or catch it in the debit method itself. The following listing shows the
modified debit method that specifies that it throws InsufficientBalanceException :
Listing 8-21 Account class’s debit method – throws clause usage
1 public void debit(int amt) throws InsufficientBalanceException {
2 int tempBalance = currentBalance - amt;
3 if (tempBalance < 0) {
4 throw new InsufficientBalanceException(accountNumber, currentBalance);
5 }
6 currentBalance = tempBalance;
7 }

In the above listing, we’ve added the throws clause to the debit method definition. The debit method now
clearly indicates that it throws InsufficientBalanceException which the calling method can catch and attempt
to recover from it.
NOTE You should note that an unchecked exception represents a programming error (like, division
by zero); therefore, a calling method should not attempt to recover from it. For this reason, throw an
unchecked exception if you expect that the calling methods can’t recover from it. And, you should
throw a checked exception if you expect that the calling methods can recover from it.
Adding throws clause to Account class’s debit method results in compilation error in the FundTransfer
class(refer figure 8-8). The line on which we call Account ’s debit method shows compilation error
because the debit method is defined to throw InsufficientBalanceException checked exception (refer listing 8-
21). The transferFunds method must either catch InsufficientBalanceException or specify that it also
throws InsufficientBalanceException .
Figure 8-8 FundTransfer class fails to compile because the transferFunds method doesn’t
catch InsufficientBalanceException or specify that it throws InsufficientBalanceException
NOTEWhen InsufficientBalanceException was defined as an unchecked exception, it was notrequired
for FundTransfer ’s transferFunds method to catch the exception or specify it using the throws clause. This
shows that if a method calls a method that throws a checked exception, the calling method must either
catch the checked exception or specify it using the throws clause.
The following listing shows the modified transferFunds method that uses the throws clause to specify that
it throws InsufficientBalanceException :
Listing 8-22 FundTransfer class
1 package com.sample;
2
3 public class FundTransfer {
4 public static boolean transferFunds(Account xAcc, Account yAcc, int amt)
5 throws InsufficientBalanceException {
6 xAcc.debit(amt);
7 yAcc.credit(amt);
8 System.out.println("Completed fund transfer");
9 return true;
10 }
11 }
The FundTransfer class will now compile successfully.
NOTE If a method throws multiple checked exceptions, you can specify comma-separated names of
those exceptions in the throws clause.
You’ll now notice that the InternetBanking ’s main method shows compilation error (refer figure 8-9) on
the line where the call is made to FundTransfer ’s transferFunds method. As
the FundTransfer ’s transferFunds method specifies that it throws InsufficientBalanceException , the main method
must either catch the exception or specify it using the throws clause.

Figure 8-9 InternetBanking class fails to compile because it must either catch InsufficientBalanceException or
specify that the main method throws it
As we don’t want the InsufficientBalanceException to propagate to the JVM, modify InternetBanking ’s main
method to catch the exception, as shown here:
Listing 8-23 InternetBanking class– catching InsufficientBalanceException
1 package com.sample;
2
3 public class InternetBanking {
4 public static void main(String args[]) {
5 Account xAcc = new Account(1, 1000);
6 Account yAcc = new Account(2, 1200);
7
8 try {
9 FundTransfer.transferFunds(xAcc, yAcc, 1400);
10 } catch (InsufficientBalanceException ex) {
11 System.out.println("Failed to transfer money. Reason: --> " + ex.getMessage());
12 }
13 .....
14 }
15 }

In the above listing, call to FundTransfer ’s transferFunds method (line #9) is surrounded by try - catch
block.The catch block catches InsufficientBalanceException and prints the exception message on the output
(line #11).Notice that we’ve explicitly called the getMessage method of InsufficientBalanceException object to
obtain the exception message.
If you run InternetBanking ’s main method, you’ll get the following output:
Failed to transfer money. Reason: --> The bank account 1 has balance 1000
xAcc’s current balance 1000
yAcc’s current balance 1200
Completed execution of main method

If we had let the InsufficientBalanceException propagate to JVM, the output would have consisted of
methods and Java classes that come into picture when InsufficientBalanceException is thrown. The above
output is simple to understand and has relevant details that tellwhy the program failed to transfer
money from xAcc to yAcc account. This graceful handling of exceptions is required in real-world Java
applications.
QUIZ
8-1: Which of the following statements are true about exceptions?
a) an unchecked exception represents a programming error
b) a checked exception represents a recoverable exception
c) if an exception class extends from java.lang.Exception , then it represents an unchecked
exception
d) if an exception class extends from java.lang.RuntimeException , then it represents a checked
exception
e) java.lang.Error and its subclasses represent unrecoverable exceptions
8-2: Consider the following Calculator class whose calculate method performs calculations on the
supplied number:
1 public class Calculator {
2 private int memory;
3
4 public void calculate(int i) {
5 memory = i;
6 memory = memory + 10; increment memory by 10
7 try {
8 memory = memory / 0; divide memory by 0
9 } catch (ArithmeticException ae) {
10 memory = memory + 10; increment memory by 10
11 memory = memory / 0; divide memory by 0
12 } finally {
13 memory = memory * 2; multiply memory by 2
14 memory = memory / 0; divide memory by 0
15 }
16 }
17
18 public int getMemory() {
19 return memory;
20 }
21 }

What would be the output from executing the following main method?
1 public static void main(String args[]) {
2 Calculator calculator = new Calculator();
3 try {
4 calculator.calculate(5); call Calculator ’s calculate method
5 } catch (Exception e) {
6 System.out.println(calculator.getMemory()); print the value of memory variable
7 }
8 }

8-3: Consider the following doSomething method:


1 public void doSomething() {
2 try {
3 Object object = new Rectangle();
4 String string = (String)object; object is downcasted to String
5 } catch(RuntimeException re) {
6 System.out.println("RuntimeException");
7 } catch(ClassCastException cce) {
8 System.out.println("ClassCastException");
9 }
10 }

What will be the output from executing the doSomething method?


a) "RuntimeException"
b) "ClassCastException"
c) "RuntimeException" followed by "ClassCastException"
d) The program fails to compile
8-4: Consider the following MyException and MyClass classes:
1 public class MyException extends ClassCastException {
2 public MyException() {
3 super("MyException");
4 }
5 }
1 public class MyClass {
2 public void doSomething() {
3 try {
4 Object object = new Rectangle();
5 String string = (String)object;
6 } catch(MyException me) {
7 System.out.println("catching MyException");
8 } finally {
9 System.out.println("executing finally block");
10 }
11 }
12 }

What would be the output from executing MyClass ’s doSomething method?


a) "catching MyException"
b) "executing finally block"
c) "catching MyException" followed by "executing finally block"
d) MyClass fails to compile
8-5: Consider the following CatchException classin which the catch block catches java.lang.Throwable :
1 public class CatchException {
2 public void doSomething() {
3 try {
4 int i = 1/0; throws java.lang.ArithmeticException
5 } catch(Throwable throwable) { catches java.lang.Throwable
6 System.out.println("catching java.lang.Throwable exception");
7 }
8 }
9 }
Which of the following statements are correct about CatchException class?
a) The class fails to compile because a catch block can only catch exceptions that are of
type java.lang.Exception or its subtype
b) ArithmeticException thrown on line #4 is not caught by the catch block
8-5 Summary
In this chapter, we saw how you can throw and catch exceptions. A real-world Java application
typically defines some custom exceptions that are specific to the problem domain. For instance, we
defined InsufficientBalanceException to represent insufficient balance in bank account. As incorrect
placement of try-catch block can result in incorrect result, you should carefully consider what
statements of a method should be enclosed within try block, andwhat does the catch block should do in
case an exception occurs.
Chapter 9 – Arrays, immutability, recursive
methods and wrapper classes
9-1 Introduction
Let’s say that you are developing a program which sorts a given set of integer numbers and arranges
them in an ascending order. If the number of integers to sort is 10, will you create10 int type variables
in your program to store these integers? Once you have sorted the integers, how will you store the
integers in a sorted order in your program? In this scenario, you can use arrays to simplify writing
your program.
An array is an object that can store a fixed number of objects or primitive types. The objects or
primitives stored in an array are referred to as elements of the array. You should note that an array
can only store a singletype of object or primitive type. For instance, you can’t store both int and float
types in the same array.
In this chapter, we’ll look at:
how to define a variable of array type
how to initialize an array
how to access elements of an array
why String is an immutable object?
a recursive program that finds factorial of a given number
a recursive program that uses binary search to find a number
wrapper classes corresponding to primitive data types
Let’s begin by looking at how arrays are created and initialized.
IMPORTIt is recommended that you import the array project into your Eclipse IDE.
9-2 Creating and initializing arrays
The syntax for defining and creating an array is:
<type> [] <variable-name> = new <type> [ <number-of-elements> ];
here, <type> is the type of object (or primitive type) that can be stored in the array,
<variable-name> is the variable name with which we are defining the array in our program,
and <number-of-elements> is the maximum number of objects (or primitive types) that this
array can store
NOTEIf you see [] following a primitive or object type, it means we are referring to an array of that
primitive or object type. For instance int[] represents an int array. We saw that the main method accepts
a String[] as argument, which means that it accepts a String array.
The following statement creates an int array that can store up to 10 int values:
int[] numbers = new int[10];

The following figure shows how this array looks like:

The above figure shows that new int[10] expression creates an array with 10 placeholders for storing int
type values. And, each placeholder is initialized with the default value of int , which is 0 . You should
note that the placeholders are numbered from 0 to 9 .
The following statement creates a float array that can store up to 10 floating-point numbers:
float[] floatingNumbers = new float[10];

As in the case of int[] , each placeholder of floatingNumbers array is initialized with the default value
of float type, which is 0.0f .
The following statement creates a Person[] that can store 10 Person objects:
Person[] persons = new Person[10];

The new Person[10] creates a Person array with 10 placeholders for storing Person type objects. And,
because Person is an object, each placeholder is initialized with null . As mentioned earlier, these
placeholders are numbered from 0 to 9 .
NOTE The maximum number of elements that an array can store is referred to as the size of the
array.For instance, the size of numbers , floatingNumbers and persons arrays is 10 .
You set an element of an array by using the following syntax:
<array-variable>[<index>] = <object-or-value>;
here, <array-variable> is the name of the array variable, <index> is the index of the
placeholder, and <object-or-value> is the object or value that you want to put in that
placeholder
The following statement shows how you can assign the value 21 (an int type) to the placeholder on
index 5 of numbers array:
numbers[5] = 21;

The following figure shows the numbers array after the value 21 is added to index 5 :

As placeholders are numbered starting from 0 , numbers[5] refers to the 6th placeholder in the array from
the left.
The following statement shows how you can assign a Person object to the placeholder on
index 8 of persons array:
persons[8] = new Person(1, "A");

As placeholders are numbered starting from 0 , the Person object is added to 9th placeholder from the
left.
Instead of creating an array and then individually setting each array element, you can use the
following syntax to create and initialize an array in a single statement:
<type> [] <variable-name> = { <comma-separated-objectsOrValues> };

here, <type> is the type of object (or primitive type) that can be stored in the array,
<variable-name> is the variable name with which we are defining the array in our program,
and <comma-separated-objectsOrValues> is the comma-separated list of objects (or
values) that you want to assign to each placeholder in the array
The following statement creates an int type myNumbers array which contains numbers from 25 to 32 :
int[] myNumbers = { 25, 26, 27, 28, 29, 30, 31, 32 };

The sizeof myNumbers array is the number of elements we’ve stored in it, which is 8 .
The following statement creates a Person[] :
Person[] myPersons = { new Person(1, "A"), new Person(2, "B"), new Person(3, "C") };

The myPersons array is initialized with 3 Person objects, that is, the sizeof myPersons array is 3 .You
should note that myPersons array only stores memory address of Person objects, the actual Person objects
are stored in the heap memory area of the computer.
length attribute
You don’t need to remember the size of an array, each array type object is associated with
a length attribute that tells the size of the array. For instance, you can determine the size
of myPersons array by simply accessing its length attribute, as shown here:
System.out.println("length of myPersons array is " + myPersons.length);
Let’s now look at how we can access elements of an array.
9-3 Accessing array elements
You can access the elements of an array using their index, as shown here:
System.out.println(numbers[5]);

The above statement prints the value ofelement on index 5 of numbers array.
A simpler approach to accessing array elements is to use a for loop, as shown in the following listing:
Listing 9-1 SimpleArray class – using the for loop to iterate over array elements
Project: array
Source location: src\array\SimpleArray.java
1 package array;
2
3 public class SimpleArray {
4 private static Person[] persons = { new Person(1, "A"), new Person(2, "B"), new Person(3, "C") };
5
6 public static void main(String args[]) {
7 for(int i = 0; i < persons.length; i++) {
8 System.out.println(persons[i]);
9 }
10 }
11 }

On line #4, we create a Person[] with 3 Person objects.On line #7, the for loop is used to iterate over all
the elements of persons array.As the placeholders are numbered starting from 0 , the value of i in
the for loop is initialized to 0 . On line #8, we access the element at index i of persons array and write
its value to the output.
The condition i < persons.length specifies that the for loop executesas long as the value of i is less than the
size of persons array (that is, persons.length ). This makes sense because ifthe size of persons array is 3 , we
don’t want the value of i to go beyond 2 . When the value of i becomes 3 , persons[3] will refer to a non-
existent array element.
So, what happens if you try to access a non-existent array element? Let’s look at this by changing
the SimpleArray class.
Hands-on Modify SimpleArray class to access a non-existent array element
The following listing shows the modified SimpleArray class that accesses 4th element (which doesn’t
exist) of persons array:
Listing 9-2 SimpleArray class– accessing 4th element of persons array
1 package array;
2
3 public class SimpleArray {
4 private static Person[] persons = { new Person(1, "A"), new Person(2, "B"), new Person(3, "C") };
5
6 public static void main(String args[]) {
7 for(int i = 0; i <= persons.length; i++) {
8 System.out.println(persons[i]);
9 }
10 }
11 }
We’ve only changed the for loop condition from i < persons.length to i <= persons.length . This means,
the for loop will continue to execute till the value of i becomes 4 . So, the for loopis executed for the
following values of i : 0 , 1 , 2 , and 3 .When the value of reaches 3 , the persons[3] will refer to a non-
existent element in persons array, as shown in the following figure:

If you now run the SampleArray ’s main method, you’ll see the following output:
Person [age=1, name=A]
Person [age=2, name=B]
Person [age=3, name=C]
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 3
at array.SimpleArray.main(SimpleArray.java:8)
The output shows that when the value of i was 0 , 1 and 2 , the program successfully printed the details
of Person objects.When the value of i reached 3 ,the expression persons[3] resulted
in java.lang.ArrayIndexOutOfBoundsException (an unchecked exception) indicating that you are accessing an
element beyond the size of the array.
9-4 Passing and returning arrays
Array is just like any other Java object thatextends from java.lang.Object . You can pass arrays as
arguments to methods and constructors, and also specify them as return types of methods.
The following listing shows the MyArray class whose constructor accepts an int[] argument:
Listing 9-3 MyArray class
Project: array
Source location: src\array\MyArray.java
1 package array;
2
3 public class MyArray {
4 private int[] numbers;
5
6 public MyArray(int[] numbers) {
7 this.numbers = numbers;
8 }
9
10 public int[] getNumbers() {
11 return numbers;
12 }
13
14 public void setNumbers(int[] numbers) {
15 this.numbers = numbers;
16 }
17 }
The above listing shows that MyArray ’s constructor accepts an int[] argument (line #6) that is assigned
to int[] type instance variablenamed numbers (line #4).The setNumbers method (line #14) accepts an int[]
argument that is assigned to the numbers variable.As the getNumbers method (line #10) returns
the numbers variable, its return type is specified as int[] .
The following listing shows ArrayTest class whose main method creates an instance of MyArray class and
calls it getNumbers and setNumbers methods:
Listing 9-4 ArrayTest class
Project: array
Source location: src\array\ArrayTest.java
1 package array;
2
3 public class ArrayTest {
4 public static void main(String args[]) {
5 int[] numbers = { 1, 10, 20, 500 };
6 MyArray myArray = new MyArray(numbers);
7 int[] newNumbers = { 10, 20, 40, 50, 60 };
8 myArray.setNumbers(newNumbers);
9
10 int[] returnedNumbers = myArray.getNumbers();
11 for (int i = 0; i < returnedNumbers.length; i++) {
12 System.out.println(returnedNumbers[i]);
13 }
14 }
15 }
In the above listing, we first create MyArray object (line #6) by passing the numbers array (line #5)
to MyArray ’s constructor. The numbers array is assigned to MyArray ’s numbers array (refer line #7 in
listing 9-3). We then call the setNumbers method to set the MyArray ’s numbers arrayto newNumbers array.In
the end, we call MyArray ’s getNumbers method thatreturns the MyArray ’s numbers array.
Let’s now look at how you can create and use multi-dimensional arrays.
9-5 Multi-dimensional arrays
The arrays that we’ve seen so far in this chapter are examples of one-dimensional arrays. A one-
dimensional array is suitable to represent a sequence, like a queue at a store, price of items for sale at
an e-commerce website, and so on. When it comes to representing seating arrangement in an
auditorium or location of items stored in a warehouse, you need multi-dimensional arrays.

In a multi-dimensional array, an array element itself contains another


array. For instance, consider the following seating arrangement in an auditorium:

In the above figure, each box represents a seat in the auditorium and the alphabet represents the
person to whom the seat is assigned. There are 5 seats from left to rightand 4 seats from front to
back. The above seating arrangement can be easily represented by a 2-dimensional array – one
dimension tells about the seat position from left and the other dimension tells the seat position from
front. The following figure shows seat positions from left and front:

In the above figure, each seat has a left-index (which tells the position of the seat from left side) and a
front-index (which tells the position of the seat from the front). If we represent each seat with (left-
index, front-index) format, then we can make the following statements about the above seating
arrangement: seat (0,0) is assigned to A , seat (0, 1) is assigned to T , seat (1,0) is assigned to S , and so on.
The syntax for defining a 2-dimensional array is:
<type> [][] <variable-name> = new <type> [ <number-of-elements-in-dimension-one> ]
[ <number-of-elements-in-dimension-two> ];

here, <type> is the type of object (or primitive type) that you want to store in the array,
<variable-name> is the variable name with which we are defining the array in our program,
and <number-of-elements-in-dimension-one> and <number-of-elements-in-dimension-
two> is the maximum number of objects (or primitive types) that can be stored in the two
dimensions.
For instance, the following 2-dimensional array can hold the seating arrangement shown in figure 9-5:
String[][] seating = new String[5][4];
5 and 4 are the number of seats in each dimension (left to right and front to back). As we want to the
store name of the person who’ll be sitting in a seat, we’ve specified the type the 2-dimensional
arrayas String . The following statements show how we assign person names to different seats:
seating[0][0] = "A";
seating[0][1] = "T";
seating[1][0] = "S";
.....
When initializing a 2-dimensional array, each array element itself is defined as an array:
String[][] seating = {
{"A", "T", "O", "F"}, array at seating[0] . 0 is the left-index
{"S", "B", "G", "N"}, array at seating[1] . 1 is the left-index
.....
};
The seating[0] element is {"A", "T", "O", "F"} array,
which means seating[0][0] is "A" , seating[0][1] is "T" , and so
on. Similarly, seating[1] element is {"S", "B", "G", "N"} array.
You can access an element of a 2-dimensional array by specifyingvalues for both the dimensions. For
instance, seating[2][3] will return H if the seating arrangement is as shown in figure 9-5.
As the number of dimensions increase, the number of brackets [] also increase in the definition of the
array. For instance, you might use a 3-dimensional array to store location of a product in the
warehouse, as shown here:
String[][][] products = new String[depth-index][left-index][height-index];
The 3 dimensions in this array are:
depth-index : distance inside the warehouse where the product is located
left-index : distance to the left (or right) of the entry gate of warehouse where the product is
located
height-index : height at which the product is located
The above 3 dimensions can get us to the product in the warehouse. For instance, this is how you can
specify that "Table" product is located at 100 meters inside, 200 meters left and at 50 meters height in
the warehouse:
products[100][200][50] = "Table";

NOTEAs in the case of one-dimensional arrays, you can use the length attribute to determine the size
of a multi-dimensional array.
Let’s now look at what makes String an immutable (or unmodifiable) object.
IMPORTIt is recommended that you import the string project into your Eclipse IDE.
9-6 String object and immutability
Stringobject defines methods that you can use to work with strings in your Java program. The
following listing shows the StringTest class whose main method creates a String and uses some of its
methods:
Listing 9-5 StringTest class– methods of String object
Project: string
Source location: src\string\StringTest.java
1 package string;
2
3 public class StringTest {
4 public static void main(String args[]) {
5 String text = "My name is";
6
7 String uppercase = text.toUpperCase();
8 System.out.println("uppercase string is : " + uppercase);
9 System.out.println("text is now --> " + text);
10
11 String concatenated = text.concat(" A");
12 System.out.println("concatenated string is : " + concatenated);
13 System.out.println("text is now --> " + text);
14
15 String lowercase = text.toLowerCase();
16 System.out.println("lowercase string is : " + lowercase);
17 System.out.println("text is now --> " + text);
18 }
19 }

On line #5, we define a String named text and set it to "My name is" string. On
line#7, String ’s toUpperCase method is called on text to convert all its characters into uppercase.On line
#11, String ’s concat method is called on text to concatenate string " A" to text .On line
#15, String ’s toLowerCase method is called on text to convert all its characters to lowercase.After each
method of String object is called, we write the original value of text to the output (refer line #9, #13
and #17).
If you run StringTest ’s main method, you’ll get the following output:
uppercase string is : MY NAME IS
text is now --> My name is text is unchanged
concatenated string is : My name is A
text is now --> My name is text is unchanged
lowercase string is : my name is
text is now --> My name is text is unchanged
The output shows that calling toUpperCase method on text returnsa String that has all its characters in
uppercase, but the original text object remains unchanged to "My name is" . This means, instead of
modifying the text object, the toUpperCase method returnsa new String object. As in the case of toUpperCase
method, concat and toLowerCase methods returnnew String objects. In fact, all the methods of String object
leave the original String object unchangedand return a new String object. This means, once you create
a String object, you can’t change the text or string it holds. This behavior of an object is referred to as
immutability, and the object is referred to as an immutable object.
An immutableobject (like the String object) is an object whose state (that is, instance variables)
can’tbe modified once the object is created. The string or text that a String object holds represents its
state, and because it can’t be changed, String is an immutable object. A mutable object is an object
whose state can be modified after the object is created.
Let’s now look at what is recursion and how it is useful in implementing complex programs.
9-7 Recursion
The methods that we’ve seen so far call other methods of the same or different object. When a
method calls itself, it is referred to as a recursive method. Writing a recursive method is useful when
you can break a programming problem into smaller problems that are solved when the method calls
itself. The method continues to call itself till the time problem becomes so small that the method can
solve it without calling itself again. This is when the recursion ends.
IMPORTIt is recommended that you import the recursion project into your Eclipse IDE.
Let’s look at a simple example that calculates factorial of a given number.
Calculating factorial of a number using recursion
Factorial of a number n (represented by n! ) is multiplication of all the integers from 1 to n .
1! = 1
2! = 2 (2x1)
3! = 6 (3x2x1)
4! = 24 (4x3x2x1)
5! = 120 (5x4x3x2x1)

Let’s say we definea factorial method that calculates factorialof a given number n . For
example,calling factorial(5) returns 120 , calling factorial(4) returns 24 , and so on.
The way factorial is calculated, the calculation of factorial(5) can be broken down as:
factorial(5) = factorial(4) x 5
factorial(4) = factorial(3) x 4
factorial(3) = factorial(2) x 3
factorial(2) = factorial(1) x 2
factorial(1) = 1

This shows that you can generalize calculation of factorial as factorial(n) = factorial(n-1) x n .
As in the case of factorial(5) calculation, you can break down the calculation of factorial(n) like this:
factorial(n) = factorial(n-1) x n
factorial(n-1) = factorial(n-2) x (n-1)
factorial(n-2) = factorial(n-3) x (n-2)
.....
factorial(1) = 1

This means, the following sequence of steps are followed when factorial(n) is called:
factorial(n) callsitself with argument n-1 and multiplies the returned result with n
factorial(n-1) callsitself with argument (n-2) and multiples the returned result with (n-1)
factorial(n-2) calls itself with argument (n-3) and multiples the returned result with (n-2)
.....

factorial(1) returns 1

This shows that the factorial method continues calling itself till the argument passed to the factorial method
reaches 1 . When the argument becomes 1 , the factorial method simply returns 1 .
Listing 9-6 shows the Factorial class that defines a factorial method for calculating factorial of a given
number. As shown in the listing, a recursive method has a base case and a recursive case. The
recursive case represents a condition in which the recursive method calls itself. The base case
represents a condition in which the recursive method doesn’t call itself. A recursive method
musthave a base case to ensure that the recursive method ends. In the factorial method, recursive case is
when number > 1 (refer line #8),and base case is when number == 1 (refer line #5).

Listing 9-6 Factorial class– factorial recursive method


Project: recursion
Source location: src\recursion\Factorial.java

Factorial ’s main
method calls the factorial method with argument 5 . If you run the main method, you’ll
get 120 as output, which is factorial of number 5 .
Let’s look at another program that uses binary search to find a number in an array.
Finding a number using binary search
Let’s say that you are given a sorted array of integers, and you have to find number 45 in that array. A
simple approach is to sequentially look at each element in the array and check if it is 45 . The
following listing shows this approach:
Listing 9-7 SimpleSearch class – searching for a number sequentially in a given sorted array
Project: recursion
Source location: src\recursion\SimpleSearch.java
1 package recursion;
2
3 public class SimpleSearch {
4 private static int[] numbers = { 1, 2, 10, 25,
5 30, 33, 37, 40, 45, 50, 55, 56,
6 58, 60, 66 };
7
8 public static void main(String args[]) {
9 int counter = 0;
10 for(int i = 0; i < numbers.length; i++) {
11 counter++;
12 if(numbers[i] == 45) {
13 System.out.println("Number 45 found on index " + i);
14 System.out.println("counter " + counter);
15 break;
16 }
17 }
18 }
19 }

In the above listing, the numbers array (line #4) stores integers in the ascending order.The main method
uses the for loop (line #10) to check each element of numbers array. When number 45 is found, the for
loop terminates.The counter variable is defined to calculate the number of times for loop executes
before number 45 is found. If you execute SimpleSearch ’s main method, you’ll get the following output:
Number 45 found on index 8
counter 9

The output shows that number 45 is found after the for loop is executed 9 times, that is,
after 9 times number[i] == 45 comparison is done.
Unlike sequential search, binary search checks if the middle element of the sorted array is the number
we are searching for. If not, it searches either the left- or right-half of the array. This process is
repeated till the element is found or no elements are left to search. The following figures show step
by step how binary search findsnumber 45 in numbers array that we saw in listing 9-7:

At first, the middle element of the numbers array is selected, which is 40 . As 40 is less than 45 , the
elements on the left side of 40 are ignored and elements on the right side are considered for finding the
number 45 . You should note that the elements in the array must be sorted for the binary search to
work. If the elements are not sorted, we won’t know whether to search on the left or right side of the
middle element.

Once again the middle element is selected from the list of elements on the right side of element 40 . As
the middle element 56 is greater than 45 , elements to the right side of 56 are ignored.

The middle element now is 50 which is greater than 45 ; therefore, the elements to the right of 50 are
ignored. This leaves us with only one element on the left side of 50 , and that is 45 .

As the only one element left to search is 45 , and it is the same number we were searching for, the
binary search ends.
As you can see, binary search requiresonly 4 comparisons (instead of 9 comparisons as in the case of
sequential search) to find the number 45 .
Let’s see how to implement binary search using recursion.
Implementing binary search
We can implement binary search using recursion because the search is repeated by splitting the array
into halves until the number is found or there is nothing left to be searched in the array.
The following listing shows how binary search is implemented using recursion:
Listing 9-8 BinarySearch class – finding a number using binary search
Project: recursion
Source location: src\recursion\BinarySearch.java
1 package recursion;
2
3 public class BinarySearch {
4
5 private static void binarySearch(int[] numbers, int startIndex, int endIndex, int myNumber) {
6 int middleIndex = startIndex + (endIndex - startIndex)/2;
7 int middleElement = numbers[middleIndex];
8 if(middleElement == myNumber) { base case
9 System.out.println("Number " + myNumber + " found on index " + middleIndex);
10 return;
11 }
12 if(middleElement > myNumber) { recursive case
13 //--search the array on the left of middleElement
14 binarySearch(numbers, startIndex, middleIndex - 1, myNumber);
15 }
16 if(middleElement < myNumber) { recursive case
17 //-- search the array on the right of middleElement
18 binarySearch(numbers, middleIndex + 1, endIndex, myNumber);
19 }
20 }
21
22 public static void main(String args[]) {
23 int[] numbers = { 1, 2, 10, 25, 30, 33, 37, 45, 47, 50, 55, 56,58, 60, 66, 67, 80, 83, 84 };
24 binarySearch(numbers, 0, numbers.length - 1, 45);
25 }
26 }

Thefollowing is the signature of binarySearch method:


binarySearch(int[] numbers, int startIndex, int endIndex, int myNumber)

here, myNumber is the number to be searched in numbers array, startIndex and endIndex are the start
and end indexes inthe numbers array within which myNumber is searched
The following steps are followed by the binarySearch method to find myNumber in numbers array:
the binarySearch method finds the index of the middleelement of the numbers array
using startIndex and endIndex arguments (line #6):
int middleIndex = startIndex + (endIndex – startIndex)/2

if the middle element (that is, numbers[middleIndex] ) is equal to myNumber (line #8), the binarySearch
method ends. This represents the base case.
if middle element is greater than myNumber (line #12), it means that myNumber needs to be
searched in the index ranging from startIndex to middleIndex -1 . This represents a recursive case.
At this time, binarySearch method calls itself with modified indexes: binarySearch(numbers, startIndex,
middleIndex – 1, myNumber)

if middle element is less than myNumber (line #16), it means that myNumber needs to be searched
in the index ranging from middleIndex to endIndex. As this represents a recursive case,
binarySearch method calls itself with modified indexes: binarySearch(numbers, middleIndex + 1,
endIndex, myNumber)

BinarySearch ’s main method defines a numbers array (line #23) and calls the binarySearch method for finding
number 45 in the array.If you run BinarySearch ’s main method, you’ll get the following output:
Number 45 found on index 7
If youchange the BinarySearch ’s main method to search for a number (let’s say 46 ) that doesn’t exist in
the numbers array, you’ll get the following output:
Exception in thread "main" java.lang.StackOverflowError
at recursion.BinarySearch.binarySearch(BinarySearch.java:6)
at recursion.BinarySearch.binarySearch(BinarySearch.java:14)
....
The above output shows that java.lang.StackOverflowError is thrown by the binarySearch method when a
number is notfound in the numbers array.
During program execution, the details of methods being executed (like, method arguments and local
variables) are maintained in the stack memory area of the computer. When a recursive method is
executed, the detail of each recursive method call is maintained in the stack memory area. If the
recursive method doesn’tterminate, it ends up filling up the stack memory area, resulting
in java.lang.StackOverflowError . This is the reason why binarySearch method throws StackOverflowError .
The binarySearch method misses the base casein which the myNumber is notfound in the numbers array, this
results in the binarySearch method calling itself forever.
The following listing shows the modified binarySearch method that addsthe base case in which myNumber
is notfound in the numbers array:
Listing 9-9 BinarySearch class– adding the base case in which myNumber is not found
1 package recursion;
2
3 public class BinarySearch {
4
5 private static void binarySearch(int[] numbers, int startIndex, int endIndex, int myNumber) {
6 int middleIndex = startIndex + (endIndex - startIndex)/2;
7 int middleElement = numbers[middleIndex];
8 if(middleElement == myNumber) {
9 System.out.println("Number " + myNumber + " found on index " + middleIndex);
10 return;
11 }
12 if(endIndex == startIndex) {
13 System.out.println("Number " + myNumber + " NOT found");
14 return;
15 }
16 .....
17 }
18 .....
19 }

When only one element of numbers array is left to search, then the middleElement (refer line #7) holds that
element. At this time, there are two possible base cases:
the middleElement is equal to myNumber – this base case is taken care by the if statement on line #8
there are no more elements left to search in the numbers array, that is, endIndex == startIndex – this
base case is taken care by the if statement on line #12
If you now run the BinarySearch ’s main method and search for a number (let’s say 46 ) that doesn’t exist in
the numbers array, you’ll get the following output:
Number 46 NOT found

This shows that the if statement on line #12 evaluatesto true when the value of myNumber is 46 .
9-8 Wrapper classes
You can treat primitive types as objects by using Java’s wrapper classes. A wrapper class holds a
primitive type and provides methods to perform common functions related to that primitive type.
The following table shows the classes defined by Java corresponding to different primitive types:
Table 9-1 – Primitive types and the corresponding Java classes
Primitive Wrapper class
type
byte java.lang.Byte
short java.lang.Short
int java.lang.Integer
long java.lang.Long
float java.lang.Float
double java.lang.Double
char java.lang.Character
boolean java.lang.Boolean

As the wrapper classes are defined in the java.lang package, they are implicitly imported into other
Java classes. In listing 3-5 of chapter 3, we saw that Integer ’s parseInt static method was used to convert
a String type value to int .
NOTE java.lang.Number is the superclass of all numeric type wrapper classes.
IMPORTIt is recommended that you import the wrapper-classes project into your Eclipse IDE.
The following listing shows the Wrapper class of wrapper-classes project whose callStaticMethods method
makes use of some of the static methods defined by wrapper classes:
Listing 9-10 Wrapper class – static methods defined by some of the wrapper classes
Project: wrapper-classes
Source location: src\wrapper\Wrapper.java
1 package wrapper;
2
3 public class Wrapper {
4 .....
5 private static void callStaticMethods() {
6 int i = Integer.parseInt("1");
7 int max = Integer.max(10, 20);
8 short s = Short.parseShort("2");
9 boolean b = Boolean.parseBoolean("true");
10 .....
11 }
12 .....
13 }
On line #6, Integer ’s parseInt method takes a String argument and returns the corresponding int type. On
line #7, Integer ’s max method returns the maximum of the two int types passed as arguments. On line
#8, Short ’s parseInt method takes a String argument and returns the corresponding short type. On line
#9, Boolean ’s parseBoolean method takes a String argument and returns the corresponding boolean type.The
value of i is set to 1 , max to 20 , s to 2 and b to true .
You can create an object of the wrapper class by simply supplying the value of the primitive type to
the constructor. The following listing shows createWrapperObjects method of Wrapper class that creates
objects of some of the wrapper classes:
Listing 9-11 Wrapper class – creating objects of wrapper classes
Project: wrapper-classes
Source location: src\wrapper\Wrapper.java
1 package wrapper;
2
3 public class Wrapper {
4 .....
5 private static void createWrapperObjects() {
6 Integer i = new Integer(1);
7 Short s = new Short((short)2);
8 Boolean b = new Boolean(true);
9 Character c = new Character('a');
10 .....
11 }
12 .....
13 }

On line #6, new Integer(1) creates an Integer object that holds the int value 1 . On line #7, new
Short((short)2) creates a Short object that holds the short value 2 . As an integer literal is considered to beof
type int , we have explicitly downcastedthe value 2 to short type.On line #8, new Boolean(true) creates
a Boolean object that holds the boolean value true . On line #9, new Character('a') creates a Character object
that holds the char value 'a'.
Java allows automatic conversion from the primitive type to the corresponding wrapper type and vice
versa. The automatic conversion from the primitive type to the corresponding wrapper type is
referred to as autoboxing. And, the automatic conversion from the wrapper type to the corresponding
primitive type is referred to as unboxing.
In the following listing, Wrapper ’s autoboxing method shows examples of autoboxing:
Listing 9-12 Wrapper class – autoboxing examples
Project: wrapper-classes
Source location: src\wrapper\Wrapper.java
1 package wrapper;
2
3 public class Wrapper {
4 .....
5 private static void autoboxing() {
6 Integer i = 1;
7 Short s = 2;
8 Boolean b = true;
9 Character c = 'a';
10 .....
11 }
12 .....
13 }

On line #6, integer literal 1 is assigned to an Integer type. On line #7, integer literal 2 is assigned to
a Short type. On line #8, boolean literal true is assigned to a Boolean type. On line #9, character literal 'a'
is assigned to a Character type. Notice that primitive types are automatically converted to their
corresponding object types.
In the following listing, Wrapper ’s unboxing method shows examples of unboxing:
Listing 9-13 Wrapper class – unboxing examples
Project: wrapper-classes
Source location: src\wrapper\Wrapper.java
1 package wrapper;
2
3 public class Wrapper {
4 .....
5 private static void unboxing() {
6 int i = new Integer(1);
7 short s = new Short((short)2);
8 boolean b = new Boolean(true);
9 char c = new Character('a');
10 .....
11 }
12 }

On line #6, an Integer type is assigned to an int type. On line #7, a Short type is assigned to a short type. On
line #8, a Boolean type is assigned to a boolean type. On line #9, a Character type is assigned to a char type.
Let’s look at an example in which wrapper classes are used.
The following listing shows the PrintObjects class whose print method prints the details of the object
passed as argument:
Listing 9-14 PrintObjects class – printing object details
Project: wrapper-classes
Source location: src\wrapper\PrintObjects.java
1 package wrapper;
2
3 public class PrintObjects {
4 public static void main(String args[]) {
5 print(new Rectangle(10, 20)); object
Rectangle
6 print(new Integer(10)); Integer object
7 print(new Boolean(true)); Boolean object
8 print(new Character('a')); Character object
9 print(null); null object
10 }
11
12 private static void print(Object object) {
13 if (object != null) {
14 System.out.println(object.getClass() + " " + object);
15 } else {
16 System.out.println("You passed null");
17 }
18 }
19 }

In theabove listing, the print method (line #12) accepts an Object argument and prints the class of the
object (obtained by calling Object ’s getClass method) along with its String representation.
PrintObjects ’s main method (line #4) calls the print method with different objects.As the print method
accepts an Object type argument, we can’t pass primitive type arguments to it. For this reason, we pass
objects of wrapper classes to the print method.
If you run the PrintObjects ’s main method, you’ll get the following output:
class wrapper.Rectangle Rectangle [length=10, breadth=20]
class java.lang.Integer 10
class java.lang.Boolean true
class java.lang.Character a
You passed null

The above output shows that the toString method of wrapper classes returns the value of the primitive
type they hold.
QUIZ
9-1: Consider the following SumNumbers class whose doSum method iterates over the numbers array and
fills the newNumbers array:
1 public class SumNumbers {
2 private int[] numbers = { 0, 2, 10, 40, 12, 13, 38, 12, 39, 28, 20 };
3 private int[] newNumbers;
4
5 public void doSum() {
6 newNumbers = new int[numbers.length / 2 + 1];
7 int j = 0;
8 for (int i = 0; i < numbers.length; i = i + 2) {
9 if (i + 1 < numbers.length) {
10 newNumbers[j] = numbers[i] + numbers[i + 1];
11 } else {
12 newNumbers[j] = numbers[i];
13 }
14 j++;
15 }
16 }
17 }

What is the content of newNumbers array after the execution of doSum method?
a) { 0, 2, 10, 40, 12, 13, 38, 12, 39, 28, 20 }

b) { 12, 65, 89, 48 }

c) { 2, 50, 25, 50, 67 }

d) { 2, 50, 25, 50, 67, 20 }

9-2: Consider the following Shape and Rectangle classes:


1 public abstract class Shape {
2 private int counter;
3
4 public void increment() {
5 counter++;
6 moreIncrement(); moreIncrement abstract method called
7 }
8
9 public int getCounter() {
10 return counter;
11 }
12
13 public abstract void moreIncrement(); moreIncrement abstract method
14 }
1 public class Rectangle extends Shape {
2
3 public void moreIncrement() {
4 increment(); increment abstract method called
5 }
6 }
What will be the output when the following main method is executed?
1 public static void main(String args[]) {
2 Shape shape = new Rectangle();
3 shape.increment();
4 System.out.println(shape.getCounter());
5 }
9-7 Summary
In this chapter, we saw how arrays are used to store multiple objects or primitive types. We also
looked at how you can use recursion to write some complex programs, like finding a number using
binary search or calculating factorial of a given number. This chapter sets the stage for you to write
more complex programs that require use of arrays and recursions.
Answers to quizzes
Chapter 1
Quiz 1-1
a) TRUE . Java programs are written in .java files
b) TRUE . You can use Eclipse IDE to write, run and debug Java programs.
c) TRUE . JDK contains the Java compiler which that checks if a program follows the Java
programming language rules
d) FALSE . Java is a platform-independent programming language. You can compile a Java
program on any platform (which includes hardware and operating system) and run it on any
other platform. For this reason, Java is often referred to as a language that provides ‘write
once, run anywhere’ capability.
Quiz 1-2
a) TRUE . JDK contains a private JRE that it uses for running Java programs. JRE contains
the JVM that reads bytecode from .class file, translates bytecode into platform-specific
instructions, and executes translated instructions.
b) TRUE . The JRE contained within JDK is private, and is not known to applications
installed on the system.
c) TRUE . You need JRE for running compiled Java programs. JDK is required for
compiling Java programs.
d) FALSE . JDK is required for compiling Java programs. JRE is required for running Java
programs.
e) FALSE . Java bytecode is compatible across different platforms.
f) TRUE . JVM translates bytecode into platform-specific instructions and executes them.
g) TRUE . You can use javac and java executables in JDK’s bin directory to compile and run
Java programs. For instance, you can compile HelloWorld.java using the following
command: javac HelloWorld.java , and run the compiled HelloWorld program using the following
command: java HelloWorld .
Chapter 2
Quiz 2-1
a) TRUE . A literal is a fixed or constant value.
b) FALSE . A variable name must begin with $ , _ or letter.
c) TRUE

d) FALSE . A narrowing conversion results in loss of information. On the other hand, a


widening conversion may result in loss of precision.
e) FALSE . By default, an integer literal is considered to be of type int .
f) TRUE .By default, a floating-point literal is considered to be of type float .

Quiz 2-2
a) 7someVariable - incorrect because it begins with a number
b) class – incorrect because class is a reserved word in Java
c) $someVariable – correct because a variable name can begin with a $
d) someVariable – correct
e) final – incorrect because final is a reserved word in Java
f) _someVariable – correct because a variable name can begin with an underscore
Quiz 2-3
1 package chapter02;
2
3 public class ConversionsTest {
4 public static void main(String args[]) {
5 byte temp = -127;
6 int age = 20;
7 char alphabet = 'a';
8 float mileage = 1.123456F;
9
10 alphabet = age;
11 age = mileage;
12 mileage = alphabet;
13 temp = alphabet;
14 }
15 }

Assignments on lines 10, 11 and 13 will result in compilation errors.


Line #10: converting from int type (4 bytes) to char (2 bytes) is a narrowing conversion.
Line #11: converting from float type (4 bytes) to int type (4 bytes) is a narrowing conversion.The int
type only representsinteger values, and the float type represents a floating-point value. In this
assignment, fractional part of the floating-point value is lost.
Line #13: converting from char type (2 bytes) to byte type (1 byte) is a narrowing conversion.
Quiz 2-4
int distance1 = 100;
int distance2 = 500;
int distance3 = 700;

The assignment distance2 = distance1 assigns value 100 to distance2 variable. The value of distance1 remains
unchanged to 100 .The assignment distance3 = distance2 assigns value of distance2 (which is now 100 )
to distance 3 variable. System.out.println prints the following messages on the console:
distance1 : 100
distance2 : 100
distance3 : 100

Quiz 2-5
x1 : false
x2 : true
x3 : false
x4 : true
x5 : true

x1 : (b % a) evaluates to 0 which is equal to 0 ; therefore (b % a) != 0 returns false .


x2 : (b / a) evaluates to 10 which is not equal to 0 ; therefore, (b / a) != 0 returns true .
x3 : As x1 is false and x2 is true , x1 && x2 returns false .
x4 : As x1 is false and x2 is true , x1 ||x2 returns true .
x5 : As isDone is false , !isDone returns true .

Quiz 2-6
x1 : 10
x2 : 100
x3 : false
x4 : true
x5 : false

x1 : As % has higher precedence than +, the expression b % a + 10 evaluates to 10


x2 : As / and * have the same precedence, the expression b / a * 10 evaluates to 10 * 10 (that is 100 )
x3 : As * , / and % have higher precedence compared to != and && operators in the expression b % a !=
10 &&b / a * 10 != 100 , the first round of evaluation results into the following expression:
0 != 10 && 100 != 100

As != has higher precedence than && , the expression becomes:


true && false

As the right operand is false , the expression evaluates to false .


x4 : As * , / and % have higher precedence compared to != , && and || operators in the expression b % a
!= 10 || true && b / a * 10 != 100 , the first round of evaluation results into the following expression:
0 != 10 || true && 100 != 100
As != has higher precedence compared to && and || , the expression evaluates to:
true || true && false
As && has higher precedence compared to || , the expression evaluates to:
true || false

As the left operand is true , the expression evaluates to true .


x5 : As expressions contained in parentheses take highest precedence, the first round of evaluation
results into the following expression:
(0 != 10 || true) && (100 != 100)

As != has higher precedence, the expression evaluates to:


(true || true) && (false)

Even though && has higher precedence than || , the expression (true || true) is evaluated first because it is
contained within parentheses:
(true) && (false)
As the right operand is false , the expression evaluates to false .
Chapter 3
Quiz 3-1
age : 2
infant
age + 2 : 4
age + 4 : 8

As the value of age variable is 2 , the condition age <= 2 evaluates to true . For this reason, if(age <=
2) statement block is executed. The age = age + 2; statement adds 2 to the age variable and assigns the
result back to age variable. This makes the value of age variable as 4 . After the if(age <=2) statement
block, age = age + 4; statement increments the value of age variable by 4 , making itsvalue as 8 .
Quiz 3-2
a is : 100

The expression a < b evaluates to false , which results in execution of statement b = b – a . As the value
of a is 100 and b is 10 , the value of b becomes -90 . The statement a – b >= 90 evaluates to evaluates to
true, which results in execution of System.out.println("a is : " + a) statement. As the value of a remains
unchanged, ‘ a is : 100 ’ is printed on the output.
Quiz 3-3
case 100:
case 200:
case default:

As the value of a is 100 , the switch statement transfers control to case 100: label. The System.out.println("case
100:") statement associated with case 100: label is executed. As no break statement is associated with case
100: label, the statement System.out.println("case 200:") in the following case 200: label is also executed. As
no break statement is associated with case 200: label, the statement System.out.println("case default:") in the
following case default: label is also executed.
Quiz 3-4
x + y = 11
x + y = 11
x + y = 11
x + y = 11
x + y = 11
x + y = 11
x + y = 11
x + y = 11
x + y = 11

The x + y = 11 is printed 9 times.


The following steps are followed in the execution of the while loop:
1. (iteration 1) When the program control reaches the while statement for the first time, the value
of x is 10 and y is 1 . The expression x > 0 && y < 10 evaluates to true , resulting in execution
of while statement block.The value of sum becomes 10 + 1 = 11 . The System.out.println("x + y = " +
sum); statement prints ‘x + y = 11’ because the value of sum is 11 .The statement x--; decrements
value of x by 1 to 9 , and y++; increments value of y by 1 to 2 .
2. (iteration 2) The control goes back to the while statement. The current value
of x and y are 9 and 2 ; therefore, the expression x > 0 && y < 10 evaluates to true . The while block
is executed and the value of x and y becomes 8 and 3 , respectively.At this time, the value
of sum becomes 8 + 3 = 11 . The System.out.println("x + y = " + sum); statement prints ‘x + y = 11’
because the value of sum is once again 11 .
The execution proceeds, until x > 0 && y < 10 evaluates to false .When the while loop is executed for
the 9th time, the value of x becomes 0 and y becomes 10 . So, when the control goes back to the while loop
again the expression x > 0 && y < 10 evaluates to false , resulting in termination of the while loop.
Quiz 3-5
i:0
i:1
i:2
i:3
i:4
i:5
i:6
i:7
i:8
i:9

Only values of i variable are printed on the output because the statement System.out.println("j : " + j) inside
the nested for loop is never reached. It is never reached because of the following reasons:
if j < 5 , continue statement is called, resulting in skipping the rest of the statements in the for
loop
if j >= 5 , break statement is called, resulting in termination of the nested for loop. Because of
this the System.out.println("j : " + j) statement is not called.
Chapter 4
Quiz 4-1
a) TRUE . An object has state (represented by attributes of the class) and behavior
(represented by methods of the class)
b) TRUE . You call a class’s constructor to create an object.
c) FALSE . An object’s state is represented by the attributes of the class
d) FALSE . An object’s behavior is represented by the methods of the class
Quiz 4-2
a) TRUE . The Airplane ’s constructor accepts the speed of the airplane as argument.
b) TRUE . The fly method represents behavior of the Airplane object.
c) FALSE .The return type of fly method is void .
d) TRUE .The speed and distanceCovered variables represent the state of an Airplane object.
e) FALSE . A constructor doesn’t return anything; therefore, it doesn’t specify a return type.
On the other hand, a method must alwaysspecify its return type. If a method doesn’t return
anything, even then void must be specified as the return type.
Quiz 4-3
The syntax for defining a method is:
public <return-type> <method-name>(<arg-type> <arg-name>, <arg-type> <arg-name>,
...) {
// the actions performed by the method go here
}
a) public void doSomething { ... } – This method definition is incorrect because it doesn’t specify
brackets ( ) in which method arguments are specified. Even if a method doesn’t accept any
argument, the brackets ( ) must be specified.
b) public doSomething() { … } – This method definition is incorrect because it doesn’t specify the
return type of the method.
c) public float doSomething { ... } – This method specifies the return type but doesn’t specify the
brackets ( ) in which method arguments are specified.
d) public void doSomething(float f) { ... } – This method definition is correct.The method accepts
a float argument and its return type is void .
Quiz 4-4
The syntax for defining a constructor is:
public <class-name> (<arg-type> <arg-name>, <arg-type> <arg-name>, .....) {
//- - do something
}
a) public void MyClass{ ... } – This constructor definition is incorrect because a constructor must
not specify a return type
b) public MyClass() { … } – This constructor definition is correct.
c) public float MyClass{ ... } – This constructor definition is incorrect because a constructor must
not specify a return type
d) public void MyClass(float f) { ... } – This constructor definition is incorrect because a constructor
must not specify a return type, which includes void .
Quiz 4-5
a) Airplane myAirplane = Airplane(100); - This is incorrect because the new keyword is required for
creating an object of a class.
b) Airplane myAirplane = new Airplane(); -
This is incorrect because the Airplane constructor is
defined to accept an argument of type int . So, you must pass an integer value to the Airplane
constructor.
c) Airplane myAirplane = new Airplane(100); - This is correct.This statement creates an Airplane object
whose speed attribute is set to 100 , and the newly created object is assigned to myAirplane
variable.
Quiz 4-6
The output from running the main method is:
airplane1's distanceCovered is: 1000.0
airplane2's distanceCovered is: 500.0

The following statement creates an Airplane object whose speed attribute value is set to 100 :
Airplane airplane1 = new Airplane(100);
The call to airplane1 ’s fly method executes the following statement:
distanceCovered = distanceCovered + speed*time;

This statement first evaluates the value of distanceCovered + speed*time expression and assigns it to
the distanceCovered attribute. At the time of execution of the above statement, value
of distanceCovered attribute is 0.0 , speed is 100.0 and time is 10 . This means, the expression evaluates
to 1000.0 . For this reason, airplane1 ’s distanceCovered attribute’s value is printed as 1000.0 .
In the case of airplane2 object, the same reasoning applies for printing 500.0 as the value of distanceCovered
attribute.
Quiz 4-7
a) TRUE . Instance and class variables are accessible to all the methods of the class.
b) TRUE . Local variables are defined inside methods and constructors.
c) FALSE . Local variables don’t have a default value; you must explicitly set their values or
the compiler with complain
d) TRUE . Instance variables are initialized to their default values if the constructor doesn’t
set their values
e) TRUE .Class variables are defined using static keyword
f) FALSE . Instance variables are private to an object; each object gets its own copy of
instance variables
g) FALSE . Class variables are not private to an object; they are shared between objects of
the class
h) TRUE . The default value ofa boolean type instance variable is false .
Quiz 4-8
a) Airplane airplane = new Airplane(); - this statement will not compile because the default no-
argument constructor becomes unavailable when you explicitly define one or more
constructors that accept arguments
b) Airplane airplane = new Airplane(100); - this statement is correct. Itcreates an Airplane object
whose speed is 100.0 and distanceCovered is 0.0 .
c) Airplane airplane = new Airplane(100, 10); - this statement is correct. It creates an Airplane object
whose speed is 100.0 and distanceCovered is 10.0 .
Quiz 4-9
The output from running the main method is:
Distance covered : 1000.0
Distance covered : 2000.0
Distance covered : 3000.0
The following statement creates a new Airplane object whose speed attribute is set
to 100.0 and distanceCovered attribute is set to 0.0 :
Airplane airplane = new Airplane(100);

The while loop then executes as long as airplane ’s canFly method returns true . The canFly method returns
true only if the value of distanceCovered attribute is <= 2000 . In each iteration of the while loop,
the airplane ’s fly method is called:
while(airplane.canFly()) {
airplane.fly(10);
System.out.println("Airplane can fly more. Distance covered: " + airplane.getDistanceCovered());
}

As the value of distanceCovered attribute is 0.0 when the Airplane object is created, the first call to fly
method updates the valueof distanceCovered attribute to 0.0 + 100.0 * 10 = 1000.0 .The while loop continues to
iterate till the value of distanceCovered attributebecomes > 2000 , in which case the canFly method
returns false and the while loop terminates.
Chapter 5
Quiz 5-1
a) TRUE . Packages are useful for organizing classes in the project.
b) TRUE . A package is represented by a folder structure in the file system.For
instance, com.sample.more package is represented by com/sample/more folder structure in the file
system.
c) FALSE . As you can’t have multiple files with the same name in a folder, you can’t define
multiple classes with the same name in a package.
d) TRUE . A class can use classes from other packages either by importing them using
the import statement or by using their fully-qualified names.
e) TRUE . A class can use classes from other packages either by importing them using
the import statement or by using their fully-qualified names.
Quiz 5-2
a) TRUE . A private method is accessible only within the class.
b) FALSE . A method with package-private access can only be called from the classes in the
same package
c) FALSE .A public method can be called from classes in the same or different packages.
d) FALSE .A class can’t be defined private .
e) TRUE . A constructor can be defined private . A private constructor is not accessible outside
the class.
Quiz 5-3
a) TRUE . A static method can be called without creating an object of the class. For this
reason, a static method is also referred to as a class method because it is associated with the
class and not with the object.
b) FALSE . A static method can be called without creating an object of the class. For this
reason, you can’t modify instance variables from a static method.
c) TRUE . You can modify static variables from non-static methods.
d) FALSE . A non-static method can only be invoked on an object. For this reason, a static
method can’t call a non-static method.
e) TRUE . A non-static method can call a static method.
f) FALSE . A constructor can’t be defined as static.
Quiz 5-4
a) TRUE . The this keyword refers to the current object.
b) TRUE . The this keyword is used by non-static methods and constructors to access
instance variables of the class.
c) FALSE .The static methods can’t use the this keyword because they may be called without
creating an object of the class.
d) TRUE . A constructor can use the this keyword to call another constructor of the current
object.
e) FALSE .The this keyword can’t be used inside a static method.
Quiz 5-5
The output from running the main method is:
Distance covered: 100.0
Current speed: 0.0
Max speed: 50.0

The value of currentSpeed attribute is printed as 0.0 becausethe currentSpeed constructor argument
hidesthe currentSpeed attribute. The assignment currentSpeed = currentSpeed incorrectly assigns value
of currentSpeed constructor argument to itself.Ideally, it should have been specified as this.currentSpeed =
currentSpeed , as shown here:
public Airplane(int currentSpeed, float distanceCovered, float maxSpeed) {
this.currentSpeed = currentSpeed;
this.distanceCovered = distanceCovered;
Airplane.maxSpeed = maxSpeed;
}
Thevalue of distanceCovered attribute is printed as 100.0 because this.distanceCovered = distanceCovered statement
assigns value of distanceCovered constructor argument to distanceCovered attribute.
As the maxSpeed is a static attribute, we can refer to it either by using the this keyword or by using the
class name. This means, the following two statements are equivalent:
this.maxSpeed = maxSpeed;
Airplane.maxSpeed = maxSpeed;

Quiz 5-6
a) FALSE . Java objects are stored in the heap memory area of computer.
b) FALSE . Local variables are stored in the stack memory area of computer.
c) TRUE . A reference type variable holds memory address of the object.
d) FALSE . When you pass a reference type to a method (or constructor), a copy of the
memory address of the object is passed to the called method (or constructor).
e) TRUE . When you pass a primitive type to a method (or constructor), a copy of the
primitive type’s value is passed to the called method (or constructor).
Chapter 6
Quiz 6-1
a) TRUE . Encapsulation means that the attributes and the methods that operateon those
attributes are defined in the same class. The attributes must be defined private and methods
must be defined public .
b) TRUE . Encapsulation is referred to as data hiding because private attributes are not
directly accessible to other objects. The only way to access the attributes is through the
methods defined by the class.
c) FALSE . The attributes must be defined as private by a fully-encapsulated class.
d) FALSE . The methods that operateon attributes must be defined as public by a fully-
encapsulated class.
Quiz 6-2
The output from running the main method is:
rectangle's name : Rectangle
anotherRectangle's name : null

The following statement of the main method creates a Rectangle object using Rectangle ’s no-argument
constructor:
Rectangle rectangle = new Rectangle();

Rectangle ’s constructor calls Shape ’s constructor that accepts a String argument:


public Rectangle() {
super("Rectangle");
}
Shape ’s constructor sets the value of name instance variable to "Rectangle":
public class Shape {
private String name;
.....
public Shape(String name) {
this.name = name;
}
.....
}

So, when you call getName method on rectangle , it returns "Rectangle".


The following statement of the main method creates a Rectangle object using Rectangle ’s constructor that
accepts a String argument:
Rectangle anotherRectangle = new Rectangle("A rectangle");

Rectangle ’s constructor calls Shape ’s no-argument constructor:


public Rectangle(String name) {
super();
}

Shape ’s no-argument constructor doesn’t do anything:


public class Shape {
private String name;
.....
public Shape() {
}
.....
}
This means, the value of name variable is initialized to null .For this reason,
calling anotherRectangle ’s getName method returns null .
Quiz 6-3
a) TRUE . Shape ’s name instance variable is defined as protected ; therefore, it is inherited by
the Rectangle subclass. The statement super.name = name assigns the value of name argument
to Shape ’s name instance variable.
b) FALSE .As Rectangle ’s constructor doesn’t explicitly call Shape ’s constructor, the default no-
argument constructor of Shape class is called.
c) TRUE .As Shape ’s name instance variable is inherited by
the Rectangle class, Rectangle ’s getName method returns the inherited name instance variable.
d) FALSE . Shape ’s getName method is defined public and Rectangle ’s getName method is
defined protected . As a public method can’t be overriddenby a protected method, this will result
in compilation error.
Quiz 6-4
The method that overrides String getSomething() method must have the same signature and must not make
the method more restrictive.This means, the overriding method must be defined public , protected or with
package-private access.
a) String getSomething(String str) { ..... } – As this method accepts a String argument, its signature is
differentfrom String getSomething() method.
b) private String getSomething() { ..... } – As this methodis defined private , it is more restrictive.
c) protected String getSomething() { ..... } – As this method is defined protected , it is less restrictive
than a method with package-private access. This method overrides the String getSomething()
method.
d) public String getSomething() { ..... } – As this method is defined public , it is less restrictive than a
method with package-private access. This method overrides the String getSomething() method.
e) void getSomething() { ..... } – As this method returns void , its signature is different from String
getSomething() method.
Quiz 6-5
a) rectangle = shape; - This statement won’t compile because you must explicitlydowncast
a Shape object to a Rectangle type variable.
b) shape = rectangle; - This statement will compile successfully because we are assigning a
subtype object (that is, Rectangle ) to a supertype (that is, Shape ) variable.
c) rectangle = (Rectangle)shape; - This statement will compile successfully because we are
performing explicit downcast of a supertype object (that is, Shape ) to a subtype variable (that
is, Rectangle ).
d) shape = (Shape)rectangle; - This statement will compile successfully because we are assigning
a subtype object (that is, Rectangle ) to a supertype (that is, Shape ) variable. The explicit
upcasting to Shape is not required because the assignment performs upcasting.
Quiz 6-6
a) FALSE . As shape_1 holds reference to a Rectangle object at runtime, calling
shape_1.draw() method invokes Rectangle ’s draw method. This means, "Drawing a rectangle" is
printed.
b) FALSE . As rectangle holds reference to a Rectangle object at runtime, calling
rectangle.draw() method invokes Rectangle ’s draw method. This means, "Drawing a rectangle" is
printed.
c) FALSE .As circle holds reference to a Circle object at runtime, calling circle.draw() method
invokes Circle ’s draw method. This means, "Drawing a circle" is printed.
d) FALSE . As getCounter is a staticmethod, it is invoked on the declared type of
the shape_1 variable. As shape_1 variable is of type Shape , getCounter method of Shape class is
invoked. Shape ’s getCounter method printsthe value of shapeObjectsCounter static variable.
The shapeObjectsCounter variable is incremented each time Shape ’s constructor is called.As we
have created two Rectangle objects and one Circle object, the value of shapeObjectsCounter is 3 .For
this reason, the shape_1.getCounter() method call prints 3 .
e) TRUE . As getCounter is a staticmethod, it is invoked on the declared type of
the rectangle variable. As rectangle variable is of type Rectangle , getCounter method of Rectangle class
is invoked. Rectangle ’s getCounter method printsthe value of rectangleObjectsCounter static variable.
The rectangleObjectsCounter variable is incremented each time Rectangle ’s constructor is called. As
we have created two Rectangle objects, the value of rectangleObjectsCounter is 2 . For this reason,
the rectangle.getCounter() method call prints 2 .
f) TRUE .As getCounter is a staticmethod, it is invoked on the declared type of
the circle variable. As circle variable is of type Circle , getCounter method of Circle class is
invoked. Circle ’s getCounter method printsthe value of circleObjectsCounter static variable.
The circleObjectsCounter variable is incremented each time Circle ’s constructor is called. As we
have created one Circle object, the value of circleObjectsCounter is 1 . For this reason,
the circle.getCounter method prints 1 .
Quiz 6-7
a) As only the return types of the methods differ, the method combination doesn’t qualify as
an example of method overloading.
b) As only the return types of the methods differ, the method combination doesn’t qualify as
an example of method overloading.
c) As only the argument names of the methods differ, the method combination doesn’t qualify
as an example of method overloading.
d) As the argument types of methods differ, the method combination qualifies as an example
of method overloading.
e) As the argument types of methods differ, the method combination qualifies as an example
of method overloading.
Quiz 6-8
As both str_1 and str_2 variables are initialized to the same String literal "xyz", both the variables point
to the same String object in the String literal pool.For this reason, str_1 == str_2 expression evaluates to
true and the program prints "same".
Quiz 6-9
a) FALSE . Object ’s hashCode method returns an integer value that remains unchanged only
during the execution of the program. The value may change if the program is executed again.
b) TRUE .

c) TRUE .By default, Object ’s equals method compares memory addresses of the objects.This
means, equals method returns true only if two objects are referring to the same object in
memory.
d) TRUE .
Chapter 7
Quiz 7-1
a) FALSE . An abstract class can define one or more concrete methods.
b) TRUE . An abstract class can extend from another concrete or abstract class.
c) FALSE . An abstract class can define one or more constructors. An abstract class’s
constructor is called when the constructor of its concrete subclass is called.
d) TRUE . You can’t create an object of an abstract class. An attempt to do so will result in
compilation error.
e) FALSE . It is not mandatory for an abstract class to define an abstract method.
f) TRUE . An abstract class can define static attributes and methods.
Quiz 7-2
The output from executing the main method is : 6
Shape ’s increment method does the following two things:
1. it increments the counter variableby 1 , and
2. calls the moreIncrement abstract method
As the counter variable is defined as protected and increment method is defined as public , they areinherited
by the Rectangle subclass. Rectangle class implements the moreIncrement method such that itincrements
the counter variable by 2 .
As Rectangle class is a subclass of Shape class, the following assignment is correct:
Shape shape = new Rectangle();

When the increment method is called on the shape variable for the first time, it increments
the counter variable by 1 and calls the moreIncrement method. As the moreIncrement method increments the
value of counter variable by 2 , the value of counter variable is incremented to 3 . When
the increment method is called again, the value of counter variable is incremented to 6 (3 + 1 + 2 = 6) .
Quiz 7-3
a) FALSE . An interface can only define abstract methods.
b) TRUE . A class can implement multiple interfaces.
c) TRUE . An interface can inherit from multiple interfaces.
d) FALSE . An interface can’t have constructors. An abstract class can have one or more
constructors.
Quiz 7-4
a) FALSE . As Rectangle class is a subclass of Shape , it means that Rectangle is a subtypeof Shape .
For this reason, youcan pass an object of Rectangle to a method that accepts a Shape type
argument.
b) FALSE .As Rectangle class implements Drawable interface, it means that Rectangle is a
subtypeof Drawable .For this reason, you can pass an object of Rectangle to a method that accepts
a Drawable type argument.
c) FALSE . RedRectangle is a subclass of Rectangle , which in turn is a subclass of Shape . This
means, RedRectangle is a subtype of both Rectangle and Shape . For this reason, you can pass an
object of RedRectangle to a method that accepts a Shape or Rectangle type argument.
d) FALSE . RedRectangle is a subclass of Rectangle , which inherits from Shape class and
implements the Drawable interface. This means, RedRectangle indirectly implements the Drawable
interface. For this reason, you can pass an object of RedRectangle to a method that accepts
a Drawable type argument.
e) FALSE . As you can assign a subtype object to a supertype variable, you canassign an
object of Rectangle (the subtype) to a Shape (the supertype) type variable.
f) FALSE .As RedRectangle indirectly implements Drawable interface, RedRectangle is a subtype
of Drawable . As you can assign a subtype object to a supertype variable, you canassign an
object of RedRectangle (the subtype) to a Drawable (the supertype) type variable.
Quiz 7-5
a) TRUE . A final class cannot be subclassed.
b) FALSE . A final method can be overloaded by can’t be overridden.
c) TRUE . A final primitive type variable’s value can’t be changed.
d) FALSE .If a reference type variable is declared as final , it means that you can’t make the
variable refer to any other object in memory. But, you can always modify the referenced
object.
e) FALSE .You can’t define a constructor as final .
Quiz 7-6
a) TRUE . The static initializer blocks are used for initializing static variables.
b) TRUE . The instance initializer blocks are used for initializing instance variables.
c) FALSE . A constructor can’t be used instead of a static initializer block because a static
initializer block is executed when the class is loaded by the JVM.
d) FALSE . The static variables of a class are initialized when the class is loaded by the
JVM, and an instance initializer block is executed when an object of the class is executed.
For this reason, you can use an instance initializer block to initialize static variables.
Chapter 8
Quiz 8-1
a) TRUE . An unchecked exception represents a programming error.
b) TRUE . A checked exception represents a recoverable exception.
c) FALSE .The java.lang.RuntimeException class and its subclasses represent unchecked exceptions.
d) FALSE . The java.lang.Exception class and its subclasses (excluding java.lang.RuntimeException class
and its subclasses) represent checked exceptions.
e) TRUE .The java.lang.Error class and its subclasses represent serious problem with the
application from which a program can’t recover.
Quiz 8-2
The output from executing the main method is : 50 .
This is how the calculate method sets the value of memory variable to 50 :
On line #5, the value of i (the argument passed to the calculate method) is assigned to
the memory variable. As the value of i is 5 , the value of memory variable is set to 5 .
On line #6, memory = memory + 10; statement sets memory variable’s value to 15 .
On line #8, memory variable’s value is divided by 0 , which results in ArithmeticException .
The catch block catches the ArithmeticException and memory = memory + 10; statement
sets memory variable’s value to 25 .
On line #11, the memory variable’s valueis divided by 0 , which results in ArithmeticException .
The finally block is executed that multiplies the value of memory variable by 2 . The value
of memory variable becomes 50 .
On line #14, memory variable’s value is divided by 0 , which results in ArithmeticException . The
control is now returned to the main method.
The main method calls Calculator ’s getMemory method that returns the value of memory variable. As
the value of memory variable is 50 , the value 50 is returned to the main method.
Quiz 8-3
The correct answer is (d). As RuntimeException is a more generic exception than ClassCastException , the
catch block corresponding to ClassCastException is not reachable.

Quiz 8-4
The output from executing MyClass ’s doSomething method is:
"executing finally block"
A catch block catches all exceptions of the specified exception type and its subtypes. This means,
the catch block corresponding to MyException (refer line #6of MyClass ) catches exceptions that are
of MyException type and its subtypes. The doSomething method throws ClassCastException when Object type is
downcasted to String (refer line #5 of MyClass ). As ClassCastException is nota subtype of MyException , the
exception is not caught by the catch block. For this reason, only thestatements inside the finally block
are executed.
Quiz 8-5
a) FALSE . The class will compile successfully because the catch block can be used to catch
any exception that is of type java.lang.Throwable or its subtype.
b) FALSE . As java.lang.ArithmeticException is a subtype of java.lang.Throwable , the ArithmeticException is
caught by the catch block.
Even though you can catch exceptions by specifying java.lang.Throwable in the catch block, it is not
recommended. As java.lang.Error (a subclass of java.lang.Throwable ) and its subclasses represent serious
problem with the program and should not be caught, specifying java.lang.Throwable will catch these
errors also.
Chapter 9
Quiz 9-1
The correct answer is (d) - { 2, 50, 25, 50, 67, 20} .The doSum method iterates over the numbers array and
sums two consecutive numbers in the array.Let’s look at how the doSum method works.
1 public class SumNumbers {
2 private int[] numbers = { 0, 2, 10, 40, 12, 13, 38, 12, 39, 28, 20 };
3 private int[] newNumbers;
4
5 public void doSum() {
6 newNumbers = new int[numbers.length / 2 + 1];
7 int j = 0;
8 for (int i = 0; i < numbers.length; i = i + 2) {
9 if (i + 1 < numbers.length) { this will evaluate to false when
10 newNumbers[j] = numbers[i] + numbers[i + 1];
11 } else {
12 newNumbers[j] = numbers[i];
13 }
14 j++;
15 }
16 }
17 }

On line #6, the newNumbers array is created with size (number.length/2 + 1) . As the size of numbers array
is 11 , the newNumbers array is created with size (11/2 + 1) = (5 + 1)= 6 . The + 1 is done forcalculating the
size for newNumbers array to address situations in which the numbers array’s size is odd. On line #8,
the for loop iterates over the numbers array. As we want to calculate sum of 2 consecutive numbers in the
array, the value of loop variable i is incrementedby 2 after each iteration. If the size of the numbers
array is odd, the last number in the array will be left out. To address such a scenario, the if–else
statement has been used to ensure that the last number in the numbers array is added to the newNumbers
array.
Quiz 9-2
When the main method is executed, java.lang.StackOverflowError is thrown.
Shape ’s increment method calls the moreIncrement abstract method (refer line #6 of Shape class).
And, Rectangle ’s moreIncrement method calls Shape ’s increment (refer line #4 of Rectangle class). As increment
and moreIncrement methods continue to call each other, the stack memory area of the computer memory is
filled, resulting in java.lang.StackOverflowError .
INDEX

A
Abstract classes, 203
no abstract methods, 209
static variables and methods, 210
upcasting, 209
abstract methods, 203
Access modifiers, 138
Arrays
accessing elements, 266
creating and initializing, 263
multi-dimensional, 269
passing and returning, 267

B
Binary numbers, 48
Branching statements, 89
break, 89
continue, 90
break statement, 71

C
Catching exceptions
finally block, 252
try-catch block, 244
checked exception, 236
class types
default value, 114
class variables, 109
constructor
default, 117
syntax, 99
Constructor overloading, 188
constructors
multiple, 115
continue statement
flowchart, 91
Custom exception types, 254

D
do-while
flowchart, 84
Downcasting, 177

E
Eclipse IDE, 11
configuration, 16
create Java class, 20
create Java project, 18
create package, 131
importing projects, 26
installing, 11
Package Explorer, 15
Problems, 15
Run Configurations, 63
Terminate option, 81
Encapsulation, 160
Exception classes, 235
Exception handling, 239
Exception propagation, 239
extends keyword, 162

F
final arguments, 227
final classes, 224
final keyword, 224
constants, 226
final methods, 224
final variables, 225
float
F (or f) suffix, 33, 36
for loop
flowchart, 87
nested, 88

I
if statement, 57
flowchart, 60
nested, 59
if statements
multiple, 59
if-else statement, 66
flowchart, 67
implements keyword, 213
import statement, 135
Inheritance, 161
is-a relationship, 179
multi-level, 179
instance initialization block
alternatives, 230
instance initializer blocks, 227
instance method, 143, 144
instance variable, 109
instance variables
hiding, 187
instanceof operator, 218
Interfaces, 211
inheritance, 217
multiple inheritance, 214
Interfaces vs abstract classes, 217

J
jar, 26
java, 26
Java
data types, 30
expressions, 41
literals, 32
operators, 40
platform-independent, 24
statements, 41
variables, 30
Java attributes
default values, 112
initial value, 108
Java bytecode, 24, 25
Java class, 21, 97
.java extension, 21
attributes, 97, 108
behaviors, 97
constructor, 98
constructors, 115
main method, 22
methods, 99, 120
Java compiler, 24
compilation errors, 34
Java control flow statements, 56
conditional, 57
if, 57
types, 56
Java declaration statements, 56
Java expression statements, 56
Java expressions
intermediate expression types, 52
Java method, 22
Java object
creation, 100
Java operators
arithmetic, 42
assignment, 47
bitwise, 48
conditional, 46
precedence, 51
relational, 44
Java package, 20
classes with same name, 137
Java packages, 131
creating, 131
organization classes, 134
Java program, 22
Java project
structure, 24
Java Runtime Environment, 25
Java variable
assigning value, 31
defining, 30
naming convention, 30
Java Virtual Machine, 25
java.lang.ArithmeticException, 238
java.lang.ClassCastException, 238
java.lang.Exception, 236
java.lang.NullPointerException, 235, 236
java.lang.Object, 189
equals, 190, 192
getClass, 190
hashCode, 190
toString, 190, 196
java.lang.OutOfMemoryError, 236
java.lang.Throwable, 235
javac, 26
javadoc, 26
JDK, 11, 26
installing, 11
java -version, 13
update number, 12
JRE, 12, 26
JVM
responsibility, 25

L
local variables, 109
default values, 114
long
(L of l) suffix, 35
L (or l) suffix, 33
looping statements
do-while, 82
for, 85
infinite loops, 92
while, 77
Looping statements, 76

M
main method
pass values at execution time, 62
terminate, 81
method
multiple return statements, 123
return statement, 122
syntax, 99
Method
calling, 102
Method overloading, 188
Method overriding, 172
restrictions, 174
multi-line comments, 37

N
narrowing conversion, 35, 36
examples, 39
new keyword, 101

O
Object
behavior, 96
state, 96
Operator precedence
parentheses, 53

P
Pass by value, 152
Polymorphism, 183
primitive type variables, 31
primitive types
default value, 114
range, 31
storage size, 33

R
Recursion, 272
calculating factorial, 272
finding a number using binary search, 274
reference to an object, 154

S
single-line comments, 37
static initialization block
alternatives, 230
static initializer blocks, 227
static methods, 143
hiding, 188
restrictions, 146
static modifier, 142
static variables, 143
hiding, 188
String object
immutability, 271
String type, 98
super keyword, 171
switch statement, 70
default label, 73
duplicate case labels, 72
flowchart, 71
multiple case satatements for same set of statements, 75
without break statement, 72
System.out.println, 22

T
this keyword, 147
try-catch block
catching exceptions related by inheritance, 251
catching multiple exceptions, 250
type conversion, 35
compatibility, 40

U
unchecked exception, 236
Upcasting, 177
method return type, 179

W
while loop
flowchart, 79
widening conversion
examples, 38
Wrapper classes, 279
autoboxing, 281
unboxing, 281

Вам также может понравиться