Object Oriented Programming
Object Oriented Programming
Institute of Technology
School of Electrical and Computer engineering
For 3st year
Object Oriented Programming (ECEg-3091)
Chapter One
Introduction
Programming Paradigms
A programming paradigm is a model of programming based on distinct concepts that shapes the
way programmers design, organize and write programs. A programming paradigm is a style or
way of programming. Features of various programming languages determine which programming
paradigms they belong to; as a result, some languages fall into only one paradigm, while others
fall into multiple paradigms. Some paradigms are concerned primarily with the way that code is
organized, such as grouping code into units along with the state that is modified by the code. Yet
others are concerned primarily with the style of syntax and grammar.
Why does a programming paradigm matter? Program size keeps growing quickly leading to more
complexity. The following table shows some software with their lines of code.
Software Size in lines of code Year
Windows 2000 29 million 2000
Windows XP 45 million 2001
Windows 7 40 million 2009
Android 12 million
Debian 5.0 324 million 2009
Debian 7.0 419 million 2012
Google Chrome 5 million
Firefox 10 million
Choosing a good paradigm that helps manage the complexity of programs is very important.
1. Unstructured Programming
Usually, people start learning programming by writing small and simple programs consisting only
of one main program. Here main program stands for a sequence of commands or statements which
modify data which is global throughout the whole program.
2
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
Structured programming is a programming paradigm aimed at improving the clarity, quality, and
development time of a computer program by making extensive use of subroutines, block structures,
for and while loops. This is in contrast to unstructured which uses simple tests and jumps such as
the goto statement which could lead to "spaghetti code" causing difficulty to both follow and
maintain.
Unstructured programming technique provides tremendous disadvantages once the program gets
sufficiently large. For example, if the same statement sequence is needed at different locations
within the program, the sequence must be copied. This increases the code size and becomes
unmanageable if the program is big. This has led to the idea to extract these sequences, name them
and offering a technique to call and return from these procedures. Making the data global also has
the adverse effect of getting unwanted changes inadvertently.
3
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
2. Procedural Programming
In procedural programming, the program is built from one or more procedures (also called
subroutines or functions). With procedural programming you are able to combine returning
sequences of statements into one single place. A procedure call is used to invoke the procedure.
After the sequence is processed, flow of control proceeds right after the position where the call
was made.
With introducing parameters as well as procedures, programs can now be written more structured
and error free. For example, if a procedure is correct, every time it is used it produces correct
results. Consequently, in case of errors you can narrow your search to those places which are not
proven to be correct.
Now a program can be viewed as a sequence of procedure calls. The main program is responsible
to pass data to the individual calls, the data is processed by the procedures and once the program
has finished, the resulting data is presented. Thus, the flow of data can be illustrated as a
hierarchical graph, a tree, as shown in the figure.
Generally, we have a single program which is divided into small pieces called procedures. To
enable usage of general procedures or groups of procedures also in other programs, they must be
4
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
separately available. For that reason, modular programming allows grouping of procedures into
modules.
Procedural programming offers many benefits over simple sequential programming since
procedural code is:
• easier to read and more maintainable
• allows reuse of procedures
• more flexible
• facilitates the practice of good program design
3. Modular Programming
With modular programming procedures of a common functionality are grouped together into
separate modules. A program therefore no longer consists of only one single part. It is now divided
into several smaller parts which interact through procedure calls and which form the whole
program.
Main program coordinates calls to procedures in separate modules and hands over appropriate
data as parameters.
Each module can have its own data. This allows each module to manage an internal state which is
modified by calls to procedures of this module. However, there is only one state per module and
each module exists at most once in the whole program.
5
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
4. Logic Programming
Logic programming is a programming paradigm based on formal logic. A program written in a
logic programming language is a set of sentences in logical form, expressing facts and rules about
the problem domain. Major logic programming language families include Prolog, Answer set
programming (ASP) and Datalog.
The rules of inference are applied for deriving the goal statement from the axioms and the
execution of a logic program corresponds to the construction of a proof of the goal statement from
the axioms.
OOP Concepts
1. Encapsulation
Encapsulation is the mechanism that binds together code and the data it manipulates, and keeps
both safe from outside interference and misuse. One way to think about encapsulation is as a
protective wrapper that prevents the code and data from being arbitrarily accessed by other code
6
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
defined outside the wrapper. Access to the code and data inside the wrapper is tightly controlled
through a well-defined interface.
Encapsulation is the principle of data hiding. It is the process of hiding the data structures of the
class and allowing changes in the data through a public interface where the incoming values are
checked for validity, and so not only it permits the hiding of data in an object but also of behavior.
This prevents clients of an interface from depending on those parts of the implementation that are
likely to change in future, thereby allowing those changes to be made more easily, that is, without
changes to clients.
The power of encapsulated code is that everyone knows how to access it and thus can use it
regardless of the implementation details—and without fear of unexpected side effects.
In Java/C++ the basis of encapsulation is the class. A class defines the structure and behavior (data
and code) that will be shared by a set of objects. Each object of a given class contains the structure
and behavior defined by the class, as if it were stamped out by a mold in the shape of the class.
For this reason, objects are sometimes referred to as instances of a class. Thus, a class is a logical
construct; an object has physical reality.
When you create a class, you will specify the code and data that constitute that class. Collectively,
these elements are called members of the class. Specifically, the data defined by the class are
referred to as member variables or instance variables. The code that operates on that data is
referred to as member methods or just methods. In properly written Java programs, the methods
define how the member variables can be used. This means that the behavior and interface of a class
are defined by the methods that operate on its instance data.
2. Data Hiding
It just provides a way to protect your data from the outside world. What it means is, let’s say if I
made my instance variable public, then anyone can change its state. But if we make our instance
variable private/protected then actually we are restricting outside entities from making changes to
it.
3. Abstraction
An abstraction separates interface from implementation. Abstraction hides implementation details
from the outside world. Through the process of abstraction, a programmer hides all but the relevant
data about an object in order to reduce complexity and increase efficiency.
4. Inheritance
Inheritance is the process by which one object acquires the properties of another object. This is
important because it supports the concept of hierarchical classification. For example, a Golden
7
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
Retriever is part of the classification dog, which in turn is part of the mammal class, which is under
the larger class animal. Without the use of hierarchies, each object would need to define all of its
characteristics explicitly.
However, by use of inheritance, an object need only define those qualities that make it unique
within its class. It can inherit its general attributes from its parent. Thus, it is the inheritance
mechanism that makes it possible for one object to be a specific instance of a more general case.
Inheritance describes a relationship between two or more types of objects in which one inherits
features of the parent, allowing for shared functionality. This lets programmers re-use or reduce
code and simplifies the development and maintenance of software.
Inheritance is a form of software reusability in which new classes are created from existing classes
by absorbing their attributes and behaviors and adding new capabilities the new classes require.
Software reusability saves time in program development. It encourages reuse of proven and
debugged high-quality software, thus reducing problems after a system becomes operational.
These are exciting possibilities.
Most people naturally view the world as made up of objects that are related to each other in a
hierarchical way, such as animals, mammals, and dogs. If you wanted to describe animals in an
abstract way, you would say they have some attributes, such as size, intelligence, and type of
skeletal system. Animals also have certain behavioral aspects; they eat, breathe, and sleep. This
description of attributes and behavior is the class definition for animals.
If you wanted to describe a more specific class of animals, such as mammals, they would have
more specific attributes, such as type of teeth, and mammary glands. This is known as a subclass
of animals, where animals are referred to as mammals’ superclass. Since mammals are simply
more precisely specified animals, they inherit all of the attributes from animals. A deeply inherited
subclass inherits all of the attributes from each of its ancestors in the class hierarchy.
8
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
Fig inheritance
Inheritance interacts with encapsulation as well. If a given class encapsulates some attributes, then
any subclass will have the same attributes plus any that it adds as part of its specialization. This is
a key concept which lets object-oriented programs grow in complexity linearly rather than
geometrically. A new subclass inherits all of the attributes of all of its ancestors. It does not have
unpredictable interactions with the majority of the rest of the code in the system.
5. Polymorphism
Polymorphism (from Greek, poly “many” and morph “form”, combined together “many forms”)
is a feature that allows one interface to be used for a set of actions.
The specific action is determined by the exact nature of the situation. Consider a stack (which is a
last-in, first-out list). You might have a program that requires three types of stacks. One stack is
used for integer values, one for floating-point values, and one for characters. The algorithm that
implements each stack is the same, even though the data being stored differs. In a non–object-
oriented language, you would be required to create three different sets of stack routines, with each
set using different names. However, because of polymorphism, in Java you can specify a general
set of stack routines that all share the same names.
More generally, the concept of polymorphism is often expressed by the phrase “one interface,
multiple methods.” This means that it is possible to design a generic interface to a group of related
activities. This helps reduce complexity by allowing the same interface to be used to specify a
9
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
general class of action. It is the compiler’s job to select the specific action (that is, method) as it
applies to each situation. You, the programmer, do not need to make this selection manually. You
need only remember and utilize the general interface.
10
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
In the Java programming language, all source code is first written in plain text files ending with
the .java extension. Those source files are then compiled into .class files by the javac compiler.
A .class file does not contain code that is native to your processor; it instead contains bytecodes —
the machine language of the Java Virtual Machine (Java VM). The java launcher tool then runs
your application with an instance of the Java Virtual Machine.
Because the Java VM is available on many different operating systems, the same .class files are
capable of running on Microsoft Windows, the Solaris Operating System (Solaris OS), Linux, or
Mac OS. Some virtual machines, such as the Java HotSpot virtual machine, perform additional
steps at runtime to give your application a performance boost. This includes various tasks such as
finding performance bottlenecks and recompiling (to native code) frequently used sections of code.
11
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
Characteristics of Java
The Java programming language is a high-level language that can be characterized by all of the
following buzzwords:
• Object oriented
• Distributed
• Multithreaded
• Dynamic
• Architecture neutral/portable
• High performance
• Robust
• Secure
Architecture-Neutral/Portable
A central issue for the Java designers was that of code longevity and portability. One of the main
problems facing programmers is that no guarantee exists that if you write a program today, it will
run tomorrow—even on the same machine. Operating system upgrades, processor upgrades, and
changes in core system resources can all combine to make a program malfunction. The Java
designers made several hard decisions in the Java language and the Java Virtual Machine in an
attempt to alter this situation. Their goal was “write once; run anywhere, anytime, forever”. This
is called WORA(Write Once, Run anywhere).To a great extent, this goal was accomplished.
12
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
Object-Oriented
Object-oriented programming is at the core of Java. In fact, all Java programs are object-oriented—
this isn’t an option the way that it is in C++, for example. OOP is so integral to Java that you must
understand its basic principles before you can write even simple Java programs.
As explained earlier, while it is true that Java was engineered for interpretation, the Java bytecode
was carefully designed so that it would be easy to translate directly into native machine code for
very high performance by using a just-in-time compiler. Java run-time systems that provide this
feature lose none of the benefits of the platform-independent code. “High-performance cross-
platform” is achieved in Java.
Distributed
Java is designed for the distributed environment of the Internet, because it handles TCP/IP
protocols. In fact, accessing a resource using a URL is not much different from accessing a file.
The original version of Java included features for intra-address-space messaging. This allowed
objects on two different computers to execute procedures remotely. Java revived these interfaces
in a package called Remote Method Invocation (RMI). This feature brings an unparalleled level of
abstraction to client/server programming.
Multithreaded
Java supports multithreaded programming, which allows you to write programs that do many
things simultaneously. The Java run-time system comes with an elegant yet sophisticated solution
for multiprocess synchronization that enables you to construct smoothly running interactive
systems. Java’s easy-to-use approach to multithreading allows you to think about the specific
behavior of your program, not the multitasking subsystem.
Dynamic
Java programs carry with them substantial amounts of run-time type information that is used to
verify and resolve accesses to objects at run time. This makes it possible to dynamically link code
in a safe and expedient manner. This is crucial to the robustness of the applet environment, in
which small fragments of bytecode may be dynamically updated on a running system.
13
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
Dynamic programming languages are languages which, at runtime, execute many common
programming behaviors that static programming languages perform during compilation. These
behaviors could include extension of the program, by adding new code, by extending objects and
definitions, or by modifying the type system.
A platform is the hardware or software environment in which a program runs. Some of the most
popular platforms are Microsoft Windows, Linux, Solaris OS, and Mac OS. Most platforms can
be described as a combination of the operating system and underlying hardware. The Java platform
differs from most other platforms in that it's a software-only platform that runs on top of other
hardware-based platforms.
Java Virtual Machine is the base for the Java platform and is ported onto various hardware-based
platforms. The JVM executes Java bytecode. When you compile Java code, you produce bytecode
which is an intermediate representation. Bytecode is not directly executable because it is not
machine code. It is possible to compile code written in other languages into Java bytecode.
The Java Application Program Interface (Java API) is a large collection of ready-made software
components that provide many useful capabilities. It is grouped into libraries of related classes and
interfaces; these libraries are known as packages.
The Java Class Library (JCL) is a set of dynamically loadable libraries that Java applications
can call at run time. Because the Java Platform is not dependent on a specific operating system,
applications cannot rely on any of the platform-native libraries. Instead, the Java Platform provides
a comprehensive set of standard class libraries, containing the functions common to modern
operating systems.
14
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
The API and Java Virtual Machine insulate the program from the underlying hardware.
As a platform-independent environment, the Java platform can be a bit slower than native code.
However, advances in compiler and virtual machine technologies are bringing performance close
to that of native code without threatening portability.
The key that allows Java to solve both the security and the portability problems is that the output
of a Java compiler is not executable code, rather, it is bytecode. Bytecode is a highly optimized set
of instructions designed to be executed by the Java run-time system Java Virtual Machine (JVM).
That is, in its standard form, the JVM is an interpreter for bytecode. Most modern languages are
designed to be compiled, not interpreted—mostly because of performance concerns. However, the
fact that a Java program is executed by the JVM helps solve the major problems associated with
downloading programs over the Internet.
Translating a Java program into bytecode helps makes it much easier to run a program in a wide
variety of environments. The reason is straightforward: only the JVM needs to be implemented for
each platform. Once the run-time package exists for a given system, any Java program can run on
it. If a Java program were compiled to native code, then different versions of the same program
would have to exist for each type of CPU available. This is, of course, not a feasible solution. Thus,
the interpretation of bytecode is the easiest way to create truly portable programs.
The fact that a Java program is interpreted also helps to make it secure. Because the execution of
every Java program is under the control of the JVM, the JVM can contain the program and prevent
it from generating side effects outside of the system. As you will see, safety is also enhanced by
certain restrictions that exist in the Java language.
When a program is interpreted, it generally runs substantially slower than it would run if compiled
to executable code. However, with Java, the differential between the two is not so great. The use
of bytecode enables the Java run-time system to execute programs much faster than you might
expect.
Although Java was designed for interpretation, there is technically nothing about Java that prevents
on-the-fly compilation of bytecode into native code. Along these lines, Sun supplied its Just In
15
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
Time (JIT) compiler for bytecode, which is included in the Java 2 release and later. When the JIT
compiler is part of the JVM, it compiles bytecode into executable code in real time, on a piece-by-
piece, demand basis. It is important to understand that it is not possible to compile an entire Java
program into executable code all at once, because Java performs various run-time checks that can
be done only at run time. Instead, the JIT compiles code as it is needed, during execution. However,
the just-in-time approach still yields a significant performance boost. Even when dynamic
compilation is applied to bytecode, the portability and safety features still apply, because the run-
time system (which performs the compilation) still is in charge of the execution environment.
Whether your Java program is actually interpreted in the traditional way or compiled on-the-fly,
its functionality is the same.
The Oracle Corporation, which owns the Java trademark, distributes the Java Virtual Machine
implementation HotSpot together with an implementation of the Java Class Library under the
name Java Runtime Environment (JRE).
16
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
The JVM specification defines the subsystems and their external behavior. The JVM has the
following major subsystems:
• Class Loader: responsible for reading Java source code and loading classes into the data
areas.
• Execution Engine: responsible for executing instructions from the data areas.
The data areas occupy memory that is allocated by the JVM from the underlying OS.
17
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
Class Loader
The JVM uses different class loaders organized into the following hierarchy:
• The bootstrap class loader is the parent for other class loaders. It loads the core Java
libraries and is the only one written in native code. The bootstrap class loader loads the
core Java libraries located in the <JAVA_HOME>/jre/lib directory.
• The extension class loader is a child of the bootstrap class loader. It loads the extension
libraries. The extensions class loader loads the code in the extensions directories
<JAVA_HOME>/jre/lib/ext.
• The system class loader is a child of the extension class loader. It loads the application
class files that are found in the classpath.
• A user-defined class loader is a child of the system class loader or another user-defined
class loader.
When a class loader receives a request to load a class, it checks the cache to see if the class has
already been loaded, then delegates the request to the parent. If the parent fails to load the class,
then the child attempts to load the class itself. A child class loader can check the cache of the parent
class loader, but the parent cannot see classes loaded by the child. The design is such because a
child class loader should not be allowed to load classes that are already loaded by its parent.
18
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
Execution Engine
The execution engine executes commands from the bytecode loaded into the data areas one by
one. To make the bytecode commands readable to the machine, the execution engine uses two
methods.
• Interpretation - the execution engine changes each command to machine language as it is
encountered.
• Just-in-time (JIT) compilation - if a method is used frequently, the execution engine
compiles it to native code and stores it in the cache. After that, all commands associated
with this method are executed directly without interpretation.
Although JIT compilation takes more time than interpretation, it is done only once for a method
that might get called thousands of times. Running such method as native code saves a lot of
execution time compared to interpreting each command one by one every time it is encountered.
JIT compilation is not a requirement of the JVM specification, and it is not the only technique that
is used to improve JVM performance. The specification defines only which bytecode commands
relate to which native code; it is up to the implementation to define how the execution engine
actually performs this conversion.
Besides interpreting Java bytecode, most software implementations of the JVM include a just-in-
time (JIT) compiler that generates machine code for frequently used methods. Machine code is the
native language of the CPU and can be executed much faster than interpreting bytecode.
19
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
I. STAND-ALONE APPLICATIONS
Console Applications
Like in many other programming languages, Java application can either be GUI based or console
based. Console based applications are Java programs that run from a command prompt and do not
display any GUI based screen. Such programs have console based outputs.
20
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
A Java applet is a special kind of Java program that a browser enabled with Java technology can
download from the internet and run. An applet is typically embedded inside a web page and runs
in the context of a browser. An applet must be a subclass of the java.applet.Applet class. The
Applet class provides the standard interface between the applet and the browser environment.
A Java applet is a small application which delivered to users in the form of that bytecode. The user
launches the Java applet from a web page, and the applet is then executed within a Java Virtual
Machine (JVM) in a process separate from the web browser itself. A Java applet can appear in a
frame of the web page, a new application window, Sun's AppletViewer, or a stand-alone tool for
testing applets. Java applets were introduced in the first version of the Java language, which was
released in 1995.
21
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
Chapter 2
Input is any information that is needed by your program to complete its execution. Input to
programs takes different forms. Some programs use graphical components like a popup dialog
box to accept and return the character string that is typed by the user. You are certainly familiar
with programs that are controlled simply by clicking the mouse in a specific area of the
screen. Still other programs, like word processing programs, get some of their input from a file
that is stored on the computer's floppy or hard disk drive. Some programs, like web browsers, get
their data from a network connection, while others get data from devices like scanners, digital
cameras and microphones. The possibilities are limited only by computer scientists' imagination.
Output is any information that the program must convey to the user. The information you see on
your computer screen is being output by one or more programs that are currently running on your
computer. When you decide to print a document, a program is told to send some output to the
printer. Any sound that your computer makes is because some program sent output to the speakers
on your computer. The possibilities for program output are also limited only by our imaginations.
There are several potential error conditions that may occur when a program needs to get input from
the user. If a user enters letters when a program is expecting numbers, an exception (error) will
occur if the program assumes incorrectly that it has a valid integer to use in calculations. Programs
must be written to survive bad input by the user. One way to do this is to ensure that only valid
input is accepted.
22
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
Standard Java classes do not ensure that only valid input is accepted. They are designed to be very
flexible to support the wide variety of input and output options available now and in the
future. This flexibility comes at the cost of increased complexity.
Java applications can accept input from console or GUI input fields. The console window is the
window that is automatically launched when you run a Java program. Console input is any input
that is entered in the console window instead of typing it into a field or dialog box that pops up in
a window.
Java applications are designed to work in a terminal (console) I/O environment. Every Java
application has at its disposal three I/O streams that are designed for terminal-based input and
output, which simply sends or receives data one character at a time. The three streams are:
• Standard input (stdin): A stream designed to receive input data. This stream is usually
connected to the keyboard at the computer where the program is run. That way, the user
can type characters directly into the standard input stream. You can connect this input
stream to a class called Scanner that makes it easy to read primitive data types from the
standard input stream.
• Standard output (stdout): A stream designed to display text output on-screen. When you
run a Java program under Windows, a special console window is opened, and the standard
output stream is connected to it. Then, any text you send to standard output is displayed in
that window.
• Standard error (stderr): Another stream designed for output. This stream is also
connected to the console window. As a result, text written to the standard output stream is
often intermixed with text written to the error stream. Windows and other operating
systems allow you to redirect standard output to some other destination — typically a file.
23
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
When you do that, only the standard output data is redirected. Text written to standard error
is still displayed in the console window.
All three standard streams are available to all Java program via the fields of the System class.
Field Description
System.in Standard input
System.out Standard output
System.err Standard error
Output
System.out is known as the standard output object. System.out allows Java applications to display
strings and other types of information in the console window from which the Java application
executes.
System.out defines the print() and println() methods which are used to write data to the console.
You can use both methods with either a String argument or an argument of any primitive data type.
The method System.out.println() displays a line of text in the command window. When
System.out.println() completes its task, it automatically positions the output cursor to the beginning
of the next line in the command window. This move of the cursor is similar to you pressing the
Enter key when typing in a text editor.
Syntax:
System.out.print(message);
System.out.println(message);
The only difference between the print() and the println() methods is that the println() method adds
a line-feed character to the end of the output, so the output from the next call to print() or println()
begins on a new line. Because it doesn’t start a new line, the print() method is useful when you
want to print two or more items on the same line. For example:
System.out.print("Hello world...\n");
System.out.println("Hello world...");
System.out.print( "The answer is: ");
System.out.print( 3.14 );
System.out also implements the low-level method write( ). Thus, write( ) can be used to write to
the console. The simplest form of write( ) defined by PrintStream is shown here:
void write(int byteval)
This method writes to the stream the byte specified by byteval. Although byteval is declared as an
integer, only the low-order eight bits are written. Here is a short example that uses write( ) to output
the character “A” followed by a newline to the screen:
24
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
class WriteDemo {
public static void main(String args[]) {
int b = 'A';
System.out.write(b);
}
}
You will not often use write( ) to perform console output (although doing so might be useful in
some situations), because print( ) and println( ) are substantially easier to use.
Escape Sequence
The backslash (\) is called an escape character. It indicates that a “special character” is to be
output. When a backslash appears in a string of characters, Java combines the next character with
the backslash to form an escape sequence. The escape sequence \n is the newline character. When
a newline character appears in a string being output with System.out, the newline character causes
the screen’s output cursor to move to the beginning of the next line in the command window.
Input
In Java, console input is accomplished by reading from System.in. System.in refers to standard
input, which is the keyboard by default. System.in is an object of type InputStream.
System.in is a byte oriented input accepting mechanism which allows to accept byte by byte.
System.in has a method called read() which returns an integer whose value can be in the range of
0-255. This value is represents a byte of data read from console.
Example:
int a;
System.out.print("Enter a character: ");
a = System.in.read();
System.out.println("Accepted value: “ + a);
25
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
Accepting input using System.in directly is very inflexible because it deals with bytes instead of
characters. As a result, it is not used commonly. Instead other input accepting mechanisms are
used of which one is the Scanner class.
Scanner Class
Until recently, getting text input from the user in a console-based Java program wasn’t easy. But
with Java 1.5, a new class called Scanner has been introduced to simplify the task of getting input
from the user.
Before you can use the Scanner class in a program, you must import it. To do that, we have to use
an import statement at the beginning of the program, before the class declaration as shown below:
import java.util.Scanner;
Before you can use the Scanner class to read input from the console, you must declare a Scanner
variable and create an instance of the Scanner class. I recommend you create the Scanner variable
as a class variable, and create the Scanner object in the class variable initializer, as shown below:
static Scanner sc = new Scanner(System.in);
That way, you can use the sc variable in any method in the class. To create a Scanner object, you
use the new keyword followed by a call to the Scanner class constructor. Note that the Scanner
class requires a parameter that indicates the input stream that the input comes from. You can use
System.in here to specify standard keyboard console input.
To read an input value from the user, you can use one of the methods of the Scanner class. As you
can see, the primitive data type has a separate method.
Method Explanation
boolean nextBoolean() Reads a boolean value from the user
byte nextByte() Reads a byte value from the user
double nextDouble() Reads a double value from the user
float nextFloat() Reads a float value from the user
int nextInt() Reads an int value from the user
String nextLine() Reads a String value from the user
long nextLong() Reads a long value from the user
short nextShort() Reads a short value from the user
Table Scanner Class Methods that get input values
26
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
Example:
import java.util.Scanner;
public class ScannerApp {
static Scanner sc = new Scanner(System.in);
public static void main(String[] args) {
System.out.print("Enter an integer: ");
int x = sc.nextInt();
System.out.println("You entered " + x);
}
}
If the user enters a value that can’t be converted to the correct type, the program crashes, which
means that it abruptly terminates. As the program crashes, it displays a cryptic error message that
indicates what caused the failure. For example, if you enter three instead of an actual number, the
console window looks something like this:
Enter an integer: three
Exception in thread “main” java.util.InputMismatchException
at java.util.Scanner.throwFor(Scanner.java:819)
at java.util.Scanner.next(Scanner.java:1431)
at java.util.Scanner.nextInt(Scanner.java:2040)
at java.util.Scanner.nextInt(Scanner.java:2000)
at ScannerApp.main(ScannerApp.java:11)
This message indicates that an exception called InputMismatch Exception has occurred, which
means that the program was expecting to see an integer, but got something else instead.
Subtle bugs are introduced into your program when you connect more than one Scanner object to
the single System.in. So, create only one instance of the Scanner connected to System.in for use
throughout their entire program. All keyboard operations will use that single
shared Scanner object. The code below is placed with other class data members and is not inside
any method.
//Create a single shared Scanner object for keyboard input
private static Scanner scr = new Scanner( System.in );
27
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
Error
System.err (the standard error stream object) normally enables a program to output error messages
to the screen. Standard error is typically used by programs to output error messages or diagnostics.
It is a stream independent of standard output and can be redirected separately.
Example:
try {
static Scanner sc = new Scanner(System.in);
String s = br.nextLine();
double number = Double.parseDouble(s);
System.out.println("Number is:" + number);
} catch (Exception e) {
System.err.println("Error invalid number");
}
The variable is the basic unit of storage in a Java program. A variable is defined by the combination
of an identifier, a type, and an optional initializer. In addition, all variables have a scope, which
defines their visibility, and a lifetime.
Declaring a Variable
In Java, all variables must be declared before they can be used. The basic form of a variable
declaration is shown here:
type identifier [ = value][, identifier [= value] ...] ;
The type is one of Java’s primitive types, or the name of a class or interface. The identifier is the
name of the variable. You can initialize the variable by specifying an equal sign and a value. Keep
in mind that the initialization expression must result in a value of the same (or compatible) type as
that specified for the variable. To declare more than one variable of the specified type, use a
comma-separated list.
Variable Names
The rules and conventions for naming variables can be summarized as follows:
• Variable names are case-sensitive. Variable names age and Age are different variables.
• A variable's name can be any legal identifier — an unlimited-length sequence of Unicode
letters and digits, beginning with a letter, the dollar sign ($), or the underscore (_). The
convention, however, is to always begin your variable names with a letter, not $ or _.
Additionally, the dollar sign character, by convention, is never used at all. While it is
technically legal to begin your variable's name with "_" or "$", this practice is discouraged.
White space is not permitted as part of variable name.
• Subsequent characters may be letters, digits, dollar signs, or underscore characters. As a
convention, when choosing a name for your variables, use full words instead of cryptic
28
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
abbreviations. Doing so will make your code easier to read and understand. In many cases
it will also make your code self-documenting; fields named cadence, speed, and gear, for
example, are much more intuitive than abbreviated versions, such as s, c, and g. Also keep
in mind that the name you choose must not be a keyword or reserved word.
• If the name you choose consists of only one word, spell that word in all lowercase letters.
If it consists of more than one word, capitalize the first letter of each subsequent word. The
names gearRatio and currentGear are prime examples of this convention. If your variable
stores a constant value, such as static final int NUM_GEARS = 6, the convention changes
slightly, capitalizing every letter and separating subsequent words with the underscore
character. By convention, the underscore character is never used elsewhere.
Data Types
Java defines eight simple or primitive types of data: byte, short, int, long, char, float, double,
and boolean. These can be put in four groups:
• Integers - this group includes byte, short, int, and long, which are for wholevalued signed
numbers.
• Floating-point numbers - this group includes float and double, which represent numbers
with fractional precision.
• Characters - this group includes char, which represents symbols in a character set, like
letters and numbers.
• Boolean - this group includes boolean, which is a special type for representing true/false
values.
Integers
Java defines four integer types: byte, short, int, and long. All of these are signed, positive and
negative values. Java does not support unsigned, positive-only integers. All of them are
represented as signed two's complement integer.
byte
The smallest integer type is byte. This is a signed 8-bit type that has a range from –128 to 127.
Variables of type byte are especially useful when you’re working with a stream of data from a
network or file. They are also useful when you’re working with raw binary data that may not be
directly compatible with Java’s other built-in types.
29
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
Byte variables are declared by use of the byte keyword. For example, the following declares two
byte variables called b and c:
byte b, c;
short
The short data type is a 16-bit signed two's complement integer. It has a minimum value of -32,768
and a maximum value of 32,767. You can use a short to save memory in large arrays, in situations
where the memory savings actually matters.
int
The int data type is a 32-bit signed two's complement integer. It has a minimum value of -
2,147,483,648 and a maximum value of 2,147,483,647. For integral values, this data type is
generally the default choice unless there is a reason to choose something else. This data type will
most likely be large enough for the numbers your program will use, but if you need a wider range
of values, use long instead.
In addition to other uses, variables of type int are commonly employed to control loops and to
index arrays. Any time you have an integer expression involving bytes, shorts, ints, and literal
numbers, the entire expression is promoted to int before the calculation is done.
long
long is a signed 64-bit type and is useful for those occasions where an int type is not large enough
to hold the desired value. The range of a long is quite large. This makes it useful when big, whole
numbers are needed.
For example, here is a program that computes the number of kilometers that light will travel in a
specified number of days.
// approximate speed of light in meters per second
int lightspeed = 299792458;
long days, seconds, distance;
days = 1000; // specify number of days here
seconds = days * 24 * 60 * 60; // convert to seconds
distance = lightspeed * seconds; // compute distance
System.out.print("In " + days);
System.out.print(" days light will travel about ");
System.out.println((distance/1000) + " kilometers.");
30
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
Floating-Point Types
Floating-point numbers, also known as real numbers, are used when evaluating expressions that
require fractional precision. For example, calculations such as square root, or trigonometry such
as sine and cosine, result in a value whose precision requires a floating-point type. Java implements
the standard (IEEE–754) set of floating-point types and operators. There are two kinds of floating-
point types, float and double, which represent single- and double-precision numbers, respectively.
Name Width Range
(bits)
double 64 4.9e–324 to 1.8e+308
float 32 1.4e−045 to 3.4e+038
Floating-point literals in Java default to double precision. To specify a float literal, you must
append an F or f to the constant. You can also explicitly specify a double literal by appending a D
or d. Doing so is, of course, redundant.
float
The type float specifies a single-precision value that uses 32 bits of storage. Single precision is
faster on some processors and takes half as much space as double precision, but will become
imprecise when the values are either very large or very small. Variables of type float are useful
when you need a fractional component, but don’t require a large degree of precision.
Example:
float x = 2.5345;
float y = 34.23f;
float z = 6.022E+23;
This data type should never be used for precise values, such as currency. For that, you will need
to use the java.math.BigDecimal class instead.
31
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
double
Double precision uses 64 bits to store a value. For decimal values, this data type is generally the
default choice. Double precision is actually faster than single precision on some modern
processors that have been optimized for high-speed mathematical calculations. All transcendental
math functions, such as sin( ), cos( ), and sqrt( ), return double values. When you need to maintain
accuracy over many iterative calculations, or are manipulating large-valued numbers, double is
the best choice.
char
In Java, the data type used to store characters is char. Java uses Unicode to represent characters.
Unicode defines a fully international character set that can represent all of the characters found in
all human languages. It is a unification of dozens of character sets, such as Latin, Greek, Arabic,
Cyrillic, Hebrew, Katakana, Hangul, and many more. For this purpose, it requires 16 bits. Thus,
in Java char is a 16-bit type. The range of a char is 0 to 65,536.
The standard set of characters known as ASCII still ranges from 0 to 127 as always, and the
extended 8-bit character set, ISO-Latin-1, ranges from 0 to 255. Since Java is designed to allow
applets to be written for worldwide use, it makes sense that it would use Unicode to represent
characters of all languages. Of course, the use of Unicode is somewhat inefficient for languages
such as English, German, Spanish, or French, whose characters can easily be contained within 8
bits. But such is the price that must be paid for global portability.
Character literals should be enclosed in single quotes (‘’), but not double quotes. Numbers can be
assigned to char variables. These numbers are treated as character code of the character desired.
Hence, you can use unary operators on characters just like on numbers.
Example:
char ch1, ch2;
ch1 = 88; // code for X
32
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
ch2 = 'Y';
System.out.print("ch1 and ch2: " + ch1 + " " + ch2); //output: ch1 and ch2: X Y
ch2++; //increment character code by 1
System.out.print("ch2: " + ch2); //output: ch2: Z
Unicode characters are represented using \uxxxx format where xxxx is the Unicode code of the
character and \u is indication of that this is Unicode representation. The number xxxx is given in
hexadecimal. It has a minimum value of '\u0000' and a maximum value of '\uffff'.
Booleans
Java has a simple type, called boolean, for logical values. It can have only one of two possible
values: true or false. This is the type returned by all relational operators, such as a < b. boolean
is also the type required by the conditional expressions that govern the control statements such as
if and for.
Example:
boolean b = false;
System.out.println("b is " + b);
b = 3 < 4;
System.out.println("b is " + b);
Strings are declared and initialized much like primitive types. In fact, the only difference is that
the word String is capitalized, unlike the keywords for the primitive types. The following
statements define and initialize a string variable:
String s;
s = "Hello, World!";
33
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
Notice that string literals are enclosed in quotation marks, not apostrophes. Apostrophes are used
for character literals, which are different than string literals.
You can combine two strings by using + which is a concatenation operator. For example, the
following statement combines the value of two string variables to create a third string:
String he = "Jimma University, ";
String wo = "Jimma";
String greeting = he + wo;
The final value of the greeting variable is "Jimma University, Jimma!".
You can also mix variables and string literals. For example:
String hello = "Hello";
String world = "World! ";
String greeting = hello + ", " + world;
Note: If you come from a C or C++ background, keep in mind that Java is more strictly typed than
either language. For example, in C/C++ you can assign a floating-point value to an integer. In Java,
34
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
you cannot. Also, in C there is not necessarily strong type-checking between a parameter and an
argument. In Java, there is.
When one type of data is assigned to another type of variable, an automatic type conversion
(implicit casting) will take place if the following two conditions are met:
• The two types are compatible.
• The destination type is larger than the source type.
When these two conditions are met, a widening conversion takes place. For example, the int type
is always large enough to hold all valid byte values, so no explicit cast statement is required. For
widening conversions, the numeric types, including integer and floating-point types, are
compatible with each other.
35
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
Type Casting
To create a conversion between two incompatible types, you must use a cast. A cast is simply an
explicit type conversion. Casting is similar to conversion, but isn’t done automatically.
When you use casting, you run the risk of losing information. For example, a double can hold
larger numbers than an int. But, an int can’t hold the fractional part of a double. As a result, if you
cast a double to an int, you run the risk of losing data or accuracy. For example, 3.1415 becomes
3.
To cast a primitive value from one type to another, you use a cast operator, which is simply the
name of a primitive type in parentheses placed before the value you want to cast. The general
syntax is:
variable = (data-type) value
Here, data-type specifies the desired type to convert the specified value to.
For example, the following fragment casts an int to a byte. If the integer’s value is larger than the
range of a byte, only bits that can fit into byte is taken and other bits discarded.
int a = 100;
byte b = (byte) a;
36
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
A different type of conversion will occur when a floating-point value is assigned to an integer type:
truncation. Thus, when a floating-point value is assigned to an integer type, the fractional
component is lost. Of course, if the size of the whole number component is too large to fit into the
target integer type, then that value will be reduced to the bits that fit into the target type.
Example:
public static void main(String args[]) {
byte b;
int i = 257;
double d = 323.142;
System.out.println("\nConversion of int to byte.");
b = (byte) i;
System.out.println("i and b " + i + " " + b);
System.out.println("\nConversion of double to int.");
i = (int) d;
System.out.println("d and i " + d + " " + i);
System.out.println("\nConversion of double to byte.");
b = (byte) d;
System.out.println("d and b " + d + " " + b);
}
Output:
Conversion of int to byte.
i and b 257 1
Conversion of double to int.
d and i 323.142 323
Conversion of double to byte.
d and b 323.142 67
A boolean value cannot be assigned to any other data type. Except boolean, all the other data types
can be assigned to one another either implicitly or explicitly; but boolean cannot. This means,
boolean is incompatible for conversion.
String to Number
Converting a primitive value to a string value is pretty easy. But converting a string value to a
primitive is a little more complex, because it doesn’t always work. For example, if a string contains
the value 10, you can easily convert it to an integer. But if the string contains “thirty-two”, you
can’t.
37
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
To convert a string to a primitive type, you use a parse method of the appropriate wrapper class
(see table below).
Wrapper class Parse Method Example
Integer parseInt(String) int x = Integer.parseInt(“100”);
Short parseShort(String) short x = Short.parseShort(“100”);
Long parseLong(String) long x = Long.parseLong(“100”);
Byte parseByte(String) byte x = Byte.parseByte(“100”);
Float parseFloat(String) float x = Float.parseFloat (“19.95”);
Double parseDouble(String) double x = Double.parseDouble(“19.95”);
Boolean parseBoolean(String) boolean x = Boolean.parseBoolean(“true”);
For example, to convert a string value to an integer, you use statements like this:
String s = “10”;
int x = Integer.parseInt(s);
Constant
A constant, also called final variable, is a variable whose value you can’t change once it has been
initialized. To declare a final variable, you add the final keyword to the variable declaration, like
this:
final double PI = 5;
Although it isn’t required, using all capital letters for final variable names is common. You can
easily spot the use of final variables in your programs.
Constants are useful for values that are used in several places throughout a program and that don’t
change during the course of the program.
2.3 Operators
An operator is a special symbol or keyword that is used to designate a mathematical operation or
some other type of operation that can be performed on one or more values, called operands. In all,
Java has about 40 different operators.
38
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
Operator Description
+ Unary plus operator; indicates positive value (numbers are positive
without this still)
- Unary minus operator; negates an expression
++ Increment operator; increments a value by 1
-- Decrement operator; decrements a value by 1
! Logical complement operator; inverts the value of a boolean
Example:
public static void main(String[] args) {
int result = +1; // result is now 1
result--; // result is now 0
result++; // result is now 1
result = -result; // result is now -1
boolean success = false;
boolean tt = !success; // true
}
Arithmetic Operators
These arithmetic operators perform basic arithmetic operations, such as addition, subtraction,
multiplication, and division.
Operator Description Example
+ Addition x = 3+4;
- Subtraction y = 5-3;
* Multiplication x = 5*5;
/ Division y = 50/2;
% Remainder y = 20%7;
++ Increment y++; ++x;
-- Decrement y--; --x;
Example:
short x = 6, y = 4;
float a = 12.5f, b = 7f;
System.out.println("x is " + x + ", y is " + y);
System.out.println("x + y = " + (x + y));
System.out.println("x - y = " + (x - y));
System.out.println("x / y = " + (x / y));
System.out.println("x % y = " + (x % y));
39
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
Example:
double x = 5.5, y = 2.0;
double m = x + y; // m is 7.5
double n = x - y; // n is 3.5
double o = x * y; // o is 11.0
double p = x / y; // p is 2.75
double q = x % y; // q is 1.5
x++; // x is now 6.5
y--; // y is now 1.0
Relational Operators
The relational operators determine the relationship that one operand has to the other. Specifically,
they determine equality and ordering i.e. which one is greater than or less than the other.
Operator Meaning Example
== Equal x == 3
!= Not equal x != 3
< Less than x<3
> Greater than x>3
<= Less than or equal to x <= 3
>= Greater than or equal to x >= 3
The outcome of these operations is a boolean value. The relational operators are most frequently
used in the expressions that control the if statement and the various loop statements.
Example:
int a = 4, b = 1;
boolean c = a < b; //false
if(a > 10)
System.out.println("Greater than ten");
Logical Operators
A logical operator (sometimes called a boolean operator) is an operator that returns a boolean result
that’s based on the boolean result of one or two other expressions. Expressions that use logical
operators are sometimes called compound expressions because the effect of the logical operators
is to let you combine two or more condition tests into a single expression.
40
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
Example:
boolean a = true, b = false;
boolean d = a & b;
boolean e = a ^ b;
boolean f = (!a & b) | (a & !b);
boolean g = !a;
System.out.println(" a = " + a + " b = " + b);
System.out.println(" a&b = " + d); //false
41
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
Operator Precedence
Operator precedence determines the order in which operators are performed. This can clearly affect
the result of the operation.
Parentheses raise the precedence of the operations that are inside them. This is often necessary to
obtain the result you desire.
42
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
Packages
A package is a group of classes that belong together. It is a group of similar types of classes,
interfaces and sub-packages. It is a container for classes & interfaces. It is a way to organize classes
into groups and reduce mess. The advantages of Java Package are:
• packages are used to categorize the classes and interfaces so that they can be easily
maintained.
• package provides access protection. Package protects accessibility of class members.
• package removes naming collision. Classes in different packages can have the same name.
Package in Java can be categorized in two: built-in package and user-defined package.
Built-in Packages
The Java platform provides an enormous class library suitable for use in your own applications.
This library is known as the Application Programming Interface or API for short. Its packages
represent the tasks most commonly associated with general-purpose programming. For example,
a String object contains state and behavior for character strings; a File object allows a programmer
to easily create, delete, inspect, compare, or modify a file on the file system; a Socket object allows
for the creation and use of network sockets; various GUI objects control buttons and checkboxes
and anything else related to graphical user interfaces. There are literally thousands of classes to
choose from. This allows you, the programmer, to focus on the design of your particular
application, rather than the infrastructure required to make it work.
43
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
Importing Packages
Application developers use Java API classes when writing programs. To include these classes into
programs, we use the import statement. The purpose of the import statement is to let the compiler
know that the program is using a class that’s defined by the Java API.
Because the Java API contains literally thousands of classes, some form of organization is needed
to make the classes easier to access. Java does this by grouping classes into manageable groups
called packages. A package is a namespace that organizes a set of related classes. Conceptually
you can think of packages as being similar to different folders on your computer. You might keep
HTML pages in one folder, images in another, and scripts or applications in yet another. Because
software written in the Java programming language can be composed of hundreds or thousands of
individual classes, it makes sense to keep things organized by placing related classes and interfaces
in packages.
The import statements must appear at the beginning of the class file, before any class declarations.
This occurs immediately following the package statement (if it exists) and before any class
definitions. You can include as many import statements as are necessary to import all the classes
used by your program.
44
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
All of the standard Java classes included with Java are stored in a package called java or javax.
The basic language functions are stored in a package inside of the java package called java.lang.
Normally, you have to import every package or class that you want to use, but since Java can’t run
without much of the functionality in java.lang, it is automatically imported by the compiler for all
programs. This is equivalent to the following line being at the top of all of your programs:
import java.lang.*;
If a class with the same name exists in two different packages that you import using *, the compiler
will remain silent, unless you try to use one of the classes. In that case, you will get a compile-
time error and have to explicitly name the class specifying its package.
45
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
Strictly speaking, import statements are never required. But if you don’t use import statements to
import the API classes your program uses, you must fully qualify the names of the classes when
you use them by listing the package name in front of the class name.
Example:
Date dt; //requires import
java.util.Date dt; //fully qualified, no import needed
To create a package, simply include a package command as the first statement in a Java source
file. Any classes declared within that file will belong to the specified package. The package
statement defines a name space in which classes are stored. If you omit the package statement, the
class names are put into the default package, which has no name. While the default package is fine
for short, simple programs, it is inadequate for real applications. Most of the time, you will define
a package for your code.
Java uses file system directories to store packages. For example, the .class files for any classes you
declare to be part of MyPackage must be stored in a directory called MyPackage. Remember that
it is case-sensitive, and the directory name must match the package name exactly.
Example: the program defines a class called Addition in a package called arithmetic
package arthimetic;
import java.util.Scanner;
public class Addition {
public static void main(String args[]) {
Scanner sc = new Scanner(System.in);
double a, b, c;
46
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
47
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
Exercise
1. Convert the following algebraic expression into Java code:
𝑎+𝑏+𝑐+𝑑+𝑒
a. 𝑚 =
5
b. y = mx+b2
c. y = ax2 + bx + c
2. What is the output of the following program?
int x = 10, y;
y = x += 3 + 4;
System.out.println(x + " " + y);
3. What is the output of the following program?
int x = 10, z = 5;
x += z = 4;
System.out.println(x + " " + z);
8. Write a program that accepts the coefficients of quadratic equation and then solve it. The
program accepts values of a, b and c and then compute both roots and display.
48
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
Chapter 3
Decision and Repetition Statements
Control Structure
The statements inside your Java codes are generally executed from top to bottom, in the order that
they appear. Control flow statements, however, break up the flow of execution by employing
decision making, looping, and branching, enabling your program to conditionally execute
particular blocks of code.
Java, like any programming language, uses control statements to cause the flow of execution to
advance and branch based on changes to the state of a program. Java control statements can be put
into the following categories: selection, iteration, and jump. Selection statements allow your
program to choose different paths of execution based upon the outcome of an expression or the
state of a variable. Iteration statements enable program execution to repeat one or more statements
again and again. Jump statements allow your program to execute in a nonlinear fashion.
The if Statement
The if-then statement is the most basic of all the control flow statements. It tells your program to
execute a certain section of code only if a particular test evaluates to true. The if statement relies
heavily on the use of boolean expressions, which are expressions that yield a simple true or false
result.
Syntax:
if (boolean-expression){
statement;
}
if-else statements
An if-else statement adds an additional element to a basic if statement: a statement or block that’s
executed if the boolean expression is false. The basic syntax is
if (boolean-expression){
statement
}
else {
statement
}
49
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
else-if statements
A common programming construct that is based upon a sequence of nested ifs is the if-else-if
ladder. It looks like this:
if(condition){
statements;
}
else if(condition){
statements;
}
else if(condition){
statements;
}
...
else {
statements;
}
The if statements are executed from the top down. As soon as one of the conditions controlling the
if is true, the statement associated with that if is executed, and the rest of the ladder is bypassed.
If none of the conditions is true, then the final else statement will be executed. The final else acts
as a default condition; that is, if all other conditional tests fail, then the last else statement is
performed. If there is no final else and all other conditions are false, then no action will take place.
50
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
Switch
Switch provides an easy way to dispatch execution to different parts of your code based on the
value of an expression.
Unlike if-then and if-then-else statements, the switch statement can have a number of possible
execution paths. A switch works with the byte, short, char, and int primitive data types. It also
works with enumerated types, the String class, and a few special classes that wrap certain primitive
types: Character, Byte, Short, and Integer.
Syntax:
switch (expression) {
case value1:
// statement sequence
break;
case value2:
// statement sequence
break;
...
default:
// default statement sequence
}
The body of a switch statement is known as a switch block. A statement in the switch block can
be labeled with one or more case or default labels. The switch statement evaluates its expression,
then executes all statements that follow the matching case label.
The following code example, declares an int named month whose value represents a month. The
code displays the name of the month, based on the value of month, using the switch statement.
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int month = sc.nextInt();
String monthString;
switch (month) {
case 1: monthString = "January"; break;
case 2: monthString = "February"; break;
case 3: monthString = "March"; break;
case 4: monthString = "April"; break;
case 5: monthString = "May"; break;
case 6: monthString = "June"; break;
51
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
The break statement is optional. If you omit the break, execution will continue on into the next
case. It is sometimes desirable to have multiple cases without break statements between them.
For example, consider the following program:
int month = 4;
String season;
switch (month) {
case 12:
case 1:
case 2:
season = "Winter"; break;
case 3:
case 4:
case 5:
season = "Spring"; break;
case 6:
case 7:
case 8:
season = "Summer"; break;
case 9:
case 10:
case 11:
season = "Autumn"; break;
default:
season = "Bogus Month";
}
System.out.println("April is in the " + season + ".");
52
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
3.2 Loops/Iteration
In Java, like in other programming languages, a loop repeatedly executes the same set of
instructions until a termination condition is met. Java provides three iteration statements: for,
while, and do-while.
53
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
if(isPrime == True)
System.out.println(“It is prime”);
else
System.out.println(“It is not prime”);
In the initialization expression, you can’t declare variables if you use more than one expression.
That’s why variables a and b are declared before the for statement in the example above.
You can’t list more than one expression in the test expression. However, you can use compound
conditions created with logical operators, so you don’t need to use an expression list.
Omitting Expressions
Another aspect of for loops is that all three of the expressions are optional. If you omit one or more
of the expressions, you just code the semicolon as a placeholder so the compiler knows. Omitting
the test expression or the iteration expression is not common, but omitting the initialization
expression is common. For example, the variable you’re incrementing in the for loop may already
be declared and initialized before you get to the loop. In that case, you can omit the initialization
expression, as in this example:
Scanner sc = new Scanner(System.in);
System.out.print(“Where should I start? “);
int a = sc.nextInt();
for ( ; a >= 0; a--)
System.out.println(a);
You can also omit all three of the expressions if you want to, as in this example:
for(; ;)
System.out.println(“Oops”);
This program also results in an infinite loop. There’s little reason to do this because while(true)
has the same effect and is more obvious.
54
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
The do loop
Java also provides a do-while statement, which can be expressed as follows:
do {
statement(s)
} while (expression);
The difference between do-while and while is that do-while evaluates its expression at the bottom
of the loop instead of the top. Therefore, the statements within the do block are always executed
at least once, even if the condition is false from the beginning.
55
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
Nested Loops
Loops can contain loops in the body of the loop. The technical term for this is nested loop. A nested
loop is simply a loop that is completely contained inside another loop. The loop that’s inside is
called the inner loop, and the loop that’s outside is called the outer loop.
3.3. Jumping
Java supports three jump statements: break, continue, and return. These statements transfer control
to another part of a program.
56
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
The continue statement skips the current iteration of a loop and jump to the next iteration.
Example: add number between 0 and 100 excluding numbers from 40-60
double sum = 0;
for(int t = 1; t < 100; t++) {
if(t >= 40 && t <= 60)
continue;
sum = sum + t;
}
57
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
Exercise
1. Write a program that accepts a number form user and calculates the factorial of the input. If
the input is n, calculate n! and display the result on console.
3. Write a program that adds the odd integers between 1 and 99 using a for loop structure. Display
the sum on a console.
4. A certain shop sells five different products whose retail prices are as follows: product 1, $2.98;
product 2, $4.50; product 3, $9.98; product 4, $4.49; and product 5, $6.87. Write an application
that reads a pair of numbers as follows:
- product number
- quantity sold for one day
Your program should use a switch structure to help determine the retail price for the product.
It should calculate and display the total price of the item taking quantity into consideration.
5. Write a program that produces the following shape. The output produced by this program is
shown here:
*********
********
*******
******
*****
****
***
**
*
58
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
Chapter 4
Classes and Objects
What Is an Object?
Objects are key to understanding object-oriented technology. Look around right now and you'll find many
examples of real-world objects: cat, desk, television set, bicycle, book, etc.
Real-world objects share two characteristics: They all have state and behavior. Cats have state (name,
color, breed, hungry, etc) and behavior (meowing, stalking, wagging tail, etc). Bicycles also have state
(current gear, current pedal cadence, current speed) and behavior (changing gear, changing pedal cadence,
applying brakes). Identifying the state and behavior for real-world objects is a great way to begin thinking
in terms of object-oriented programming.
An attribute is usually something static. This means that it cannot be changed without changing the essential
nature of the object to which it belongs. For example, all cats have the attribute color. Though attributes
themselves are usually static, the value of an attribute is usually dynamic. So you can alter the state of an
object by changing the value of its attributes.
Another characteristic of objects is that they have behavior, which means they can do things. Like state, the
specific behavior of an object depends on its type. But unlike state, the behavior isn’t different for each
instance of a type.
Identity is what makes the object unique. Students have ID no, or an email which is unique. This can identify
one student from the other student object. This is important when implementing the equals method, to
determine if the objects are different or not.
Take a minute right now to observe the real-world objects that are in your immediate area. For each object
that you see, ask yourself two questions: "What possible states can this object be in?" and "What possible
behavior can this object perform?". Make sure to write down your observations. As you do, you will notice
that real-world objects vary in complexity; a lamp in your room may have only two possible states (on and
off) and two possible behaviors (turn on, turn off), but your radio might have additional states (on/off,
current volume, current station) and behavior (turn on, turn off, increase volume, decrease volume, seek,
scan, and tune). You may also notice that some objects, in turn, will also contain other objects. For example,
a car contains tires, engine, seats, etc. These real-world observations all translate into the world of object-
oriented programming.
59
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
Software objects are conceptually similar to real-world objects: they too consist of state and behavior. A
software object stores its state in fields (variables in some programming languages) and exposes its behavior
through methods (functions in some programming languages). Methods operate on an object's internal state
and serve as the primary mechanism for object-to-object communication. Hiding internal state and requiring
all interaction to be performed through an object's methods is known as data encapsulation — a
fundamental principle of object-oriented programming.
By attributing state and providing methods for changing that state, the object remains in control of how the
outside world is allowed to use it. For example, if the bicycle only has 6 gears, a method to change gears
could reject any value that is less than 1 or greater than 6.
Bundling code into individual software objects provides a number of benefits, including:
1. Modularity: the source code for an object can be written and maintained independently of the source
code for other objects. Once created, an object can be easily passed around inside the system.
2. Information-hiding: by interacting only with an object's methods, the details of its internal
implementation remain hidden from the outside world.
3. Code re-use: if an object already exists (perhaps written by another software developer), you can
use that object in your program. This allows specialists to implement/test/debug complex, task-
specific objects, which you can then trust to run in your own code.
60
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
4. Plugability and debugging ease: if a particular object turns out to be problematic, you can simply
remove it from your application and plug in a different object as its replacement. This is analogous
to fixing mechanical problems in the real world. If a tyre breaks, you replace it, not the entire
machine.
Classes
A class is the blueprint from which individual objects are created. In real world, you'll often find many
individual objects all of the same kind. For example, there may be thousands of other bicycles in existence,
all of the same make and model. Each bicycle was built from the same set of blueprints and therefore
contains the same components. In object-oriented terms, we say that your bicycle is an instance of the class
of objects known as bicycles.
All classes must be defined by a class declaration that provides the name for the class and the body of the
class. Here’s the most basic form of a class declaration:
[public] class ClassName {
data members;
methods;
}
The public keyword indicates that this class is available for use by other classes. Although it is optional,
you usually include it on your class declarations. After all, the main reason you write class declarations is
so that other classes can create objects from the class.
The ClassName is an identifier that provides a name for your class. You can use any identifier you want to
name a class, but the following three guidelines can simplify your life:
• Begin the class name with a capital letter. If the class name consists of more than one word,
begin each word with capital. For example, Ball, Car, Dog, Bicycle, RetailCustomer, and
GuessingGame.
• Whenever possible, use nouns for your class names. Classes create objects, and nouns are the
words you use to identify objects. Thus, most class names should be nouns.
• Avoid using the name of a Java API class. This is not must, but if you create a class that has the
same name as a Java API class, you have to use fully qualified names (like java.util.Scanner) to tell
your class and the API class with the same name apart.
The data or variables defined within a class are called instance variables or fields. The code is contained
within methods. Collectively, the methods and variables defined within a class are called members of the
class. In most classes, the instance variables are acted upon and accessed by the methods defined for that
class. Thus, it is the methods that determine how a class’ data can be used.
61
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
The top level access modifier applies to classes. A class may be declared with the modifier public, in which
case that class is visible to all classes everywhere. But if a class has no modifier (the default, also known
as package-private), it is visible only within its own package.
At the member level, for both fields and methods, you can also use the public modifier or no modifier
(package-private) just as with top-level classes, and with the same meaning. For members, there are two
additional access modifiers: private and protected. The private modifier specifies that the member can only
be accessed in its own class. The protected modifier specifies that the member can only be accessed within
its own package (as with package-private) and, in addition, by a subclass of its class in another package.
The following table shows the access to members permitted by each modifier.
Modifier Package Subclass World
Public Y Y Y
protected Y Y N
no modifier Y N N
Private N N N
The second column indicates whether classes in the same package as the class (regardless of their parentage)
have access to the member. The third column indicates whether subclasses of the class — declared outside
this package — have access to the member. The fourth column indicates whether all classes have access to
the member.
Data Members
There are several kinds of variables in classes:
• Member variables in a class—these are called fields.
• Variables in a method or block of code—these are called local variables.
• Variables in method declarations—these are called parameters.
A data member is a variable that is defined in the body of a class, outside of any of the class’ methods.
Fields are available to all the methods of a class. In addition, if the data member/field specifies the public
keyword, then it is visible outside of the class. If you don’t want the field to be visible outside of the class,
use the private keyword instead.
Fields are defined the same as any other Java variable, but can have a modifier that specifies whether the
field is public, protected or private.
62
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
For local variables and parameters, using access modifier is not allowed. This makes sense since these
variables are already limited in their scope to the method they are defined in. Hence, trying to use access
modifiers when defining local variables and parameters will cause compile error.
Example: the following variable definitions are not allowed
Public void add(public double a, public double b) {
private double sum = a + b;
System.out.println("The sum is " + sum);
}
Constructors
It can be tedious to initialize all of the variables in a class each time an instance is created. Because the
requirement for initialization is so common, Java allows objects to initialize themselves when they are
created. This automatic initialization is performed through the use of a constructor.
A constructor initializes an object immediately upon creation. Thus when we use the new keyword to create
object, the class constructor is called. A constructor has the same name as the class in which it resides and
is syntactically similar to a method. Once defined, the constructor is automatically called immediately after
the object is created, before the new operator completes.
Constructors have no return type, not even void. This is because the implicit return type of a class’s
constructor is the class type itself. It is the constructor’s job to initialize the internal state of an object so
that the code creating an instance will have a fully initialized, usable object immediately.
Broadly, constructors can be divided into three: default constructor, parameterized constructor and copy
constructor. Copy constructor can be seen one type of parameterized constructor.
63
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
Default Constructors
If you don’t define a constructor in your class, Java creates one for you. This generated constructor is called
the default constructor. It doesn’t accept any parameters and it doesn’t do anything, but it does allow your
class to be instantiated.
The default constructor is not created if you declare any constructors for the class. As a result, if you declare
a constructor that accepts parameters and still want to have a default constructor, you must explicitly declare
a default constructor for the class.
Parameterized Constructors
A constructor that has parameters is known as parameterized constructor. Parameterized constructor is used
to provide different values to the distinct objects. It initializes the object to the values of the parameter
passed when new keyword is used to create object.
64
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
Example:
public class Car {
private int numLiters;
private int horsepower;
private String color;
private String model;
private String make;
65
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
this.color = "blue";
}
public static void main(String args[]) {
Car defaultCar = new Car();
System.out.println("DefaultCar: " + defaultCar);
Car chevy = new Car(2000, "Chevy", "Cavalier");
System.out.println("Chevy: " + chevy);
Car dodge = new Car("Toyota", "Corolla", 5, 400);
System.out.println("Dodge Car: " + dodge);
}
}
Copy Constructor
Another common form of a constructor is called a copy constructor. A copy constructor is a constructor that
creates a new object as a copy of an existing object. The argument of such a constructor is a reference to an
object of the same type as is being constructed. Once it gets its object argument, it creates a copy of it and
create new object.
66
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
}
void display(){
System.out.println("ID: " + id);
System.out.println("Name: " + name);
System.out.println("Birthdate: " + birthdate);
}
public static void main(String args[]) {
Student s1 = new Student(“111/05”, "Karan", new Date(1/01/1990));
Student s2 = new Student(s1);
s1.display();
s2.display();
}
}
Calling Constructors
From within a constructor, you can explicitly invoke another constructor from the same class by using the
this() statement. You may want to do this if you have several overloaded constructors in a class, all of which
must execute much of the same code.
Example:
class CoffeeCup {
private int number;
public CoffeeCup() {
this(237); // Calls other constructor
// Could have done more construction here
}
public CoffeeCup(int amount) {
number = amount;
}
}
In this example, the default constructor invokes the other constructor that takes an int as parameter. It passes
237 to the other constructor, which assigns that value to number.
You cannot call this() from methods, only from constructors. If you do call this() in a constructor, you must
call it first, before any other code in the constructor, and you can only call it once. Any code you include
after the call to this() will be executed after the invoked constructor completes.
Destructors
Often, constructors acquire various system resources such as memory. We need a disciplined way to give
resources back to the system when they are no longer needed to avoid resource leaks. The most common
resource acquired by constructors is memory. Java performs automatic garbage collection of memory to
help return memory back to the system. When an object is no longer used in the program (i.e., there are no
references to the object), the object is marked for garbage collection. The memory for such an object can
67
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
be reclaimed when the garbage collector executes. Therefore, memory leaks that are common in other
languages like C and C++ (because memory is not automatically reclaimed in those languages) are less
likely to happen in Java. However, other resource leaks can occur.
To add a destructor to a class, you simply define the finalize( ) method. The Java run time calls that method
whenever it is about to recycle an object of that class. Inside the finalize( ) method you will specify actions
that must be performed before an object is destroyed. The garbage collector runs periodically, checking for
objects that are no longer referenced by any running state or indirectly through other referenced objects.
Right before resource is freed, the Java run time calls the finalize( ) method on the object.
In Java, the tight linkage of the destruction of an object and the calling of its finalize( ) method does not
exist. In Java, objects are not explicitly destroyed when they go out of scope. Rather, an object is marked
as unused when there are no longer any references pointing to it. Even then, the finalize( ) method will not
be called until the garbage collector runs. Thus, you cannot know precisely when or where a call to finalize(
) will occur. Even if you execute a call to the garbage collector, there is no guarantee that finalize( ) will
immediately be executed.
68
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
The reason the program fails is that garbage collection does not occur each time f( ) returns. Thus, finalize(
) is not invoked, and the value of count is not decremented. After five calls to the method, count reaches
its maximum value and the program fails.
Instantiating Objects
When you create a class, you are creating a new data type. You can use this type to declare objects of that
type. However, obtaining objects of a class is a two-step process. First, you must declare a variable of the
class type. This variable does not define an object. Instead, it is simply a variable that can refer to an object.
Second, you must acquire an actual, physical copy of the object and assign it to that variable. You can do
this using the new operator. The new operator dynamically allocates (that is, allocates at run time) memory
for an object and returns a reference to it. This reference is the address in memory of the object allocated
by new. This reference is then stored in the variable. Thus, in Java, all class objects must be dynamically
allocated.
It is important to understand that new allocates memory for an object during run time. The advantage of
this approach is that your program can create as many or as few objects as it needs during the execution of
your program. However, since memory is finite, it is possible that new will not be able to allocate memory
for an object because insufficient memory exists. If this happens, a run-time exception will occur. For the
sample programs in this handout, you won’t need to worry about running out of memory, but you will need
to consider this possibility in real-world programs that you write.
69
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
Here, objname is a variable of the class type being created. The classname is the name of the class that is
being instantiated. The class name followed by parentheses specifies the constructor for the class. A
constructor defines what occurs when an object of a class is created.
The first line declares myrect as a reference to an object of type Rectangle. After this line executes, myrect
contains the value null, which indicates that it does not yet point to an actual object. Any attempt to use
myrect at this point will result in a compile-time error. The next line allocates an actual object and assigns
a reference to it to myrect.
After the second line executes, you can use myrect as if it were a Rectangle object. But in reality, myrect
simply holds the memory address of the actual Rectangle object. The effect of these two lines of code is
depicted in the figure below.
70
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
Statement Effect
null
Rectangle myrect;
myrect
myrect
height
area
Rectangle object
width
b1
height
area
b2
Rectangle object
Although b1 and b2 both refer to the same object, they are not linked in any other way. For example, a
subsequent assignment to b1 will simply unhook b1 from the original object without affecting the object or
affecting b2. For example:
71
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
Accessing Members
To access data members and methods of classes using objects, we use the dot(.) operator. This is the only
way to access members of class since Java does not support pointers. This has the general format like:
objectname.field;
objectname.method();
Static Members
Static members are a special type of field or method that isn’t associated with a particular instance of a
class. Instead, static fields and methods are associated with the class itself. That means you don’t have to
create an instance of the class to access a static field or methods. You access a static field or method by
specifying the class name, not a variable that references an object.
To create such a member, precede its declaration with the keyword static. When a member is declared
static, it can be accessed before any objects of its class are created, and without reference to any object.
You can declare both methods and variables to be static. The most common example of a static member is
main( ). main( ) is declared as static because it must be called before any objects exist.
Instance variables declared as static are, essentially, like global variables. When objects of its class are
declared, no copy of a static variable is made. Instead, all instances of the class share the same static
variable.
Static Fields
Each object of a class has its own copy of all the instance variables of the class. In certain cases, only one
copy of a particular variable should be shared by all objects of a class. A static class variable is used for
these and other reasons. A static class variable represents class-wide information—all objects of the class
share the same piece of data. The declaration of a static member begins with the keyword static.
72
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
Example:
public class Rectangle {
private static int rectangleCount;
…
}
The position of the static and access modifiers are interchangeable. As a result, the following statement
works as well:
static private int rectangleCount;
As a convention, most programmers tend to put the visibility keyword first.
Local variables can’t be defined as static variables. It is not possible to use the static keyword within a class
method. Thus, the following code won’t compile:
public class Rectangle {
static private void calcArea() {
static int x;
}
}
In other words, fields can be static, but local variables can’t.
Obviously, constructors can’t initialize static field members. So, one question that may arise is when are
the static variables initialized? Static fields are created and initialized when the class is first loaded. That
happens when a static member of the class is referred to or when an instance of the class is created,
whichever comes first. Another way to initialize a static field is to use a static initializers.
Static Initializers
Java provides a feature called a static initializer that’s designed specifically to let you initialize static fields.
The general form of a static initializer is this:
static {
statements...
}
As you can see, a static initializer is similar to an initializer block, but begins with the word static. Like an
initializer block, you code static initializers in the class body but outside of any other block, such as the
body of a method or constructor.
The first time you access a static member such as a static field or a static method, any static initializers in
the class are executed provided you haven’t already created an instance of the class. That’s because the
static initializers are also executed the first time you create an instance. In that case, the static initializers
are executed before the constructor is executed.
73
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
static {
x = 32;
}
// other class members such as constructors and methods go here...
}
Static Methods
A static method is a method declared with the static keyword. Like static fields, static methods are
associated with the class itself, not with any particular object created from the class. As a result, you don’t
have to create an object from a class before you can use static methods defined by the class.
The best-known static method is main, which is called by the JVM to start an application. The main method
must be static, which means that applications are by default run in a static context.
Outside of the class in which they are defined, static methods and variables can be used independently of
any object. To do so, you need only specify the name of their class followed by the dot operator. For
example, if you wish to call a static method from outside its class, you can do so using the following general
form:
classname.method([argument])
Here, classname is the name of the class in which the static method is declared. As you can see, this format
is similar to that used to call non-static methods through object-reference variables except that here we are
using the name of the class instead of object name.
A static variable can be accessed in the same way—by use of the dot operator on the name of the class.
This is how Java implements a controlled version of global methods and global variables.
Example:
class Rectangle {
static int width = 42;
static int height = 99;
static void display() {
System.out.println("width = " + width);
System.out.println("height = " + height);
}
}
class ABC {
public static void main(String args[]) {
Rectangle.display();
System.out.println("width = " + Rectangle.width);
74
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
}
}
Static methods can’t access instance (non-static) data members. For example, the following code generates
error (static can’t access member)
public class TestClass {
private int x = 5; // an instance field
public static void main(String[] args) {
int y = x; // error: won’t compile
}
}
Even if the static members can’t access instance field and methods, you can access static methods and fields
from an instance method. For example, the following code works fine:
public class Invoice {
private static double vatRate = 0.15;
private double itemPrice;
public double computeTax() {
return itemPrice * vatRate;
}
}
Example:
public class Car {
private static int carCount = 0;
public Car() {
carCount++;
}
private static void printCount() {
System.out.println("There are now " + carCount + " cars.");
}
public static void main(String[] args) {
printCount();
for (int i = 0; i < 10; i++) {
Car c1 = new Car();
printCount();
}
}
}
75
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
You can’t achieve this effect by using Java constructors, because a class instance has already been created
by the time the constructor is executed. That’s why you can use the this keyword from within a constructor.
As a result, the normal way to implement a singleton class is to declare all the constructors for the class as
private. That way, the constructors aren’t available to other classes.
Then, you provide a static method that returns an instance. This method either creates a new instance or
returns an existing instance. Here’s a barebones example of a singleton class:
class Triangle {
private static Triangle instance;
private Triangle() { }
public static Triangle getInstance() {
if (instance == null)
instance = new Triangle();
return instance;
}
}
Here, the Triangle class contains a private instance variable that maintains a reference to an instance of the
class. Then, a default constructor is declared with private visibility to prevent the constructor from being
used outside of the class. Finally, the static getInstance() method calls the constructor to create an instance
if the instance variable is null. Then, it returns the instance to the caller.
Here’s a bit of code that calls the getInstance() method twice, and then compares the resulting
objects:
Triangle s1 = Triangle.getInstance();
Triangle s2 = Triangle.getInstance();
if (s1 == s2)
System.out.println("The objects are the same");
else
System.out.println("The objects are not the same");
When this code is run, the first call to getInstance creates a new instance of the Triangle class. The second
call to getInstance simply returns a reference to the instance that was created in the first call. As a result,
the comparison in the if statement is true, and the first message is printed to the console.
76
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
C. Preventing Instances
Sometimes, you want to create a class that can’t be instantiated at all. Then, the class consists entirely of
static fields and methods. A good example in the Java API is the Math class. Its methods provide utility-
type functions that aren’t really associated with a particular object.
You may occasionally find the need to create similar classes yourself. For example, you might create a class
with static methods for validating input data. Or, you might create a database access class that has static
methods to retrieve data from a database. You don’t need to create instances of either of these classes.
You can use a simple trick to prevent anyone from instantiating a class. To create a class instance, you have
to have at least one public constructor. If you don’t provide a constructor in your class, Java automatically
inserts a default constructor, which is public. All you have to do to prevent a class instance from being
created, then, is to provide a single private constructor, like this:
public class Validation {
private Validation() {} // prevents instances
public static boolean isValidName(String name) {
//name should contain only A-Z, a-z
for(int t=0; t<name.length(); t++) {
if (name.charAt(t) >=65 && name.charAt(t) <= 90) //capital letters
77
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
continue;
else if (name.charAt(t) >=97 && name.charAt(t) <= 122) //small letters
continue;
else
return false;
}
return true;
}
}
Now, because the constructor is private, the class can’t be instantiated.
When a method of a class references data member of a specific object of that class, how does Java ensure
that the proper object is referenced? If you have two objects of the same type called a and b, you might
wonder how it is that you can call a method foo( ) for both those objects:
class Banana {
void foo(int i) { /* ... */ }
public static void main(String args[]) {
Banana a = new Banana(), b = new Banana();
a.foo(1);
b.foo(2);
}
}
If there’s only one method called foo(), how can that method know whether it is being called for the object
a or b?
The answer is that each object has access to a reference to itself—called the this reference. The this
reference is used implicitly to refer to both the instance variables and methods of an object.
So, when a method needs to refer to the object that invoked it, it can use the this reference. this can be used
inside any method to refer to the current object. That is, this is always a reference to the object on which
the method was invoked. You can use this anywhere a reference to an object of the current class’ type is
permitted.
To allow you to write the code in a convenient object-oriented syntax, the compiler does some undercover
work for you. There is a secret first argument passed to the method foo(), and that argument is the reference
to the object that is being manipulated. So the two method calls above become something like:
Banana.foo(a, 1);
Banana.foo(b, 2);
78
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
This is internal and you can’t write these expressions and get the compiler to accept them, but it gives you
an idea of what’s happening.
Suppose you are inside a method and you’d like to get the reference to the current object. Since that
reference is passed secretly by the compiler, there’s no identifier for it. However, for this purpose there is
a keyword: this. The this keyword—which can be used only inside a method—produces the reference to
the object the method has been called for. You can treat this reference just like any other object reference.
this can be used inside any method to refer to the current object. That is, this is always a reference to the
object on which the method was invoked. You can use this anywhere a reference to an object of the current
class’s type is permitted.
The this keyword is usually used to qualify references to instance variables of the current object. For
example:
public calss Employee {
String firstName;
String lastName;
public Employee(String last, String first) {
this.lastName = last;
this.firstName = first;
}
}
Here, this isn’t really necessary because the compiler can tell that lastName and firstName refer to class
variables. However, suppose you use lastName and firstName as the parameter names for the constructor:
public Employee(String lastName, String firstName) {
this.lastName = lastName;
this.firstName = firstName;
}
Here, the this keywords are required to distinguish between the parameters named lastName and firstName
and the instance variables with the same names.
The most important type of nested class is the inner class. An inner class is a non-static nested class. It has
access to all of the variables and methods of its outer class and may refer to them directly in the same way
79
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
that other non-static members of the outer class do. Thus, an inner class is fully within the scope of its
enclosing class.
An inner class is simply a class that is contained inside another class. However, there is more to it than that.
Here are some key points about inner classes:
• An inner class automatically has access to all the fields and methods of the outer class — even
private fields and methods. Thus, an inner class has more access to its outer class than a subclass
has to its superclass.
• An inner class carries with it a reference to the current instance of the outer class that enables it to
access instance data for the outer class.
• Because of the outer class instance reference, you can’t create or refer to an inner class from a static
method of the outer class. You can, however, create a static inner class.
• One of the main reasons for creating an inner class is to create a class that is only of interest to the
outer class. As a result, you usually declare inner classes to be private so other classes can’t access
them.
The outer class first has to create instance of the inner class before using it. Just like it is necessary to create
instance of any other classes, the same is true for inner classes. Since inner classes are visible outside of
outer class, it is the outer class that creates instance of the inner class.
80
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
salary = aSalary;
address = new Address(num, st, ct);
}
void printDetails() {
System.out.println("Name: " + name + " \nSex: " + sex + " \nBirth date: " + birthDate +
" \nSalary:" + salary);
}
// inner class
class Address {
int number = 0;
String street = "";
String city = "";
Address(int num, String aStreet, String aCity) {
number = num;
street = aStreet;
city = aCity;
}
void printDetails() {
System.out.println("Address: " + number + " " + street + " , " + city);
}
}
Occasionally, code in an inner class needs to refer to the instance of its outer class. To do that, you list the
name of the outer class followed by the dot operator and this. For example, if Address class wants to access
instance of Employee class, then it goes like:
Employee.this.methodname(); //to access methods
Employee.this.fieldname; //to access data members
81
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
class Engine {
//code here
}
class Wing {
//code here
}
Class LandingGear {
//code here
}
}
Anonymous classes enable you to make your code more concise. They enable you to declare and instantiate
a class at the same time. They are like local classes except that they do not have a name. Use them if you
need to use a local class only once.
82
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
}
public class Car {
//anonymous inner class definition
Engine en = new Engine() {
float maxSpeed = 100; //100km per hour
public void start() {
System.out.println(“Engine starting…”);
}
};
public void startEngine() {
en.start();
}
public static void main(String[] args) {
Car cr = new Car();
cr.startEngine();
}
}
Here are some things that you should keep in mind when you work with anonymous classes:
• You can’t create a constructor for an anonymous class. Because the anonymous class doesn’t have
a name, there is no way to you call the constructor anyway.
• If you list parameters in the parentheses following the class name, Java looks for a constructor in
the base class that matches the parameters you supply. If it finds one, that constructor is called with
the parameters. If not, a compiler error is generated.
• You can’t pass parameters if the anonymous class is based on an interface. That only makes sense,
because interfaces don’t have constructors so Java wouldn’t have anything to pass the parameters
to.
• An anonymous class is a special type of inner class. So, like any inner class, it automatically has
access to the fields and methods of its outer class.
• An anonymous class can’t be static.
The code on the left is a short form of the code on the right.
83
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
Since anonymous inner classes are sub classes, they can be created in two ways: using a class or using an
interface. The engine example given above uses a class defined outside the car class to create anonymous
inner class inside car class.
Anonymous inner classes are usually used for creating event handling code in Java. In GUI based Java
applications, to respond to events like button click, menu selection, etc, we can use anonymous classes.
84
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
Built-in Classes
1. String Class
Implementing strings as built-in objects allows Java to provide a full complement of features that make
string handling convenient. For example, Java has methods to compare two strings, search for a substring,
concatenate two strings, change the case of letters within a string, etc. Also, String objects can be
constructed a number of ways, making it easy to obtain a string when needed.
In Java, String object is immutable i.e. once a String object has been created, you cannot change its content.
Naturally, this may seem to be a serious restriction. However, this is not the case and you can still perform
all types of string operations. Each time you need an altered version of an existing string, a new String
object is created that contains the modifications. The original string is left unchanged. This approach is used
because fixed, immutable strings can be implemented more efficiently than changeable ones.
For those cases in which a modifiable string is desired, there is a companion class to String called
StringBuffer, whose objects contain strings that can be modified after they are created. Both the String
and StringBuffer classes are defined in java.lang. Both are declared final, which means that neither of
these classes may be subclassed. This allows certain optimizations that increase performance to take place
on common string operations.
Frequently, you will want to create strings that have initial values. The String class provides a variety of
constructors to handle this. To create a String initialized by an array of characters, use the constructor
shown here:
String(char chars[ ])
Here is an example:
char chars[] = { 'a', 'b', 'c' };
String s = new String(chars);
This constructor initializes s with the string “abc”.
You can specify a subrange of a character array as an initializer using the following constructor:
String(char chars[ ], int startIndex, int numChars)
Here, startIndex specifies the index at which the subrange begins, and numChars specifies the number of
characters to use. Here is an example:
char chars[] = { 'a', 'b', 'c', 'd', 'e', 'f' };
String str = new String(chars, 2, 3);
85
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
You can construct a String object that contains the same character sequence as another String object using
this constructor:
String(String strObj)
86
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
int indexOf(String str) Returns the index of the first (last) occurrence of the
int lastIndexOf(String str) specified substring.
The String class has four methods for replacing characters or substrings.
Method Description
String replace(char oldChar, char Returns a new string resulting from replacing all occurrences of
newChar) oldChar in this string with newChar.
String replace(CharSequence
Replaces each substring of this string that matches the literal
target, CharSequence
target sequence with the specified literal replacement sequence.
replacement)
String replaceAll(String regex, Replaces each substring of this string that matches the given
String replacement) regular expression with the given replacement.
String replaceFirst(String regex, Replaces the first substring of this string that matches the given
String replacement) regular expression with the given replacement.
87
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
String Modifications
The trim method removes white space characters (spaces, tabs, newlines, and so on) from the start and end
of a word. For example:
String s = " Umpa Lumpa "; //space at the beginning and end
s = s.trim();
88
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
Several of the methods of the String class return modified versions of the original string. The toLowerCase()
method converts a string to all lowercase letters. The toUpperCase method works the same, but converts
strings to all uppercase letters.
String t, u;
String s = "Umpa Lumpa";
t = s.toLowerCase();
u = s.toUpperCase();
System.out.println(t + " " + u); //umpa lumpa UMPA LUMPA
The index of the first character in a string is 0 and hence the above code returns fee starting from index 3
untill the end of the string.
c o f f e e
0 1 2 3 4 5
89
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
Searching Strings
The String class provides two methods that allow you to search a string for a specified character or
substring: indexOf( ) and lastIndexOf( ). indexOf() starts searching from beginning of the string and goes
till the end of the string. lastIndexOf() on the other hand begins from the end of the string and goes till the
beginning of the string.
Example:
String s = "Now is the time for all good men to come to the aid of their country.";
System.out.println(s);
System.out.println("indexOf(t) = " + s.indexOf('t'));
System.out.println("lastIndexOf(t) = " + s.lastIndexOf('t'));
System.out.println("indexOf(the) = " + s.indexOf("the"));
System.out.println("lastIndexOf(the) = " + s.lastIndexOf("the"));
System.out.println("indexOf(t, 10) = " + s.indexOf('t', 10));
System.out.println("lastIndexOf(t, 60) = " + s.lastIndexOf('t', 60));
System.out.println("indexOf(the, 10) = " + s.indexOf("the", 10));
System.out.println("lastIndexOf(the, 60) = " + s.lastIndexOf("the", 60));
Output:
Now is the time for all good men to come to the aid of their country.
indexOf(t) = 7
lastIndexOf(t) = 65
indexOf(the) = 7
lastIndexOf(the) = 55
indexOf(t, 10) = 11
lastIndexOf(t, 60) = 55
indexOf(the, 10) = 44
lastIndexOf(the, 60) = 55
90
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
String Comparison
The String class includes several methods that compare strings or substrings within strings. To compare
two strings for equality, use equals( ). It has this general form:
boolean equals(Object str)
Here, str is the String object being compared with the invoking String object. It returns true if the strings
contain the same characters in the same order, and false otherwise. The comparison is case-sensitive.
To perform a comparison that ignores case differences, call equalsIgnoreCase( ). When it compares two
strings, it considers A-Z to be the same as a-z. It has this general form:
boolean equalsIgnoreCase(String str)
equals( ) versus ==
It is important to understand that the equals( ) method and the == operator perform two different operations.
As just explained, the equals( ) method compares the characters inside a String object. The == operator
compares two object references to see whether they refer to the same instance. The following program
shows how two different String objects can contain the same characters, but references to these objects
will not compare as equal:
String s1 = "Hello";
String s2 = new String(s1);
System.out.println(s1 + " equals " + s2 + " -> " + s1.equals(s2));
System.out.println(s1 + " == " + s2 + " -> " + (s1 == s2));
The contents of the two String objects are identical, but they are distinct objects. This means that s1 and s2
do not refer to the same objects and are, therefore, not ==.
compareTo( )
Often, it is not enough to simply know whether two strings are identical. For sorting applications, you need
to know which is less than, equal to, or greater than the other. A string is less than another if it comes
before the other in alphabetical order. A string is greater than another if it comes after the other in
alphabetical order. The String method compareTo( ) and compareToIgnoreCase() serves this purpose. It
has this general form:
int compareTo(String str);
int compareToIgnoreCase(String str);
91
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
System.out.println(arr[j]);
}
}
}
2. Math Class
Java’s built-in operators are useful, but they don’t come anywhere near providing all the mathematical
needs of most Java programmers. That’s where the Math class comes in. It includes a bevy of built-in
methods that perform a wide variety of mathematical calculations, from basic functions such as calculating
an absolute value or a square root to trigonometry functions such as sin and cos, to practical functions such
as rounding numbers or generating random numbers.
Math class methods allow the programmer to perform certain common mathematical calculations.
Math.PI The constant Pi (π), the ratio of a circle’s radius and 3.141592653589793
diameter
Methods
The Math class provides many built-in methods. You can use these functions to calculate such things as the
absolute value of a number, the minimum and maximum of two values, square roots, powers, and
logarithms
92
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
Method Description
static double sin(double arg) Returns the sine of the angle specified by arg in radians.
static double cos(double arg) Returns the cosine of the angle specified by arg in radians.
static double tan(double arg) Returns the tangent of the angle specified by arg in radians.
static double asin(double arg) Returns the angle whose sine is specified by arg.
static double acos(double arg) Returns the angle whose cosine is specified by arg.
static double atan(double arg) Returns the angle whose tangent is specified by arg.
static double exp(double arg) Returns e raised to the arg.
static double log(double arg) Returns the natural logarithm of arg.
Returns the base 10 logarithm of the argument. The
static double log10(argument)
argument and the return value are doubles.
Returns y raised to the x;
static double pow(double y, double x)
Math.pow(2.0, 3.0); //8.0
static double sqrt(double arg) Returns the square root of arg.
Returns the cube root of the argument. The argument and
static double cbrt(argument)
return value are doubles.
93
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
random( ) returns a pseudorandom number. This value will be between 0 and 1. Most of the time, you will
use the Random class when you need to generate random numbers. If you want to generate random
numbers between 0 – 1000, multiply the result by 1000.
Example:
public class MathClassTest {
public static void main(String[] args) {
int a = 100;
int b = -50;
int c = 3;
double x = 25.0;
double y = 3.0;
double z = 4.0;
The random method generates a random double value between 0.0 (inclusive, meaning it could be 0.0) and
1.0 (exclusive, meaning it can’t be 1.0). However, most computer applications that need random values
need random integers between some arbitrary low value (usually 1, but not always) and some arbitrary high
value. For example, a program that plays dice needs random numbers between 1 and 6, while a program
that deals cards needs random numbers between 1 and 52.
As a result, you need a Java expression that converts the double value returned by the random function into
an int value within the range your program calls for. The following code shows how to do this, with the
values set to 1 and 365 for days of the year:
int low = 1; // the lowest value in the range
int high = 365; // the highest value in the range
int rnd = (int)(Math.random() * (high - low + 1)) + low;
94
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
3. Date Class
The Date class encapsulates the current date and time. It supports the following constructors:
Date( )
Date(long millisec)
Date(String)
The first constructor initializes the object with the current date and time. The second constructor accepts
one argument that equals the number of milliseconds that have elapsed since midnight, January 1, 1970.
Method Description
boolean after(Date date) Returns true if the invoking Date object contains a date that is later
than the one specified by date. Otherwise, it returns false.
boolean before(Date date) Returns true if the invoking Date object contains a date that is earlier
than the one specified by date. Otherwise, it returns false.
int compareTo(Date date) Compares the value of the invoking object with that of date. Returns
0 if the values are equal.
Returns a negative value if the invoking object is earlier than date.
Returns a positive value if the invoking object is later than date.
95
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
getMonth() Returns the month represented by this date. The value is between 0-
11.
getYear() Returns the year represented by this date, minus 1900. It returns a 2
digit year value.
void setTime(long time) Sets the time and date as specified by time, which represents an
elapsed time in milliseconds from midnight, January 1, 1970.
String toString( ) Converts the invoking Date object into a string and returns the result.
Date Comparison
There are three ways to compare two Date objects. First, you can use getTime( ) to obtain the number of
milliseconds that have elapsed since midnight, January 1, 1970, for both objects and then compare these
two values. Second, you can use the methods before( ), after( ), and equals( ). Because the 12th of the month
comes before the 18th, for example, new Date(99, 2, 12).before(new Date (99, 2, 18)) returns true. Finally,
you can use the compareTo( ) method, which is defined by the Comparable interface and implemented by
Date.
96
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
Exercise
1. What is the output of the following program?
String s1 = "ab";
String s2 = s1;
s1 = s1 + "c";
System.out.println(s1 + " " + s2);
2. How many String objects are created in the following program?
int count = 5;
String msg = “There are “;
String msg += count;
String msg += “ apples in the basket.”;
3. Define a class called Course that has three data members: course title, course code, and credit
hour. Include default, parameterized and copy constructor that initializes objects. Also include a
method that accepts course information from user and another method that displays course
information.
4. Define a class called RightTraingle that represents a right angle triangle. It should accept the
base and height of the triangle and then compute its hypotenuse, perimeter and area. Define three
methods one for computing hypotenuse, the other for perimeter and the third one for area. After
the computation, display the result. Also data validate so that base and height can’t be negative.
5. Write a program that calculates GPA of a student after accepting grades of five courses and their
respective credit hours. The course class should be defined as inner class of student class. The
program should accept student details like ID, full name, sex, and birth date. It also should accept
course title, course code, credit hour, and grade for that course. Based on this, the program
computes GPA and display in a grade report format.
97
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
Chapter 5
Arrays
An array is a set of variables that are referenced using a single variable name combined with an index
number. Each item of an array is called an element. All the elements in an array must be of the same type.
Thus, the array itself has a type that specifies what kind of elements it can contain. For example, an int
array can contain int values, and a String array can contain strings.
Here are a few additional tidbits of array information to ponder before you get into the details of creating
and using arrays:
• An array is itself an object. You can refer to the array object as a whole rather than a specific
element of the array by using the array’s variable name without an index. For example, if x[5] refers
to an element of an array, then x refers to the array itself.
• An array has a fixed length that’s set when the array is created. This length determines the number
of elements that can be stored in the array. The maximum index value you can use with any array
is one less than the array’s length. Thus, if you create an array of 10 elements, you can use index
values from 0 to 9.
• You can’t change the length of an array after you create the array.
Array is one type of variable which stores multiple values with same data type. It has many dimensions
such as one dimension, two dimensions, or multidimensional. Array is non-primitive data type.
1. One-Dimensional Arrays
A one-dimensional array is, essentially, a list of similar data typed variables. Single dimensional arrays
store only one column of data. To create an array, you first must create an array variable of the desired type.
The general form of a one-dimensional array declaration is
type var-name[ ];
Here, type declares the base type of the array. The base type determines the data type of each element that
comprises the array. Thus, the data type for the array determines what type of data the array will hold. For
example, the following declares an array named month_days with the type “array of int”:
int month_days[];
Although this declaration establishes the fact that month_days is an array variable, no array actually exists.
In fact, the value of month_days is set to null, which represents an array with no value. To link month_days
with an actual, physical array of integers, you must allocate one using new and assign it to month_days.
new is a special operator that allocates memory.
All objects in Java (including arrays) must be allocated dynamically with operator new. For an array, the
programmer specifies the type of the array elements and the number of elements as part of the new
operation. The general form of new as it applies to one-dimensional arrays appears as follows:
array-var = new type[size];
Here, type specifies the type of data being allocated, size specifies the number of elements in the array, and
array-var is the array variable that is linked to the array. That is, to use new to allocate an array, you must
specify the type and number of elements to allocate.
The elements in the array allocated by new will automatically be initialized to zero. This example allocates
a 12-element array of integers and links them to month_days.
int c[]; // declares the array
98
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
After this statement executes, month_days will refer to an array of 12 integers. Further, all elements in the
array will be initialized to zero.
Initializing an Array
Arrays can be initialized in different ways.
One way to initialize the values in an array is to simply assign them one by one:
String[] days = new Array[7];
Days[0] = “Sunday”;
Days[1] = “Monday”;
Days[2] = “Tuesday”;
Days[3] = “Wednesday”;
Days[4] = “Thursday”;
Days[5] = “Friday”;
Days[6] = “Saturday”;
Java has a shorthand way to create an array and initialize it with constant values:
String[] days = { “Sunday”, “Monday”, “Tuesday”, “Wednesday”, “Thursday”, “Friday”, “Saturday” };
In the second case, each element to be assigned to the array is listed in an array initializer. Here is an
example of an array initializer for an int array:
int[] primes = { 2, 3, 5, 7, 11, 13, 17 };
The length of an array created with an initializer is determined by the number of values listed in the
initializer.
And here’s a loop that fills an array of player names with strings entered by the user:
String[]scientist[] = new String[10];
for (int i = 0; i < scientist.length; i++) {
System.out.print(“Enter scientist’s name: “);
99
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
Java introduced a new type of for loop called an enhanced for loop that is designed to simplify loops that
process arrays and collections. When used with an array, the enhanced for loop has this format:
for (type identifier : array) {
statements...
}
The type identifies the type of the elements in the array, and the identifier provides a name for a local
variable that is used to access each element. And array names the array you want to process. Here’s an
example:
String[] days = { “Sunday”, “Monday”, “Tuesday”, “Wednesday”, “Thursday”, “Friday”, “Saturday” };
for (String d : days) {
System.out.println(d);
}
When using enhanced for loop, knowing the array size is not necessary because Java will handle that
internally. This makes it very simple way of iterating over arrays.
2. Multidimensional Arrays
In Java, multidimensional arrays are actually arrays of arrays. When the elements of an array are
themselves arrays, we say that the array is multidimensional. If the number of dimensions is only two, then
the array is called a two-dimensional array.
Multidimensional arrays are often used to represent tables of values consisting of information arranged in
rows and columns. To identify a particular table element, we must specify the two subscripts — the first
identifies the element’s row and the second identifies the element’s column. Arrays that require two
subscripts to identify a particular element are called two-dimensional arrays.
Two-dimensional arrays are often used to track data in a column and row format, much the way a
spreadsheet works. For example, suppose you’re working on a program that tracks five years worth of sales
(2001 through 2005) for ABC company, with the data broken down for each of four sales territories (North,
South, East, and West). You could create 20 separate variables, with names such as sales2001North,
sales2001South, sales2001East, and so on to store these values. But that gets a little tedious.
100
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
For example, the following declares a two-dimensional array variable called sales to store.
double[][] sales = new double[5][4];
Like a one-dimensional array, a multidimensional array can be initialized using an array literal. Simply use
nested sets of curly braces to nest arrays within arrays. For example, we can declare, create, and initialize
a 5×5 multiplication table like this:
int[][] products = { {0, 0, 0, 0, 0},
{0, 1, 2, 3, 4},
{0, 2, 4, 6, 8},
{0, 3, 6, 9, 12},
{0, 4, 8, 12, 16} };
When working with multidimensional arrays, it is often necessary to use nested loops to create or initialize
them. For example, you can create and initialize a large multiplication table as follows:
int[][] products = new int[13][13];
System.out.print("\t");
for(int row = 0; row <= 12; row++)
System.out.print(row + "\t");
System.out.print("\n");
101
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
For example, since our multiplication table is symmetrical about the diagonal from top left to bottom right,
we can represent the same information in a nonrectangular array with fewer elements:
int[][] products = { {0},
{0, 1},
{0, 2, 4},
{0, 3, 6, 9},
{0, 4, 8, 12, 16} };
To iterate over such arrays, you need to check the length of each row. You can use something like this:
for(int i = 0; i < products.length; i++) {
for(int j=0; j<products[i].length; j++)
System.out.print(products[i][j]);
System.out.println();
}
To initialize arrays whose row lengths vary, it is possible to use loops. For example, to initialize triangular
array like the one above, it is possible to use this code.
int k = 0;
int[][] products = new int[4][];
for(int row = 0; row < 4; row++) {
products[row] = new int[row+1]; // allocate an array of for each row
for(int col = 0; col < row+1; col++) // For each element of the int[],
products[row][col] = k++;
}
Example: iterating over the sales table and calculating the total sales for each year
double[][] sales = {
102
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
Java defines a class called Arrays, which provides a collection of static methods that are useful for working
with arrays. The Arrays class is in the java.util package, so you have to use an import statement for the
java.util.Arrays class or the entire java.util.* package to use this class.
Method Description
static int binarySearch (array, key) Searches for the specified key value in an array. The return value
is the index of the element that matches the key. Returns –1 if
the key couldn’t be found. The array must be sorted in ascending
order for this method to work.
boolean equals(array1, array2) Returns true if the two arrays have the same element values. This
method only checks equality for one-dimensional arrays.
boolean deepEquals(array1, Returns true if the two arrays have the same element values. This
array2) method works for arrays of two or more dimensions.
static void fill(array, value) Fills the array with the specified value. The value and array must
be of the same type and can be any primitive type or an object.
static void fill(array, from, to, Fills the elements indicated by the from and to int parameters
value) with the specified value. The value and array must be of the same
type and can be any primitive type or an object.
103
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
static String toString(array) Formats the array values in a string. Each element value is
enclosed in brackets, and the element values are separated from
each other with commas.
Filling an array
The fill method can be handy if you want to pre-fill an array with values other than the default values for
the array type. For example, here is a routine that creates an array of integers and initializes each element
to the value 100:
int[] startValues = new int[10];
Arrays.fill(startValues, 100);
Sorting an array
The sort method is a quick way to sort an array into sequence. For example, these statements create an array
with 100 random numbers, and then sort the array into sequence so the random numbers are in order:
int[] lotto = {4, 90, 65, 84, 99, 81};
Arrays.sort(lotto); //4 65 81 84 90 99
Searching an array
The binarySearch method is an efficient way to locate an item in an array by its value. For example, suppose
you want to find out if your lucky number is in the lotto array created in the previous example.
int lucky = 13;
int foundAt = Arrays.binarySearch(lotto, lucky);
if (foundAt > -1)
System.out.println(“My number came up!”);
else
System.out.println(“I’m not lucky today.”);
4. ArrayList Class
Java defines a class called ArrayList that supports dynamic arrays that can grow as needed. In Java,
standard arrays are of a fixed length. After arrays are created, they cannot grow or shrink, which means that
you must know in advance how many elements an array will hold. But, sometimes, you may not know until
104
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
run time precisely how large of an array you need. To handle this situation, the collections framework
defines ArrayList. In essence, an ArrayList is a variable-length array of object references. That is, an
ArrayList can dynamically increase or decrease in size. Array lists are created with an initial size. When
this size is exceeded, the collection is automatically enlarged. When objects are removed, the array may be
shrunk.
The ArrayList solves the most common problems of working with normal arrays like:
• An array list automatically resizes itself whenever necessary. Arrays have fixed size which you
can’t change during run time. ArrayList has no such limitation.
• An array list lets you insert elements into the middle of the collection. With an array, inserting
elements in the middle is pretty hard to do unless you are overwriting existing value.
• An array list lets you delete items. If you delete an item from an array, the deleted element becomes
null but the empty slot that was occupied by the item stays in the array.
• The ArrayList class actually uses an array internally to store the data you add to the array list. The
ArrayList class takes care of managing the size of this array. When you add an item to the array list
and the underlying array is full, the ArrayList class automatically creates a new array with a larger
capacity and copies the existing items to the new array before it adds the new item.
The ArrayList class is in the java.util package, so your program must import either java.util.ArrayList or
java.util.*. ArrayList has the constructors shown here:
ArrayList( )
ArrayList(Collection c)
ArrayList(int capacity)
The first constructor builds an empty array list. The second constructor builds an array list that is initialized
with the elements of the collection c. The third constructor builds an array list that has the specified initial
capacity. The capacity is the size of the underlying array that is used to store the elements. The capacity
grows automatically as elements are added to an array list.
To create an array list, you first declare an ArrayList variable, and then call the ArrayList constructor to
instantiate an array list object and assign it to the variable. You can do this on separate lines:
ArrayList signs;
signs = new ArrayList();
or, you can do it on a single line:
ArrayList signs = new ArrayList();
If you are using Java 1.5 and later, you can also specify the type of elements the array list is allowed to
contain. The syntax for this is:
ArrayList<datatype> name = new ArrayList<datatype>();
For example, this statement creates an array list that holds String or Integer objects:
ArrayList<String> books = new ArrayList<String>();
ArrayList<Integer> marks = new ArrayList<Integer>();
After you create an array list, you can use the add method to add objects to the array list. For example,
here’s code that adds strings to an array list:
ArrayList books = new ArrayList();
books.add(“Practical Java Programming”);
books.add(“Basics of Electronic Equipments”);
105
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
books.add(“PHP Simplified”);
books.add(“The Beauty of Chemistry”);
books.add(“Computer Design and Manufacturing”);
If you specified a type when you created the array list, the objects you add via the add method must be of
the correct type.
Accessing Elements
To access a specific element in an array list, you can use the get method. It specifies the index value of
the element you want to retrieve. For example, here’s a for loop that prints all the strings in an array list:
for (int i = 0; i < books.size(); i++)
System.out.println(books.get(i));
Here, the size method is used to set the limit of the for loop’s index variable.
The easiest way to access all the elements in an array list is by using an enhanced for statement. It lets you
retrieve the elements without bothering with indexes or the get method. For example:
for (String s : books)
System.out.println(s);
Here, each String element in the books array list is printed to the console.
106
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
107
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
Exercise
1. Write a program that accepts temperature of the last ten days and then store on an array. Using
the array, compute the average temperature. Also display the hottest and coldest days of the last
ten days.
2. Write a program that accepts and stores names of employees on an array. Using an insertion sort,
sort the employees in ascending order.
3. Write a program that stores prime numbers between 1 and 1,000,000 on an array.
4. Write a program that stores marks of ten subjects for five students. Based on the accepted mark,
calculate the total and average for each student and store it on the array.
108
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
Chapter 6
Inheritance & Polymorphism
1. Inheritance
Inheritance is one of the cornerstones of object-oriented programming because it allows the creation of
hierarchical classifications. Using inheritance, you can create a general class that defines traits common to
a set of related items. This class can then be inherited by other, more specific classes, each adding those
things that are unique to it. The class that is inherited is called the parent class, the base class, or the
superclass. The class that inherits is called the child class, the derived class, sub class or the child class.
Therefore, a subclass is a specialized version of a superclass. It inherits all of the instance variables and
methods defined by the superclass and adds its own, unique elements. The terms subclass and superclass
seem to be the preferred term among Java gurus.
Animal
The idea of inheritance is simple but powerful: when you want to create a new class and there is already a
class that includes some of the code that you want, you can derive your new class from the existing class.
In doing this, you can reuse the fields and methods of the existing class without having to write (and debug)
them yourself.
109
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
A subclass inherits all the members (fields, methods, and nested classes) from its superclass. Constructors
are not members, so they are not inherited by subclasses, but the constructor of the superclass can be
invoked from the subclass.
Creating Subclasses
The basic procedure for creating a subclass is simple. You just use the extends keyword on the declaration
for the subclass. The basic format of a class declaration for a class that inherits a base class is this:
public class DerivedClassName extends BaseClassName {
// class body goes here
}
Java’s form of inheritance is called single inheritance. Single inheritance means that each Java class can
have only one superclass. You can only specify one superclass for any subclass that you create. Java does
not support multiple inheritance. In other words, Java does not support the inheritance of multiple
superclasses into a single subclass. This differs from C++, in which you can inherit multiple base classes.
You can, however, create a hierarchy of inheritance in which a subclass becomes a superclass of another
subclass. However, no class can be a superclass of itself.
A superclass’s public members are accessible anywhere in its subclass types. A superclass’s private
members are accessible only in methods of that superclass i.e. they are not accessible in the subclasses.
Private members are generally not inherited. However, if the superclass has public or protected methods
for accessing its private fields, these can also be used by the subclass.
110
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
A nested class has access to all the private members of its enclosing class—both fields and methods.
Therefore, a nested class (either public or protected) inherited by a subclass has indirect access to all of the
private members of the superclass.
A superclass’s protected access members serve as an intermediate level of protection between public and
private access. A superclass’s protected members are accessible in the superclass, in the subclasses and
other classes in the same package (protected members have package access).
Example:
public class Bicycle {
public int gear;
public int speed;
public Bicycle(int startSpeed, int startGear) {
gear = startGear;
speed = startSpeed;
}
public void setGear(int newValue) {
gear = newValue;
}
public void applyBrake(int decrement) {
speed -= decrement;
}
public void speedUp(int increment) {
speed += increment;
}
}
public class MountainBike extends Bicycle {
public int seatHeight;
public MountainBike(int startHeight, int startSpeed, int startGear) {
super(startSpeed, startGear);
seatHeight = startHeight;
}
public void setHeight(int newValue) {
seatHeight = newValue;
}
public static void main(String args[]) {
Bike b = new Bike(20, 3);
MountainBike mb = new MountainBike();
}
}
111
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
Example: inheritance
class Art {
Art() {
System.out.println("Art constructor");
}
}
class Drawing extends Art {
Drawing() {
System.out.println("Drawing constructor");
}
}
public class Cartoon extends Drawing {
Cartoon() {
System.out.println("Cartoon constructor");
}
public static void main(String[] args) {
Cartoon x = new Cartoon();
}
}
The output for this program shows the automatic calls:
Art constructor
Drawing constructor
Cartoon constructor
Example:
public class Ball {
public Ball() {
System.out.println(“Hello from the Ball constructor”);
}
}
public class BaseBall extends Ball {
public BaseBall() {
System.out.println(“Hello from the BaseBall constructor”);
}
public static void main(String args[]) {
BaseBall bb = new BaseBall();
}
}
When you create an instance of the BaseBall class, the following two lines are displayed on the console:
Hello from the Ball constructor
Hello from the BaseBall constructor
112
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
If you want, it is possible to explicitly call a base class constructor from a subclass by using the super
keyword. Because Java automatically calls the no-arg or default constructor for you, the only reason to do
this is to call a constructor of the base class that uses a parameter.
You need to obey a few rules and regulations when working with superclass constructors:
▪ If you use super to call the superclass constructor, you must do so in the very first statement in the
subclass constructor.
▪ If you don’t explicitly call super, the compiler inserts a call to the default constructor of the base
class. In that case, the base class must have a default constructor. If the base class doesn’t have a
default constructor, the compiler refuses to compile the program.
▪ If the superclass is itself a subclass, the constructor for its superclass is called in the same way. This
continues all the way up the inheritance hierarchy, until you get to the Object class, which has no
superclass.
Example:
final class A {
// ...
}
// The following class is illegal.
class B extends A { // ERROR! Can't subclass A
113
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
// ...
}
2. Overriding Methods
When a class defines a method using the same name, return type, and arguments as a method in its
superclass, the method in the subclass overrides the method in the superclass. When the method is invoked
for an object of the subclass, it is the new definition of the method that is called, not the superclass's old
definition.
Method a subclasses declares a method that has the same signature as a public method of the base class, the
subclass version of the method overrides the base class version of the method. This technique lets you
modify the behavior of a base class to suit the needs of the subclass.
Example:
public class Animal {
public static void speak() {
System.out.println("The class method in Animal.");
}
public void walk() {
System.out.println("The instance method in Animal.");
}
}
public class Cat extends Animal {
public static void speak() {
System.out.println("The class method in Cat.");
}
public void walk() {
System.out.println("The instance method in Cat.");
114
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
}
public static void main(String[] args) {
Animal myAnimal = new Cat();
Animal.speak();
myAnimal.walk();
}
}
The Cat class overrides the instance method in Animal and hides the class method in Animal. The main
method in this class creates an instance of Cat and calls speak() on the class and walk() on the instance.
When overriding a method, you might want to use the @Override annotation that instructs the compiler
that you intend to override a method in the superclass. If, for some reason, the compiler detects that the
method does not exist in one of the superclasses, it will generate an error.
Example:
// Method overriding.
class A {
int i, j;
A(int a, int b) {
i = a;
j = b;
}
void show() {
System.out.println("i and j: " + i + " " + j);
}
}
class B extends A {
int k;
B(int a, int b, int c) {
super(a, b);
k = c;
}
// this overrides show() in A
@Override
void show() {
System.out.println("k: " + k);
}
}
class TestOverride {
public static void main(String args[]) {
B subOb = new B(1, 2, 3);
115
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
When an overridden method is called from within a subclass, it will always refer to the version of the
method defined by the subclass.
Method overloading is a powerful and useful feature. It's another form of polymorphism (ad-hoc
polymorphism). The idea is to create methods that act in the same way on different types of arguments and
have what appears to be a single method that operates on any of the types.
Example:
public class SpaceShip {
double speed;
public final int getSpeed() {
return this.speed;
}
}
Here, the method getSpeed is declared as final. Thus, any class that uses the SpaceShip class as a base class
can’t override the getSpeed method. If it tries, the compiler issues an error message.
Example:
class A {
public final void meth() {
System.out.println("This is a final method.");
}
}
class B extends A {
public void meth() { // ERROR! Can't override.
System.out.println("Illegal!");
}
}
Because meth( ) is declared as final, it cannot be overridden in B. If you attempt to do so, a compile-time
error will result.
Hiding Methods
116
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
If a subclass defines a static method with the same signature as a static method in the superclass, then the
method in the subclass hides the one in the superclass. The distinction between hiding a static method and
overriding an instance method has important implications:
• The version of the overridden instance method that gets invoked is the one in the subclass.
• The version of the hidden static method that gets invoked depends on whether it is invoked from
the superclass or the subclass.
Example:
public class Animal {
public static void testClassMethod() {
System.out.println("The static method in Animal");
}
public void testInstanceMethod() {
System.out.println("The instance method in Animal");
}
}
public class Cat extends Animal {
public static void testClassMethod() {
System.out.println("The static method in Cat");
}
public void testInstanceMethod() {
System.out.println("The instance method in Cat");
}
public static void main(String[] args) {
Cat myCat = new Cat();
Animal myAnimal = myCat;
myAnimal.testClassMethod();
myAnimal.testInstanceMethod();
}
}
Output:
The static method in Animal
The instance method in Cat
3. Polymorphism
Dynamic, run-time polymorphism is one of the most powerful mechanisms that object-oriented design
brings to bear on code reuse and robustness. The ability of existing code to call methods on instances of
new classes without recompiling while maintaining a clean abstract interface is a profoundly powerful tool.
The term polymorphism refers to the ability of Java to use base class variables to refer to subclass objects,
keep track of which subclass an object belongs to, and use overridden methods of the subclass even though
the subclass isn’t known when the program is compiled.
A superclass reference variable can refer to a subclass object. Java uses this fact to resolve calls to
overridden methods at run time. When an overridden method is called through a superclass reference, Java
determines which version of that method to execute based upon the type of the object being referred to at
the time the call occurs. Thus, this determination is made at run time. When different types of objects are
referred to, different versions of an overridden method will be called. In other words, it is the type of the
117
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
object being referred to (not the type of the reference variable) that determines which version of an
overridden method will be executed. Therefore, if a superclass contains a method that is overridden by a
subclass, then when different types of objects are referred to through a superclass reference variable,
different versions of the method are executed.
Example: polymorphism
class Shape {
double dim1;
double dim2;
Shape(double a, double b) {
dim1 = a;
dim2 = b;
}
double area() {
System.out.println("Area for shape is undefined.");
return 0;
}
}
class Rectangle extends Shape {
Rectangle(double a, double b) {
super(a, b);
}
// override area for rectangle
double area() {
System.out.println("Inside Area for Rectangle.");
return dim1 * dim2;
}
}
class Triangle extends Shape {
Triangle(double a, double b) {
super(a, b);
}
// override area for right triangle
double area() {
System.out.println("Inside Area for Triangle.");
return dim1 * dim2 / 2;
}
}
class FindAreas {
public static void main(String args[]) {
Shape f = new Shape(10, 10);
Rectangle r = new Rectangle(9, 5);
Triangle t = new Triangle(10, 8);
Shape figref;
figref = r;
System.out.println("Area is " + figref.area());
figref = t;
System.out.println("Area is " + figref.area());
figref = f;
System.out.println("Area is " + figref.area());
118
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
}
}
The output from the program is shown here:
Inside Area for Rectangle.
Area is 45
Inside Area for Triangle.
Area is 40
Area for Figure is undefined.
Area is 0
Although, all the area methods are called by using Shape object, they call different area() methods because
of polymorphism.
In the following example, how can the playTune(…) method know which play() method to call? It receives
an Instrument reference. So how can the compiler possibly know that this Instrument reference points to
a Wind or Brass or Instrument? The compiler can’t. To get a deeper understanding of the issue, it’s helpful
to examine the subject of binding.
class Instrument {
public void play() {
System.out.println("Instrument play");
}
}
class Wind extends Instrument {
public void play() {
System.out.println("Wind play");
}
}
class Stringed extends Instrument {
public void play() {
System.out.println("Stringed play");
}
}
public class Music {
public static void playTune(Instrument ins) {
ins.play();
}
public static void main(String[] args) {
Wind flute = new Wind();
Stringed violin = new Stringed();
Instrument frenchHorn = new Instrument();
playTune (flute);
playTune (violin);
playTune (frenchHorn);
}
}
Connecting a method call to a method body is called binding. When binding is performed by the compiler,
it’s called early binding. This is done during compilation of source code. Languages like C have only one
kind of method call, and that’s early binding.
119
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
The other approach is called late binding, which means that the binding occurs at run-time based on the
type of object. Late binding is also called dynamic binding or run-time binding. When a language
implements late binding, there must be some mechanism to determine the type of the object at run-time and
to call the appropriate method. That is, the compiler still doesn’t know the object type, but the method-call
mechanism finds out and calls the correct method body.
All method binding in Java uses late binding unless a method has been declared final. This means that
ordinarily you don’t need to make any decisions about whether late binding will occur—it happens
automatically.
In the above program, in the playTune(…) method, the compiler does not know which play() method to
call because there are different paly() methods that can be called by Instrument class object ins. To
determine this, Java uses late-binding during run-time after checking the type of the object. This is what
allows polymorphism.
Within a class, a field that has the same name as a field in the superclass hides the superclass's field, even
if their types are different. Within the subclass, the field in the superclass cannot be referenced by its simple
name. Instead, the field must be accessed through super.
5. Abstract Classes
120
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
There are situations in which you will want to define a superclass that declares the structure of a given
abstraction without providing a complete implementation of every method. That is, sometimes you will
want to create a superclass that only defines a generalized form that will be shared by all of its subclasses,
leaving it to each subclass to fill in the implementation details. Such a class determines the nature of the
methods that the subclasses must implement. One way this situation can occur is when a superclass is unable
to create a meaningful implementation for a method.
You can enforce that certain methods be overridden by subclasses by specifying the abstract type modifier.
These methods are sometimes referred to as subclasser responsibility because they have no implementation
specified in the superclass. Thus, a subclass must override them—it cannot simply use the version defined
in the superclass.
Java lets you declare that a method is abstract, which means that the method has no body. An abstract
method is just a prototype for a method: a return type, a name, a list of parameters, and (optionally) a throws
clause.
Any class that contains one or more abstract methods must also be declared abstract. To declare a class
abstract, you simply use the abstract keyword in front of the class keyword at the beginning of the class
declaration. There can be no objects of an abstract class i.e. an abstract class cannot be directly instantiated
with the new operator. Such objects would be useless, because an abstract class is not fully defined.
A class that contains at least one abstract method is called an abstract class, and must be declared with the
abstract modifier on the class declaration. For example:
public abstract class Shape {
public abstract double calculateArea();
}
If you omit the abstract modifier from the class declaration, the Java compiler brings up an error message
to remind you that the class must be declared abstract.
An abstract class can’t be instantiated. Thus, given the preceding declaration, the following line doesn’t
compile:
Shape b = new Shape(); //error: Shape is abstract
You can create a subclass from an abstract class Shape like this:
public class Rectangle extends Shape {
double width, height, area;
public double calculateArea() {
area = width * height;
}
}
In abstract classes, you cannot declare abstract constructors, or abstract static methods. Any subclass of an
abstract class must either implement all of the abstract methods in the superclass, or be itself declared
abstract.
121
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
▪ Not all the methods in an abstract class have to be abstract. A class can provide an implementation
for some of its methods but not others. In fact, you can declare an abstract class that doesn’t have
any abstract methods. In that case, the class can’t be instantiated.
▪ A private method can’t be abstract. That only makes sense, because a subclass can’t override a
private method, and abstract methods must be overridden.
▪ Although you can’t create an instance of an abstract class, you can declare a variable using an
abstract class as its type. Then, use the variable to refer to an instance of any of the subclasses of
the abstract class.
▪ A class can’t be both abstract and final. That would cause a logical paradox: must be inherited and
can’t be inherited at the same time. But the point is that because an abstract class can only be used
if you subclass it, and a final class can’t be subclassed, letting you specify both abstract and final
for the same class doesn’t make sense.
Example:
public abstract class Shape {
public abstract double area();
public abstract double circumference();
}
class Circle extends Shape {
protected double r;
protected static final double PI = 3.142;
public Circle(double r) {
this.r = r;
}
public double area() {
return PI * r * r;
}
public double circumference() {
return 2 * PI * r;
}
}
class Rectangle extends Shape {
protected double w, h;
public Rectangle(double w, double h) {
this.w = w;
this.h = h;
}
public double area() {
return w * h;
}
public double circumference() {
return 2 * (w + h);
}
}
6. Interface
122
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
There are a number of situations in software engineering when it is important for disparate groups of
programmers to agree to a "contract" that spells out how their software interacts. Each group should be able
to write their code without any knowledge of how the other group's code is written. Generally speaking,
interfaces are such contracts.
An interface is similar to an abstract class. However, it can only include abstract methods and final fields
(constants), and it can’t be used as a base class. Instead, a class implements an interface by providing an
implementation for each method declared by the interface.
In the Java programming language, an interface is a reference type, similar to a class, that can contain only
constants, method signatures, and nested types. There are no method bodies. Interfaces cannot be
instantiated—they can only be implemented by classes or extended by other interfaces.
Variables can be declared inside interface declarations. They are implicitly final and static, meaning they
cannot be changed by the implementing class. They must also be initialized with a constant value. All
methods and variables are implicitly public if the interface, itself, is declared as public. So, the interface
fields are automatically assumed to be static, final, and public. You can include these keywords when you
create interface constants, but you don’t have to.
Implementing Interfaces
Once an interface has been defined, one or more classes can implement that interface. To implement an
interface, include the implements clause in a class definition, and then create the methods defined by the
interface. The general form of a class that includes the implements clause looks like this:
[access modifier] class classname [extends superclass] implements interface [,interface...] {
// class-body
}
Here, access is either public or not used. If a class implements more than one interface, the interfaces are
separated with a comma. If a class implements two interfaces that declare the same method, then the same
method will be used by clients of either interface. The methods that implement an interface must be declared
public. Also, the type signature of the implementing method must match exactly the type signature
specified in the interface definition.
Example:
public interface Shape {
// calculate area
public abstract double area();
123
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
// calculate volume
public abstract double perimeter();
Besides abstract methods, an interface can also include final fields — that is, constants. Interface fields are
used to provide constant values that are related to the interface. For example:
public interface GolfClub{
int DRIVER = 1;
int SPOON = 2;
int NIBLICK = 3;
int MASHIE = 4;
}
Here, any class that implements the GolfClub interface has these four fields constants available. Note that
interface fields are automatically assumed to be static, final, and public. You can include these keywords
when you create interface constants, but you don’t have to.
124
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
What are the differences between abstract classes and interfaces? Abstract class and interface both are used
to achieve abstraction where we can declare the abstract methods. Abstract class and interface both can't be
instantiated.
But there are many differences between abstract class and interface that are given below.
Abstract class Interface
Abstract class can have abstract and non-abstract Interface can have only abstract methods.
methods.
Abstract class doesn't support multiple Interface supports multiple inheritance.
inheritance.
Abstract class can have final, non-final, static and Interface has only static and final variables.
non-static variables.
Abstract class can have static methods, main Interface can't have static methods, main method or
method and constructor. constructor.
Abstract class can provide the implementation of Interface can't provide the implementation of
interface. abstract class.
The abstract keyword is used to declare abstract The interface keyword is used to declare interface.
class.
Example: Example:
public abstract class Shape{ public interface Drawable{
public abstract void draw(); void draw();
} }
Simply, abstract class achieves partial abstraction (0 to 100%) whereas interface achieves fully abstraction
(100%).
125
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
Exercise
1. Write a class that does the four Arithmetic operations. Define a method that accepts two numbers and
add them and return. Overload this method so that it can accept any number data type. Similarly, define
a method for subtraction, division and multiplication and overload them.
2. Define an abstract class called Employee. Put the common things that all employees have in common
in the Employee class. One such common method is a method that computes tax. Include aslo properties
like employee ID, first name, and last name in the abstract class. Then create two derived classes that
extends the Employee class: SalariedEmployee and HourlyEmployee. In the HourlyEmployee include
a method computes the salary to be paid to the employee after accepting the hours the employee worked
and the hourly payment.
3. Declare an interface called Instrument with three methods: play(), adjust(), and what(). Then implement
these methods in Wind, Stringed, and Percussion classes. Implement all the methods of the interface in
these classes. The what() method simply returns the type of the instrument. In the other two methods,
you can produce simple output using System.out. Create instances of classes and assign to reference of
type Instrument. Call the methods and see the effect.
126
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
Chapter 7
Exceptions
What is Exception?
An exceptional condition is a problem that prevents the continuation of the method or scope that is being
executed. An exception is an event, which occurs during the execution of a program that disrupts the normal
flow of the program's instructions. Division is a simple example. If you’re about to divide by zero, it’s
worth checking for that condition or otherwise program execution would be interrupted. Trying to open
non-existing file for reading is another error.
An exception is an object that’s created when an error occurs in a Java program and Java can’t automatically
fix the error. The exception object contains information about the type of error that occurred. However, the
most important information — the cause of the error — is indicated by the name of the exception class used
to create the exception. You don’t usually have to do anything with an exception object other than figure
out which exception you have.
The resulting stack trace from the default exception handler shows how the entire call stack is displayed:
Exception in thread "main" java.lang.ArithmeticException: / by zero
at Division.subroutine(Division.java:3) at Division.subroutine(Division.java:3)
at Division.main(Division.java:6)
Java Result: 1
Types of Exceptions
All exceptions are descendants of Throwable class which is the parent of all exceptions. Thus, Throwable
is at the top of the exception class hierarchy. Immediately below Throwable are two subclasses that partition
exceptions into two distinct branches. One branch is headed by Exception. The other branch is headed by
Error.
127
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
There are three kinds of exceptions. The first kind of exception is the checked exception. These are
exceptional conditions that a well-written application should anticipate and recover from. For example,
suppose an application prompts a user for an input file name, and then opens the file for reading. Normally,
the user provides the name of an existing, readable file, so the execution of the application proceeds
normally. But sometimes the user supplies the name of a nonexistent file, and opening the file fails throwing
java.io.FileNotFoundException. A well-written program will catch this exception and notify the user of the
mistake, possibly prompting for a corrected file name.
All exceptions that extend Throwable class except RuntimeException and Error are known as checked
exceptions e.g. FileNotFoundException, IOException, SQLException, etc. Checked exceptions are
checked at compile-time and the program will not compile if it is not handled.
The second kind of exception is the error. These are exceptional conditions that are external to your
application, and that the application usually cannot anticipate or recover from. Once error occurs, the
application can’t recover from it and hence comes to a halt. Exceptions of type Error are used by the Java
run-time system to indicate errors having to do with the run-time environment itself. For example, suppose
that an application successfully opens a file for reading, but is unable to read the file because of a hardware
or system malfunction. The unsuccessful read will throw java.io.IOError. StackOverflowError is another
example of such an error that is thrown when the program runs out of stack space. Another error is
OutofMemoryError thrown when there is shortage of memory. An application might choose to catch this
exception, in order to notify the user of the problem.
128
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
method2();
}
void method2() {
method1();
}
public static void main(String args[]) {
Test test = new Test();
test.method1();
}
}
Output:
Exception in thread "main" java.lang.StackOverflowError
at javatest.StackOverflow.method1(StackOverflow.java:3)
at javatest.StackOverflow.method2(StackOverflow.java:6)
….
The third kind of exception is the runtime exception. These are exceptional conditions that are internal to
the application, and that the application usually cannot anticipate or recover from. These usually indicate
programming bugs, such as logic errors or improper use of an API. For example, consider the application
described previously that passes a file name to the constructor for FileReader. If a logic error causes a null
to be passed to the constructor, the constructor will throw NullPointerException. The application can catch
this exception, but it probably makes more sense to eliminate the bug that caused the exception to occur.
The classes that extend RuntimeException are unchecked exceptions e.g. ArithmeticException,
NullPointerException, ArrayIndexOutOfBoundsException etc. Unchecked exceptions are not checked at
compile-time rather they are checked at runtime.
String s = "abc";
int i = Integer.parseInt(s); //NumberFormatException
Catching Exceptions
When the Java run-time system detects exceptions, such as an attempt to divide by zero, it constructs a new
exception object and then throws this exception. This causes the execution of the program to stop, because
once an exception has been thrown, it must be caught by an exception handler and dealt with immediately.
If the program does not supply any exception handlers of its own, the exception is caught by the default
handler provided by the Java run-time system. Any exception that is not caught by your program will
ultimately be processed by the default handler. The default handler displays a string describing the
exception, prints a stack trace from the point at which the exception occurred, and terminates the program.
The exception message you have seen above for the division by zero is produced by default handler.
129
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
In general, whenever you use a statement that might throw an exception, you should write special code to
anticipate and catch the exception.
You catch an exception by using a try statement, which has this general form:
try {
block of code that may generate errors
}catch (ExceptionType1 exOb) {
code executed when exception ExceptionType1 is generated
}catch (ExceptionType2 exOb) {
code executed when exception type ExceptionType2 is generated
}
finally {
block of code to be executed before try block ends
}
Here, you place the statements that might throw an exception within a try block. Then, you catch the
exception with a catch block. ExceptionType is the type of exception that has occurred.
Output:
java.lang.ArithmeticException: / by zero
The above try catch handles only one type of error i.e. ArithmeticException. If the code in the try catch
generates other types of exception, the try catch will not handle it. To handle all kinds of exception, it is
130
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
possible to make it general using Exception class which can catch any kind of error instead of
ArithmeticException.
The finally block always executes when the try block exits. This ensures that the finally block is executed
even if an unexpected exception occurs.
But finally is useful for more than just exception handling — it allows the programmer to avoid having
cleanup code accidentally bypassed by a return, continue, or break statements. Putting cleanup code in a
finally block is always a good practice, even when no exceptions are anticipated.
The basic framework for a try statement with a finally block is this:
try {
statements that can throw exceptions
}
catch (exception-type identifier) {
statements executed when exception is thrown
}
finally {
statements that are executed whether or not
exceptions occur
}
Example:
public class DivisionWithZeros {
public static void main(String[] args) {
int answer = divideNumbers(5, 0);
}
public static int divideNumbers(int a, int b) {
try {
int c = a / b;
System.out.println(“It worked!”);
}
catch (Exception e) {
131
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
Output:
It didn’t work.
Better clean up the mess.
Exception Propagation
When an error occurs within a method, the method creates an object and hands it off to the runtime system.
The object, called an exception object, contains information about the error, including its type and the state
of the program when the error occurred. Creating an exception object and handing it to the runtime system
is called throwing an exception.
After a method throws an exception, the runtime system attempts to find something to handle it. The set of
possible codes to handle the exception is the ordered list of methods that had been called to get to the
method where the error occurred. The list of methods is known as the call stack.
The call stack showing three method calls, where the first method called has the exception handler.
The runtime system searches the call stack for a method that contains a block of code that can handle the
exception. This block of code is called an exception handler. The search begins with the method in which
the error occurred and proceeds through the call stack in the reverse order in which the methods were called.
When an appropriate handler is found, the runtime system passes the exception to the handler. An exception
handler is considered appropriate if the type of the exception object thrown matches the type that can be
handled by the handler.
The exception handler chosen is said to catch the exception. If the runtime system exhaustively searches all
the methods on the call stack without finding an appropriate exception handler, the runtime system (and,
consequently, the program) terminates.
132
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
The call stack showing three method calls, where the first method called has the exception handler.
Exception Objects
Inside the standard package java.lang, Java defines several exception classes. The most general of these
exceptions are subclasses of the standard type RuntimeException. Since java.lang is implicitly imported
into all Java programs, most exceptions derived from RuntimeException are automatically available.
Each type of exception that can occur is represented by a different exception class. For example, here are
some typical exceptions:
• ArithmeticException: You tried an illegal type of arithmetic operation, such as dividing an integer
by zero.
• ArrayIndexOutOfBoundsException: when array index is past the last array index.
• ClassNotFoundException: a necessary class couldn’t be found.
• FileNotFoundException: when you try to open a file for reading/writing but the file does not exist.
• IllegalArgumentException: you passed an incorrect argument to a method.
• IOException: A method that performs I/O encountered an unrecoverable I/O error.
• InputMismatchException: the console input doesn’t match the data type expected by a method
of the Scanner class.
• NegativeArraySizeException: array created with a negative size.
• NullPointerException: occurs when your program creates an object reference, but has not yet
created an object and assigned it to the reference. Attempting to use such a null reference causes a
NullPointerException to be thrown.
• NumberFormatException: invalid conversion of a string to a numeric format.
• StringIndexOutOfBounds: attempt to index outside the bounds of a string.
Exception classes have built-in methods and fields. We can get information about the exception using this
methods and fields. Though there are many methods in exception classes, the following are the most
important.
Method Description
133
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
Example: displaying information about the error using exception object methods
try {
int c = 10 / 0;
}
catch (Exception e) {
System.out.println(e.getMessage());
e.printStackTrace();
}
Output:
/ by zero
java.lang.ArithmeticException: / by zero
at Division.main(Division.java: 8)
Example:
class MultiCatch {
public static void main(String args[]) {
try {
int a = args.length;
int b = 42 / a;
int c[] = { 1 };
c[42] = 99;
} catch(ArithmeticException e) {
System.out.println("Divide by 0: " + e);
} catch(ArrayIndexOutOfBoundsException e) {
System.out.println("Array index out of bounds: " + e);
}
System.out.println("After try/catch blocks.");
}
}
This program will cause a division-by-zero exception if it is started with no commandline parameters, since
a will equal zero. It will survive the division if you provide a command-line argument, setting a to
134
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
something larger than zero. But it will cause an ArrayIndexOutOfBoundsException, since the int array
c has a length of 1, yet the program attempts to assign a value to c[42].
When you use multiple catch statements, it is important to remember that exception subclasses must come
before any of their superclasses. This is because a catch statement that uses a superclass will catch
exceptions of that type plus any of its subclasses. Thus, a subclass would never be reached if it came after
its superclass. Further, in Java, unreachable code is an error.
Throws clause
If a method is capable of causing an exception that it does not handle, it must specify this behavior so that
callers of the method can guard themselves against that exception. You do this by including a throws clause
in the method’s declaration. A throws clause lists the types of exceptions that a method might throw. This
is necessary for all exceptions, except those of type Error or RuntimeException, or any of their subclasses.
All other exceptions that a method can throw must be declared in the throws clause. If they are not, a
compile-time error will result. This is the general form of a method declaration that includes a throws
clause:
[access modifier] type method-name(parameter) throws ExceptionType1, ExceptionType2, …
{
body of method
}
135
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
System.out.println("Error:" + xx.toString());
}
}
}
Output:
Error:java.lang.ArrayIndexOutOfBoundsException: 6
The displayArray() method throws a type of exception called ArrayIndexOutOfBoundsException. The loop
in the body tries to iterate 10 times but the array has only 6 elements. This generates an error when the value
of i is 6. This throws an exception. But there is no exception handler in the method, and hence the exception
is passed to the calling method. The main method which calls displayArray() should have a try catch block
to handle this error. The output given above is produced by the main method.
Throwing an Exception
So far, you have only been catching exceptions that are thrown by the Java run-time system. However, it is
possible for your program to throw an exception explicitly, using the throw statement.
The throw statement is executed to indicate that an exception has occurred and the method execution could
not complete successfully. This is called throwing an exception. A throw statement specifies an object to
be thrown.
All methods can use the throw statement to throw an exception. The throw statement requires a single
argument: a throwable object. Throwable objects are instances of any subclass of the Throwable class.
Here's an example of a throw statement.
throw someThrowableObject;
The flow of execution stops immediately after the throw statement; any subsequent statements are not
executed. The nearest enclosing try block is inspected to see if it has a catch statement that matches the
type of the exception. If it does find a match, control is transferred to that statement. If not, then the next
enclosing try statement is inspected, and so on. If no matching catch is found, then the default exception
handler halts the program and prints the stack trace.
136
Prepared by:Tesfamariam G.
Learning module for Java 2015 E.C
Output:
zeeroo
Here are the essential points to glean from the above example:
• You throw an exception by executing a throw statement. The throw statement specifies the type of
exception object to be thrown.
• If a method contains a throw statement, it must include a throws clause in its declaration.
• A method that calls a method that throws an exception must either catch or throw the exception.
Example:
class Test {
double salary[] = {2000, 4000, 3000, 7000, 1000, 15000};
public double getElement(int i) throws ArrayIndexOutOfBoundsException {
if(i >= salary.length)
throw new ArrayIndexOutOfBoundsException("Trying to access invalid array location");
else
return salary[i];
}
public static void main(String args[]) {
try{
Test dv = new Test();
dv.displayArray();
}catch(Exception xx) {
System.out.println("Error:" + xx.getMessage());
}
}
}
Output:
Error: Trying to access invalid array location
137
Prepared by:Tesfamariam G.