Você está na página 1de 839

CS3 - Lecture 2-Introduction To Java and its primitive data types

Author: Satish Singhal, Ph. D.


Version – 1.0

Introduction and Java Portability


In 1991 a-team at Sun Microsystems, led by James Gosling started to develop a
programming language to be used for programming of appliances such as washing
machines, dryers, and other devices. Understand that most “appliances” do not
have an operating system the way computer does. The appliances manufacturers
wished to keep their cost as low as possible. For example they were unwilling to
invest in developing “compilers1” for each appliance. The team at Sun had to come
up with a programming language so that once compiled; the software can run on
any appliance or on any computer2. They designed a language, which was first
called “Oak3” and then renamed Java. One of the best features of Java was that its
compiler first compiled the source code into “byte-code”. This byte-code was then
interpreted and run as a program by a java interpreter. The beauty of byte-code
technology is that the byte-code can be compiled on any type of compiler or
computer. Yet byte-code could be interpreted and run as a software on all other
appliances, devices, and computers as long as such machines had byte-code
interpretation software installed on them. The byte-code interpretation software is
called a Java virtual Machine (JVM). The problem of developing and running
software we thus reduced to following steps:
1. Compile Java software into byte-code on “any” computer.
2. Install a JVM on computer or appliance, on which the software
developed in step one was to be run.
3. JVM, once installed on a computer/appliance will run the “same”
byte-code software easily.
Developed in this manner, Java programming gave birth to a new programming
paradigm “Write once, run anywhere”. One must, however, understand that one
would still need to develop a JVM for each appliance or computer. But it is
somewhat easier to do so as JVM needs to be developed just once. Once JVM for a
computer/appliance is developed, it can run “all” java byte-code compiled software
irrespective of the computer on which it was compiled. Figure 2.1 shows the
difference in traditionally compiled language such as C++ and in byte-code
compiled language like Java.

1
Compiler is software that converts a source code into the machine readable and executable code.
2
The distinction between a computer and appliance is simple. The computers have operating system
appliances do not.
3
There was an Oak tree in front of the building in which the programming team at Sun worked.
Penultimate name of Java came from that Oak tree.

CS3 Java – Introduction to Java (Singhal) Page 1 of 52


FIG. 2.1A
The pure compile languages like C++ would take a source code such as myprog.cpp
(Figure2.1A) and first the compiler will translate it into an object code shown as
myprog.obj. The linker then will take code from C++ and other libraries and create
executable software named as myprog.exe in Figure2. The software such as
myprog.exe communicates directly with the operating system, with out any
intermediate agent. The Java programming language, which compiles a source code
into a byte-code works a bit differently (Figure 2.1B).

CS3 Java – Introduction to Java (Singhal) Page 2 of 52


FIG. 2.1B
In Java, a source code such as Payroll.java would be first compiled into a byte-code
called Payroll.class (Figure 2.1B). The byte-code Payroll.class can be created on any
computer! The same byte-code may then be run on a Windows, UNIX, or
MacIntosh computer, as long as they are all installed and running the JVM, which
simply interprets the byte-code on the fly. Notice that in this case the compiled
program –Payroll.class – does not communicate with the operating system. Rather it
communicates with the JVM and JVM communicates with the operating system.
Thus Java software needs this intermediate agent, JVM, for it to fulfill its paradigm
“Write once and run anywhere”. This at times may slow down a Java program,
especially if JVM is not designed in the best possible manner for an operating
system. Yet the advantage of being able to run the same piece of software on all
computers/appliances can outweigh the reduction in speed of execution. The ability
to be interpreted and executed on all computers/appliances gives Java software a
degree of portability that is missing from traditional languages such as C/C++. Thus
we can summarize the basic features of Java programming language as follows:

• Achieves portability by using both a compiler and an interpreter.


• Java compiler translates a Java program into an intermediate
Bytecode--not machine language.
• An interpreter program called the Java Virtual Machine (JVM)
translates each successive instruction in the Bytecode program to
machine language and immediately runs it.
Having the advantage of design of C++, available to them the Java designers were
able to improve upon it and consequently Java in many ways is a simpler language
to learn and use, compared to C++. The power of Java resides in its ability to write

CS3 Java – Introduction to Java (Singhal) Page 3 of 52


truly “Object Oriented” software. However, in the interest of simplifying the
learning of Java basics, we would ignore discussion of its Object Oriented nature for
some time. We first write a simple “Hello World” program in Java and dissect it for
further learning.

Components of a JAVA Program


A Java Program will typically be composed of the following components:
1. Syntactic Elements
2. Program Identifiers
3. Both of above coding a given algorithm, embedded into at least one Java
method4 called main.
The syntactic elements can be described as follows:
• Operators – Operators are mathematical and other symbols that
perform operations on program data and variables. For example if we
write X = Y + Z, then in this operation, both the equal and plus signs
are operators. We will learn about operators in detail later on.
• Punctuations – Punctuations are the characters that mark the
beginning and ending of a program statement, or separate an item in
a list.
• Syntax – The rules that must be followed when constructing a
program are called syntax rules. Syntax dictates how program
identifiers and operators must be used, and where the punctuation
symbols must appear.
We will discuss the program identifiers in detail a bit later. First we show some of
the syntax rules and language structure by considering a Minimal Java program
below.

A Minimal Java Program


One can guess from the details of any algorithm analysis done using Context
Diagram, Flow Charts or DFD5, that for computer to successfully solve a problem, it
must be fed step-by-step directions contained in the algorithm. Every language
provides some basic program structure, inside which the coded algorithm can be
inserted, compiled, and executed. (The coded algorithm is called a “Program Source
code”). In order to observe as to what basic program structure Java provides for us,
we write a program, which has no coded algorithm in it. Such minimal algorithm-
less Java program is shown below in Listing 2.1.

4
Functions in Java are called methods.
5
These are the components of a Software Engineering design.

CS3 Java – Introduction to Java (Singhal) Page 4 of 52


//**********************************************
//A Java program with no user coded algorithm
//Program is stored in a file called NoCode.java

public class NoCode


{

public static void main (String [ ] args )


{

}
}

// End of Java program with no user coded algorithm


//**********************************************
Listing 2.1
The program of Listing 2.1 has no user-coded algorithm in it. Therefore it does
nothing and solves no practical problem. But it does have the minimal coding
required by Java to qualify it to be a program. The program has just six lines. The
first line
public class NoCode
uses two Java Reserved words, public and class. The word public is the access
specification for the class NoCode. Details of access levels will be discussed later.
The word class defines a Java user-defined data type. This simply means that writer
of class, if they wish, may include data and members methods as needed.
Understand that in Java no methods or data members are definable
outside a class. Java does not have stand alone-methods or global
variables.

The second significant line

public static void main (String [ ] args )

gives us the signatures or header of the main method for class NoCode. Every
stand-alone Java program6 – for it to do anything useful must have at least one
static method, which must be named main. The word public, once again is the access
specifier for the main method, and its return type is void, which means that method
returns nothing. The word static simply means that one can execute a static member
method of a class with out creating an instance of that class. The main method in
Java class has an argument list

6
Java applets do not need a main method. They work on a different mechanism.

CS3 Java – Introduction to Java (Singhal) Page 5 of 52


String [ ] args
This simply means that main method “can” take an array of String objects as
command line arguments. String is a Java class, whose object can store text of
length limited by the storage available to the program. Figure 2.2 summarizes the
body of a DoNothing java class, and the signature of the main method in Java.

FIG. 2.2A Class DoNothing will compile, but will not run as an
executable program as it is missing the main method
The class DoNothing has a minimal heading required by Java using the word class
and class Name (DoNothing). The body of the class is contained inside a pair of
facing curly braces. Notice that unlike C struct and C++ class, Java class definition
does not have a semi-colon after the right brace. This is because in Java a class is a
block and not a statement7. The class DoNothing will compile, but there is no main
method in it, therefore the JVM will give an error message, if one tries to interpret
the compiled byte-code DoNothing.class. Figure 2.2B gives the details of a static
void main method, which has same signatures in any including Java class.

7
In C++ the class definition is a statement of User-defined data type. Therefore the end of class
definition in C++ needs a semi-colon.

CS3 Java – Introduction to Java (Singhal) Page 6 of 52


The execution of a Java program begins with the first line after the left curly brace
inside the main method and ends at the last line before the right curly brace (Figure
2.2B).

public static void main ( String []


Header
Begin execution
of method called args )
main { Body
program statement 1; Block
program statement 2;
End execution of
method called program statement 3;
main ……… ;
………
}
FIG. 2.2 B
The execution of program begins with the first line after the left culry brace in the
body of main method and sequential execution continues until the last program
statement just before the right curly brace is reached. Understand that a
“statement” in Figure 2.2B may be a single line terminated by a semicolon or a
compound statement contained with in a pair of curly braces. Unless the graphical
components, which behave asynchronously are a part of Java program, the
program in main method is executed sequentially line by line. Program statements
may shift control to other member methods of the including class or to other Java
objects created in the main method.

Notice that each “statement” in a Java program must either be a stand-alone


statement terminated by a semi-colon or be a compound statement enclosed in the
pair or curly braces. Use of compound statement or semi-colon terminated program
statements facilitates the compiler to parse and compile the Java program. The
amount of white space between the program statements, and between the words in
the program statements does not matter. A pair of matching parentheses will follow
every Java method name. Such pair of parentheses may or may not have a list of
arguments. When method has no argument, its argument is assumed to be of type
void. If java program including the main method is given command line arguments,
they are stored into an array of String objects named args. An example of use of
command line arguments will be shown later.

Hello World Program in Java


We write a simple Java program, which prints “Hello Word” to standard output
(usually a DOS console) (Listing 2.2).

CS3 Java – Introduction to Java (Singhal) Page 7 of 52


//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Program stored in file HelloWorld.java
public class HelloWorld
{
public static void main(String [ ] args)
{
System.out.print (“Hello World”);
}
}
//Listing 2.2
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
After compiling and executing the program in Listing 2.2 simply prints words Hello
World on the DOS or other standard output console. In this program
System.out.print is a call to method print of the member called out of class System.
Method print simply prints the string, which is passed to it as an argument. You
may recall from C/C++ programming that input output required inclusion of
header files iostream.h or stdio.h. The Listing 2.2 has no such files included in the
source code. It so turns out that in all Java programs a package called java.lang is
included automatically, which contains the output facility, such as System.out.print.
In Java files are divided into packages, whereas each file may have one or more
classes in them. In Java there are no stand-alone methods outside any class.
Therefore all method calls (except for the calls to static methods inside the same
class) are qualified either by the class name or by the instance of a class. For
example in statement:
System.out.print Overloaded
Java class in package method in
java.lang, which is Public static final PrintStream
automatically member data in class class, to print
imported or included System of type class Java primitives,
in all Java programs. PrintStream and string

FIG. 2.3
System.out.print, the word System is a Java class, which is defined in the package
java.lang, which is automatically included (Figure 2.3). The word “out” represents a
publicly accessible, static final8 object of type class PrintStream. Notice that since
the field “out” is a public data member, it can simply be accessed using the dot
operator. The word print represents an overloaded method in class PrintStream,

8
The word final before a Java identifier means that the identifier will represent a constant entity. It
is analogous to const in C++.

CS3 Java – Introduction to Java (Singhal) Page 8 of 52


which can print Java primitives, strings, and other Java objects. We shall discuss
the details in the output/input section of this work.

Now what is the proof that package java.lang, which contains System, and other
utility classes actually got included automatically in our program in Listing 2.2?
Well first proof is in the output. Why would there be an output if our code somehow
did not include an output facility. The second proof lays in fact that in Listing 2.2, if
we replace the line

System.out.print (“Hello World”);

with its fully qualified name

java.lang. System.out.print (“Hello World”);

our output remains unchanged. The fully qualified name gives the full path to locate
a class, field (data) or a member method. We will discuss qualified and unqualified
names in more details later.

Java Program Comments:


Followings are the main purposes of comments in a computer program:
• Assist the readability of the program,
• Create necessary documentation to understand the program variables,
methods, data and other elements,
• Document the program authors, files, versions and dates etc.
• Overall create good documentation.
The compiler ignores the part of program source code that resides inside the
comments. Java allows three types of program comments:
1. Single Line comments – These are written following the two forward
slashes ( // ). The single line comments are ignored by the Java
documentation tool and are not extracted by it.
2. Multi-line comments to be ignored by the Java documentation tool –
Number of lines desired by the programmer may be commented out.
The multi-line comments are enclosed between a pair of forward slash
and a star, which are mirror image of each other (/* */ ).
3. Multi-line comments to be extracted by the Java documentation tool:
These comments begin with a forward slash and two stars and
terminate with a star and forward slash, such as:
/**
These comments will be extracted by the
documentation tool
*/
Examples of first two are shown below:
//This is a single line comment.

CS3 Java – Introduction to Java (Singhal) Page 9 of 52


/*
Some comments may be so long that they may extend to
many lines. This comments is an example of multi-line
comment
*/
Traditionally the program editor environment is chosen such that all comment lines
are turned into green color. In the beginning you may choose to use only the multi-
line comments method. This is because if you start out by thinking that your
comment is only one line and then you keep typing past that line into the next, then
uncommented line would create compile time error. Multi-line commenting style
can also be in-lined. For example the code shown in Figure 2.4 below will compile
and run successfully. The number 1700 has been commented out inline.

FIG. 2.4

Program Identifiers and Reserved Words


We mentioned earlier that program identifiers are either the English language or
programmer made up words in the Java program. Identifiers are used for both the
language requisite program features as well as the program data. We can
summarize the identifiers as follows:

CS3 Java – Introduction to Java (Singhal) Page 10 of 52


• An identifier is the name used for a data object (a variable or a
constant), for a method, for a class, or for other program components
in a Java program.
• Java identifiers are case sensitive.

There are three types of words as one would see in Java programs.
• Java reserved words,
• Name of the main method and its argument data type (String),
• Programmer created names for data objects, methods, etc.
Reserved words serve an important purpose in the programming languages. They
help the compiler do the conversion from source code to the machine language.
Since reserved words have special meaning in the language, they cannot be used for
any purpose, other than the purpose required by the language. When we accept the
program data from the user or we would process the program data and need to
store it internally; for both we needed to name locations in the memory to store all
these data. Since reserved words have special purpose in the language, they cannot
be used to name the memory elements to store program data. Therefore it becomes
important to know as to what are the Java reserved words. These are given below in
Table 2.1.

abstract continue goto package this

assert default if private throw

boolean do implements protected throws

break double import public transient

byte else instanceof return try

case extends int short void

catch final interface static volatile

char finally long super while

CS3 Java – Introduction to Java (Singhal) Page 11 of 52


class float native switch strictfp

const for new synchronized byvalue

outer operator null

Table 2.1 Java Reserved words

The keyword assert is available only in JDK 1.4. The keywords goto, and const are
not used. They are kept only to give meaningful compile error messages in case C++
programmer use them mistakenly. So far you have learned to use only few of the
Java reserved words. It would take you years of professional Java programming to
learn and use all of the Java reserved words. In the meantime the Appendix 2.1
gives detailed definitions of most of the Java reserved words. You may not be able to
understand the definition of all the reserved words at this time.

Characteristics of Java Reserved Words:


A careful look at the Java reserved words list will show us the following main
characteristics:
• All reserved words use only lower case alphabets.
• Many common words such as try, volatile, break, and this etc., are used as
reserved words.
You may set up the environment of your Java source code editor such that all
reserved words are turned into blue color to avoid using them for identifier names.
You may also wish to keep a list of reserved words with you, to ascertain that they
are not used for variables, classes, and method names.

Rules For Programmer Created Identifiers:


Program will need to create memory or storage locations for storing the program
data and method names as well as choose names for classes and packages. The job
of the programmer is to create these identifiers. The rules for the programmer
created identifiers in Java are as follows:
1. Identifiers must only contain alphabets, underscore ( _ ),digits (0 to 9
), and a $ sign.
2. An identifier must begin with an alphabet, underscore or $. It cannot
begin with a digit.
3. An identifier cannot contain blank spaces. (A horrid practice used by
Windows filing system).
4. An identifier cannot be a Java reserved word.

CS3 Java – Introduction to Java (Singhal) Page 12 of 52


Examples of Valid and Invalid Programmer Created Identifiers:
The Table 2.2 below gives the examples of valid and invalid identifiers:
Valid Identifiers Invalid Identifiers/ Comments
A a1 Sum+var + is illegal
student_name stdntNm 2names First character
invalid
_aSystemName _anthrSysNm Stdnt Nmbr Contains Space
$class _public int Reserved word
Table 2.2
The identifier sum+var violates the rule #1. Identifier 2names violates rule #2. The
identifier Stdnt Nmbr violates the rule #3 and use of int as an identifier violates the
rule #4. Identifiers in left hand column are valid. It is important to use meaningful
identifiers. Another Java coding practice is to start the name of classes with upper
case letter. If the name of the class contains more than one word, then first letter of
each word is capitalized. The names of methods begin with lower case letter, but if
method name contains more than one word then first letter of each word after the
first word is capitalized. Names of program and class variables may be in upper or
lower case, but it is a good programming practice to use all lower case names for
Java primitive data types and first letter of each word capitalized for the instances
of Java classes or objects.

Java Data Types:


We showed during the algorithm development, that Computer will accept user input
in form of program data, as well as process those data internally. The data that
computer program may use could be:
• Stored internally in the memory, during the program execution,
• Stored externally by the user on a tape, disk drive,
• Or data are inputted from devices such as keyboard, scanner, electrical
sensors, mice, or modems etc.
Java is a “typed” language in the sense, that before a memory location for the data
can be created in the program, we need to tell the program as to what kind of data
will be stored in that memory. Based on that, during compile time the appropriate
amount of memory is reserved for the data that would be stored in a particular
memory location. We need to understand that every programming language is not
“typed” in this manner. For example in JavaScript if we make the following
assignments,
My_Integer = 10;
My_Decimal = 10.0006;

CS3 Java – Introduction to Java (Singhal) Page 13 of 52


Then the JavaScript program will reserve an integer type (smaller) memory for the
variable My_Integer and store 10 there, but reserve a larger memory for variable
My_Decimal and store 10.0006 there. No explicit data types are defined.

Not so in Java, which needs a specific data type assigned to the variable name. The
corresponding statements in Java will be;
int My_Integer = 10;
float My_Decimal = 10.0006;
Leaving out data type in Java for a local or class variable name, in which data will
be stored will cause a compile error. We do a survey of Java primitive data types in
the Figure 2.5 below:

FIG. 2.5
Java has the following primitive data types:
1. Integral (byte, char, short, int, and long).
2. boolean, which can only have values true and false.
3. Floating point (float and double).
Unlike C++, Java actually has a boolean data type, whose values are simply true and
false. Table 2.3 shows the possible values and size in bytes for various java
primitives on a Windows 9x system.
Type Size Minimum Value Maximum Value
(bytes)
char 2 Uses Unicode characters. Language dependent.
byte 1 -128 127
short 2 -32768 32767
int 4 -2147483648 2147483647
long 8 -9223372036854775808 9223372036854775807
float 4 +/- 1.4E-45 +/- 3.4028235E+38
double 8 +/- 4.9E-324 +/- 1.7976931348623157E+308

CS3 Java – Introduction to Java (Singhal) Page 14 of 52


boolean 1 false true
These values are for Windows 9X system. Values can be JVM dependent for an OS.
Table 2.3
Java allows one to find the maximum and minimum values for certain primitive
data type for a particular JVM implementation. One such program is and its output
is given in appendix 2.2. Java requires, that you be prudent in declaring the data
types for your variables and do a desk checking before running the program, to
ascertain that there will be no overflow in the memory where the results of java
program calculations are to be stored.

Figure 2.6 below shows the samples of some of Java primitive data types.

FIG. 2.6

Variable Declarations And Assigning Values To Variables


Some examples of Java program statements will be declarations of an identifier,
which would associate the identifier with a data object, data type, or a method
name. This allows programmer to refer to certain program variable by the name
coded for it. We have already used declarations in several program listings we have
shown in this chapter so far. For example, in listing 2.4, if we modify the declaration
of num1 as:
short num1;
then we are declaring that in our program a memory of type short (smaller in bytes
than int) be created and it be called by name num1. What does the variable
declaration do? A declaration tells compiler to assign enough memory for the data
type declared for the variable and associate the identifier stated in the declaration
with that memory location. For example in above declaration, the compiler will
create a memory of two bytes and short type and it will associate it with the name

CS3 Java – Introduction to Java (Singhal) Page 15 of 52


num1. Figure 2.7 below shows this process graphically. The declaration does not put
a value in the memory cell, so its contents are unknown or un-initialized.

Compiler reads the


program declaration:
short num1;

Memory
Contents = ? ? ?
named
num1 and
of type
Size = 2 bytes short

FIG. 2.7

Putting Data into Program Variables


The declaration like shown in Figure 2.7 does not put any data in the memory
location created by the declaration. Java however requires that every local variable
be initialized before it is used. If that is not done, then compile error will result. For
example a code like below will not compile!
Compile error – val1 is
int val1; used with out
int val2 = 50; initialization!
int sum = val1+val2; //
The task of putting data in a memory location can be accomplished in two different
ways:
1. Single line Method: The variable declaration and data to be stored in it are
specified in the same line. Take for example the declaration below;
short num1 = 1000;

CS3 Java – Introduction to Java (Singhal) Page 16 of 52


Figure 2.8 below shows how this declaration is parsed by the compiler. The
contents of memory called num1 are no longer undetermined. Rather 1000 is
stored in the 2-byte memory called num1.

Compiler reads the


program declaration:
short num1 = 1000;

FIG. 2.8

Memory
Contents = 1000
named
num1 and
of type
Size = 2 bytes short

2. Two Line Method: The first statement declares the variable and the second
assigns data to it. For example consider the program statements below:

short num1; //Statement 1


num1 = 1000; //Statement 2
The statement 1 creates a memory location just as shown in Figure 2.7. The
statement 2 simply stores 1000 in the memory location, thus erasing the previous
content of the memory.

Multiple Declarations
Java allows one to use the comma operator and declare multiple variables of same
data type on one line. For example the following declarations are legal.

int val1,val2,val3;
int val4=22, val5=-10, val6;

However, understand that compile error will result if any attempt is made to use
val1, val2, val3, and val6 prior to their initialization.

CS3 Java – Introduction to Java (Singhal) Page 17 of 52


Declaring local Constants in Java Programs:
In a Java program, the variables are the memory locations, whose values can be
altered by subsequent assignments. But there are program data, which are either
constants by the way they have been used, or they have been declared to be constant
by using the key word final. The constants are the program entities whose values
do not change during their lifetime. The constants can be two types.
1. Literals – Literal is any program constant that has been directly written into a
program. Take the example of code shown in Figure 2.9 below. When we output or
use some characters, strings, floating point numbers, integers, or boolean conditions
as their values directly, then those become the literal constants or literals in the
program. These include characters enclosed in a pair of single quotes, strings
enclosed in the pair of double quotes, numbers, and true and false.

Outputting a character
literal

Outputting a
string literal.

Outputting floating point,


integer, and boolean literals
respectively

FIG. 2.9
The output of the above program will show that all constants are outputted literally.
That is why they are called literals or literal constants.

2. Named Constants – Some time a constant may be used in a program many times.
In that case using the key word final before we declare the data type, constant name,
and its value identifies its constant nature. Figure 2.10 below shows the examples of
declarations of named constants in Java.

CS3 Java – Introduction to Java (Singhal) Page 18 of 52


FIG. 2.10
Unlike C++, java allows a two-line method to declare and store data into named
constants. However, the rule that all local program variables or constants must be
initialized before their use remains in force. For example the following code snippet
will not cause a compile error in Java:

final int val; Will not cause a compile error


in Java.
val = 5;
However, the following will cause a compile error!

final int val; Will cause a compile


error in Java, as Val is
System.out.println (val);
not initialized.

Therefore it is easy to remember the simple rule: All local variables and
constants in Java must be initialized before they are used!

More about Java Strings


Strings in Java are objects of class java.lang.String. This means that String class is
located in the java.lang package, and this package is automatically imported in all
Java programs. Java String class is designed in such a manner that two or more
String objects and Strings and primitive Java data (See Figure 2.5) can be

CS3 Java – Introduction to Java (Singhal) Page 19 of 52


concatenated, simply by using the plus (+) sign. For example, the following String
concatenation is a legal Java construct:

String Big_String = “John” + ‘ ‘+’H’+’.’+’ ‘+”Smith is “ + 20+


” years old and has a gpa = “+ 3.9+” and he does well in “ + true + ‘/’+
false+” type examinations.”;
System.out.println (Big_String);

The above code snippet will print the following on the DOS console:

John H. Smith is 20 years old and has a gpa = 3.9 and he does well in
true/false type examinations.

Notice that using the property of overloaded operator plus (+) for String class, Java
is able to concatenate characters (such as space, alphabets, and punctuation marks),
integers (20 in above case), floating-point numbers (3.9), and boolean literals (true
and false) all into one string. It is however, required that on right hand side of
String concatenation expression, at least one of the data must be of String type. For
example expression given below is not a valid String concatenation expression and
will cause compile error!
Compile error. None of
String Not_A_String = ‘H’ + 25 + ‘L’; the expressions to be
concatenated are String
type!

Therefore one must remember the following String concatenation rule: At least
one of the expressions to be concatenated must be of String type! More
examples of String concatenation are shown in Figure 2.11 below.

FIG. 2.11

CS3 Java – Introduction to Java (Singhal) Page 20 of 52


Question! What will the code snippet in Figure 2.11 print?

Parsing of Java Strings to get numerical data from user input


In Java all user input, whether entered by keyboard, or passed as command line
arguments, or entered into a graphical text box, is first stored as a String. Java also
allows input of user data to be read character by character or in number of bytes
per read. Data input as a string or character is done to avoid input failure that may
result because of data type mismatch between user input and the program memory
type, where such input is stored. However, the programmer must parse the user
inputted String to get the numerical and character data, in which numerical data
may be used for program calculations. Java provides so called “wrapper classes”,
which have instance methods in them to parse a String object to its corresponding
numerical value. Later discussion of classes shows the advantages of using the
wrappers for the primitive data. A simple definition of wrapper classes is as follows:
The Java wrapper classes are used to convert a primitive data type into a Java
object. Table 2.4 shows the wrapper classes for all Java primitive data types.
Java Primitive Data Type Corresponding Wrapper Class9
byte Byte
char Character
short Short
int Integer
long Long
float Float
double Double
void Void
Table 2.4
All java wrapper classes are housed in package java.lang and are automatically
included in all Java programs. Understand that unlike C++, void is a valid data type
in Java. For example in C++ if a function does not have a return type, then a void
return type is assumes. Java will not allow omission of return type as void as return
data type must be used if no return is intended. We show examples of parsing user
input using wrapper classes for cases, where the data are entered from command
line and from JOptionPane dialog box. The later one is a graphical Java component,
which allows simple user input from a dialog box. JOptionPane is a class in the
package javax.swing, which must be explicitly imported in the Java program.

Parsing the numerical command line arguments


Java allows user to pass data to the program through command line used to activate
the Java program. The Syntax of running the Java program when command line
arguments are used is as follows. Assume that we have a Java program, where main

9
All wrapper classes need not have same type of parsing methods.

CS3 Java – Introduction to Java (Singhal) Page 21 of 52


method we run is included in class CommandLineArgs (Listing 2.3). Then the
command line arguments are passed to the program by using the following syntax:

>java CommandLineArgs Argument0 Argument1 Argument2 ……..

Invoking Name of
JVM class file to
be Argument list passed to the program.
executed! Argument0 is stored in array element
args[0] and so on.

The word java on comamnd line invokes the JVM to execute the main
method in class CommandLineArgs. All space separated entries after the class name
are considered command line arguments. Figure 2.12 shows as to how the command
line arguments are stored in the String array called args.

String array passed as command


line arguments to main method

Argument0 Argument1 Argument2 ……………

String array called args


FIG. 2.12

Listing 2.3 shows a toy example of parsing integer, and floating point command line
arguments into their numerical form. Let us assume that command line received the
following list of arguments:

John got 90 points with A grade and got gpa = 3.9 // Expression 1

CS3 Java – Introduction to Java (Singhal) Page 22 of 52


public class CommandLineArgs
{
public static void main(String [] args)
{
System.out.print(args[0]+ " " + args[1]);
1. static method parseInt of
String Input = args[2]; class Integer returns the int
int score = Integer.parseInt(Input); value of String Input. Input
is args [2].
System.out.print(" " + score + " " + args[3]+" " + args[4]
+" " + args[5]+" " + args[6]+" "
+ args[7] +" " + args[8]+" " + args[9]+ " ");
Input = args[10];

double gpa = Double.parseDouble(Input);


System.out.println(gpa);
2. static method parseDouble
} of class Double returns the
}//Listing 2.3 double value of String Input.
Input is args [10].

The expression1 passed as command line argument has 11 strings in it. Therefore it
will occupy array indices from zero to 10 in the String array called args. The
mapping of command line of expression1 with the args array shown in Figure 2.12 is
as follows:
Argument0 = “John” stored in args[0];
Argument1 = “got” stored in args[1];
Argument2 = “90” stored in args[2];
………………………………………
……………………………………….
Argument10 = “3.9” stored in args[10];

Notice that in above list, the score 90 read from command line is first stored as a
String and not as an int! It holds true for 3.9 as well. It is stored as a String. Now, if
we just needed to only print values “90” and “3.9”, then we may not need to parse
them into their corresponding numerical values as strings can be printed by the
print or println methods of PrintStream class directly (remember that out in
System.out is an object of type PrintStream). However, we cannot do any
meaningful arithmetic on a string. For example one may need to do some arithmetic
on the score received by John or on his gpa. That is when parsing is required.

CS3 Java – Introduction to Java (Singhal) Page 23 of 52


In expression1 passed to command line, when running program in Listing 2.3 has
args [2] as an int. Therefore the parseInt static method of wrapper class Integer is
used to extract numerical value of 90 from string ‘90”. The syntax of integer parsing
is shown by bubble1 in Listing 2.3. The parseInt method of wrapper class Integer is
a static method, which takes a String as an argument, and if the string is really an
integer, the method parseInt returns the corresponding numerical value of String
object passed to it as an argument. Then in Listing 2.3 we print this parsed value of
integer command line argument, which is the data score. The similar kind of
parsing is done for the last command line argument in expression1, where the 3.9 a
double data type is parsed by calling the parseDouble method of wrapper class
Double (bubble 2, Listing 2.3). The wrapper class Character can be used to parse
char data types entered on command line using a slightly different procedure
compared to int and double data. The output of Listing 2.3 remains same as the
command line argument input, as we did not modify numbers 90 and 3.9 in any way
before printing them back to console.

Using JOptionPane class for inputting user data


Java has a package called javax.swing, which contains a class called JOptionPane.
When the static method showInputDialog of class JOptionPane is called, the
program creates a dialog box in which user can enter data for the program input.
An example of this type of input is shown in Listing 2.4.
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Program file: MainJOptionPaneUse.java
import javax.swing.*;

public class MainJOptionPaneUse


{
public static void main(String [] args)
{
String Input = JOptionPane.showInputDialog(null, "Please enter the "
+" non-zero coefficient of X square in the quadratic equation" +
" Then either press the enter key or click on OK!");
double val_A = Double.parseDouble(Input);
System.out.println("The value you entered = " + val_A);
System.out.println("The square of value you entered is = " +
Math.pow(val_A,2));
System.exit(0);
}
}
//Listing 2.4
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
The DOS console picture for compiling and running the above program is shown in
Figure 2.13.

CS3 Java – Introduction to Java (Singhal) Page 24 of 52


FIG. 2.13
From the command line the program is run by typing: java MainJOptionPaneUse
and pressing the enter key. A graphical input dialog box shown in Figure 2.14 then
appears for user input.

FIG. 2.14
User enters a value of –5.4 and either presses the enter key or clicks OK. The DOS
console output shows the value entered by the user and its square. Let us review the
Listing 2.4 line by line. The line:
String Input = JOptionPane.showInputDialog(null, "Please enter the "
+" non-zero coefficient of X square in the quadratic equation" +
" Then either press the enter key or click on OK!");
displays the input dialog box in Figure 2.4. The line

double val_A = Double.parseDouble(Input);

assumes that user inputted a double data types in the dialog box of Figure 2.14 and
parses it into a double data type stored in memory val_A. Since val_A is a double
type value, the mathematical operations can be done on it. The line

CS3 Java – Introduction to Java (Singhal) Page 25 of 52


System.out.println("The square of value you entered is = " +
Math.pow(val_A,2));

Calls the pow static method of class Math and returns its square, which is printed
by the println method of PrintStream class. Some time to release the memory
occupied by graphical components such as a dialog box shown in Figure 2.14, an
explicit call to static method exit of System class is needed. This is accomplished by
the program line:

System.exit (0);

CS3 Java – Introduction to Java (Singhal) Page 26 of 52


Appendix 2.1: Java Keywords Defined

abstract

The abstract keyword can be used in the declaration of classes and methods. Use of
the keyword in a class declaration typically means that one or more of the methods
within the class body are declared as abstract. If the keyword is left off the class
declaration, and a method within the body of the class is declared using the abstract
keyword, then the class is implicitly defined to be abstract. In other words, the
keyword abstract need not be provided as part of the class declaration in this
circumstance, and the code will compile successfully. (For readability it is
recommended that abstract class declarations include the keyword to make the class
intention clear.)

Classes declared to be abstract cannot be instantiated. Instead, abstract classes force


the programmer to provide a body for each abstract method within a new derived
class. The following example shows a simple abstract class and a class derived from
it:

public abstract class FruitClass


{

public boolean isPeelable( );

.
.
.
}

public class BananaClass extends FruitClass


{

private boolean bPeel;

public boolean isPeelable( ) {


.
.
.
return bPeel;
}

The derived class (BananaClass) may be instantiated, and any non-abstract methods
of the abstract class (FruitClass) will be inherited unless they are overridden.

Note that a class declaration cannot use abstract and final.

The abstract keyword can also be used to define methods. As already shown above,
a class containing abstract methods is then also (either implicitly or explicitly)

CS3 Java – Introduction to Java (Singhal) Page 27 of 52


defined as abstract and must be subclassed in order to be instantiated. An abstract
method cannot have the implementation defined within the abstract class. Rather, it
is declared with arguments and a return type as usual, but the body that is enclosed
in curly braces is replaced with a semicolon.

Consider the following example declaration of an abstract method:

abstract public int someMethod( int arg1, int arg2);

Note that a method declared with the keyword abstract cannot be declared with the
keywords static, private, or final.

boolean

The boolean keyword is used to declare a primitive Java data type containing a
truth value. The two possible values of a boolean variable are true and false. Note
that true and false are defined as keywords in the Java language, but they are
actually literal values. Hence, the keywords true and false can be used as return
values, in conditional tests, and in assignments and comparisons to other boolean
variables.

The contents of boolean variables cannot be cast to or from other types; the current
value of a boolean variable can be converted to a string however.

The following code demonstrates declaration and assignment for a boolean variable:

private boolean isRunning;

isRunning = true;

break

The break keyword is used to define a break statement which, without a label,
transfers control out of the innermost enclosing while, do, for, or switch statement.
If the break statement includes a label and the statement is executed, control will be
transferred out of the enclosing statement to the line immediately following the label
declaration. (In this case, the break target need not be a while, do, for or switch
statement.)

The break statement also transfers control outside of try/catch blocks. Note that if
the break statement with a label is executed within a try or catch block, and an
associated finally block is defined for the try/catch block, then the contents of the
finally block will first be executed. After the entire finally block has executed,
control will once again transfer to the first statement immediately following the
label declaration.

The following example demonstrates a break statement used with a label:

CS3 Java – Introduction to Java (Singhal) Page 28 of 52


block1:{

recordsRemain = getUpdateStatus( );

while (recordsRemain)
{
if (isRunning)
System.out.println("Update another record");
else
break block1;
}
}

byte

The byte keyword is used to declare a primitive Java data type containing an integer
value in the range of negative 128 to positive 127. A byte is defined as 8 bits in
length, regardless of the platform the Java bytecode executes on.

Note that byte variables can be cast to and from other numeric types.

The following example demonstrates declaration and assignment for a byte


variable:

private byte stripThis;

stripThis = 64;

case

The case keyword can only be used within a switch statement block. It is used
repeatedly to provide any number of unique constants (or numeric labels) for
comparison within a switch statement block. If the case constant equals the value of
the expression at the top of the switch statement, then control is passed to the
statement immediately following the case statement. If, on the other hand, the
expression at the top of the switch statement block and the case label do not match,
control is passed to the next case for comparison.

In the event that no case constants match the value of the expression given at the top
of the switch statement, often a default case is provided.

catch

The catch keyword is used to introduce an exception-handling block of code. The


keyword is followed by an exception type, an argument name in parentheses, and a
block of code to execute should the specified exception actually occur. A try
statement and its corresponding block of code always precede a catch statement.

CS3 Java – Introduction to Java (Singhal) Page 29 of 52


When an exception is thrown within the corresponding try statement block, the
catch statement's exception type is evaluated to determine whether it is capable of
handling the exceptional condition. If the exception type can be handled, the
argument is assigned to the specified type and the code within the catch block is
executed.

char

The char keyword is used to declare a primitive Java data type containing a single
16-bit Unicode character in the range \u0000 to \uffff. Unicode characters are used
to represent a majority of known written languages throughout the world. (ASCII
characters make up a very small part of the Unicode character set.)

Note that values stored by char may be cast to and from other numeric types.
However, because character data is implicitly unsigned, casts of char to byte or
short can result in a negative number.

The following example demonstrates declaration and assignment for a char


variable:

private char hitChar;

hitChar = 'a';

class

The class keyword is used in the declaration of a new class. A class declaration
defines a new reference type (or object) and describes its implementation through
the use of constructors, methods, and fields. These implementation details can be
inherited from superclasses, or uniquely defined as part of the class declaration.

continue

The continue keyword is used in nested loops to define a continue statement, which,
without a label, transfers control to the end of the innermost enclosing while, do, or
for loop. Once control is passed, the current loop iteration ends and a new one
begins. If the continue statement includes a label and is executed, control is
transferred to the last statement of the outer loop. In this case, the continue target
label must point to a while, do, or for loop. (Contrast this with the labeled break
statement, where the target need not be a loop, or iteration, statement.)

Note that if the continue statement with a label is executed within a try or catch
block, and an associated finally block is defined for the try/catch block, then the
contents of the finally block will be executed first. After the entire finally block has
executed, control will once again transfer to the last statement of the loop
immediately following the label declaration.

CS3 Java – Introduction to Java (Singhal) Page 30 of 52


The following code demonstrates the continue keyword used with and without a
label:

block1:
for ( int i = 0; i < 10; i++ )
{
while ( statusOkay )
{
if ( someNum < 0 )
{
someNum++;
System.out.println("Do it again");
continue;
}

if (string1[i] == null)
{
System.out.println("null string here");
continue block1;
}
else
{
string2[i] = string1[i];
}
// continue statement without label points here
}
// continue statement with label points here
}
default

The default keyword can only be used within a switch statement block. It can be
used only once, and is typically located at the end of the switch statement block. The
default keyword is used to label statements that are to be executed by default. That
is, the default statement block is only executed when the result value of the switch
expression does not match any of the case labels within a switch statement block.

do

The do keyword is used as part of a do/while loop. Unlike the other, more commonly
used loop constructs, a do/while loop expression is evaluated only after the block of
code within its body has been executed. Thus, you are ensured that the code within
the loop body is executed at least once, even if the expression tested causes the loop
to end.

Note Don't forget that a semicolon is required after the condition in a do/while
loop.

The following code shows a typical do/while loop construct:

CS3 Java – Introduction to Java (Singhal) Page 31 of 52


int i = getValue( );

do
{
System.out.println("Printing at least once");
.
.
.
} while ( i <= 10 );

double

The double keyword is used to declare a primitive Java data type containing a 64-
bit floating-point number in IEEE 754 format. Variables of type double store values
in the range negative 1.7E308 to positive 1.7E308 within approximately 14
significant digits of accuracy. When you want a floating-point literal value to be
treated as a double, append the letters 'd' or 'D' to the end of the value.

Note that double variables may be cast to and from other numeric types. However,
doubles cannot be cast to or from values of type boolean.

The following example demonstrates declaration and assignment for a double


variable:

private double dCalcSet;

dCalcSet = 1.23d;
dCalcSet = 3e2;
dCalcSet = .25;

else

The else keyword is used to provide an alternative clause to an if statement. If the


expression defined by the if statement evaluates to false, then control transfers to the
first statement following the else keyword. If the expression defined by the if
statement evaluates to true, then control transfers to the first statement following
the if keyword.

Note that if/else conditional testing is a frequent source of program bugs. Consider
the following example of a poorly formatted if/else condition:

if ( numPrints < 1000 )


if ( paperFeed == fullTray )
{
printPaperCopy( );
showStatus( );
paperFeed--;
}
else
suspendPrintJob( ) // Bad indenting!;

CS3 Java – Introduction to Java (Singhal) Page 32 of 52


In the example shown above, the beginning of the else statement block is formatted
to fall into the same column as the outermost if statement, even though it's proper
association is with the closest if statement. Problems of this nature can be easily
overlooked unfortunately, and it is up to the programmer to use good formatting to
illustrate the logical intent of the code.

extends

The extends keyword is used in a class declaration to specify the direct superclass of
the class being declared. The superclass can be thought of as the class from whose
implementation the implementation of the current class is derived. The class being
declared is said to be the direct subclass of the class it extends. If no class is explicitly
defined as the superclass with the extends keyword, then that class has the class
java.lang.Object as its implicitly declared superclass.

When a class is extended, the class being declared has access to all the public and
protected variables and methods of it's superclass. Note that classes declared with
the keyword final cannot be subclassed.

The following example shows typical use of the keyword extends:

public class TransactionApplet extends Applet


{
//……………………..
}

false

The false keyword can be used as one of the two possible boolean values. Strictly
speaking, false is not a keyword of the Java language; rather, it is a literal value to
be assigned to a variable of type boolean.

final

The final keyword is used as a modifier for classes, methods, and variables.

When the final keyword appears in a class declaration, it means that the class may
never be subclassed or overridden. This prevents over-specialization of a particular
class. In some sense, the person who created the class considered any further
changes to be tangential to its primary purpose.

When the final keyword appears in a method declaration, it means that the method
may never be overridden. (Note that methods declared with the keywords static or
private are implicitly final.)

When the final keyword appears in a variable declaration, it means that the variable
has an assigned value that can never be changed.

CS3 Java – Introduction to Java (Singhal) Page 33 of 52


finally

The finally keyword is used to define a block of code following a try/catch exception
block. The finally block is optional, and appears after the try block and after any
catch blocks. The code in a finally block is always executed once, regardless of how
the code in a try block executes. In normal execution, control reaches the end of the
try block and then proceeds to the finally block, which typically performs any
necessary cleanup.

Note that if control leaves the try block because of a return, continue, or break
statement, the contents of the finally block are still executed before control transfers
out of the try block.

If an exception occurs in the try block, and there is an associated catch block to
handle the exception within the method, control transfers first to the catch block,
and then to the finally block. If there is not a local catch block to handle the
exception, control transfers first to the finally block, and then moves up the series of
prior method calls until the exception can be handled.

float

The float keyword is used to declare a primitive Java data type containing a 32-bit
floating-point number represented in IEEE 754 format. Variables of type double
store values in the range positive 3.40282347E+38 to negative 1.40239846E-45.
When you want a floating-point literal value to be treated as a float, append the
letters 'f' or 'F' to the end of the value.

The following example demonstrates declaration and assignment for a float


variable:

float fCalcSet;

fCalcSet = 1.23f;
fCalcSet = 3e2f;
fCalcSet = .25f;

for

The for keyword is used to create a loop construct. An initialization section, an


expression section, and an update section immediately follow the keyword. A
semicolon separates each section, and all appear together within at least one set of
parentheses.

The initialization section allows the programmer to declare one or more local loop
variables. Once the loop ends, these variables are no longer valid.

CS3 Java – Introduction to Java (Singhal) Page 34 of 52


The expression section contains an expression that is evaluated to determine
whether the loop should continue. A true result allows the loop to continue; a false
result allows control to transfer to the statement following the loop body.

The update section allows the programmer to increment loop counters or perform
other updates. Typically, the update section is used to increment or decrement
whatever loop counters the programmer defines.

The following example shows a typical for loop construct:

for ( int i = 0; i < 10; i++ )

if

The if keyword is used to execute a statement or block of statements when it's


associated expression evaluates to true. An if statement may also have an alternative
else clause. If the expression defined by the if statement evaluates to false, then
control transfers to the statement (or block of statements) following the else
keyword. If the expression defined by the if statement evaluates to true, then control
transfers to the first statement following the if keyword.

implements

The implements keyword is used in a class declaration to indicate that the class
provides an implementation for one or more interfaces. If more than one interface is
implemented within the class, the interface names must be separated by commas in
the declaration. The implements keyword must also follow the extends clause in the
class declaration.

The following example demonstrates use of the keyword implements in a class


declaration:

public class PotatoHead implements InterchangeableParts


{

}
import

The import keyword is used by Java to make classes available to the current file
using an abbreviated name. Any number of import statements may appear in a Java
program, but they must appear after the optional package statement at the top of
the file, and before the first class or interface definition in the file.

The following examples demonstrate use of the keyword import:

import my.package.*; // all classes in my.package are imported

CS3 Java – Introduction to Java (Singhal) Page 35 of 52


import my.package.cool; // only the cool class is imported from
//my.package

instanceof

The instanceof keyword is used as an operator that returns true if an object on its
left side is an instance of the class specified on its right side. The instanceof operator
will also return true when comparison is done with an object implementing an
interface. The instanceof operator returns false if the object is not an instance of the
specified class or does not implement the specified interface. It also returns false if
the specified object is null.

int

The int keyword is used to declare a primitive Java data type that contains an
integer value in the range of negative 2147483648 to positive 2147483647. An int is
defined as 32 bits in length, regardless of what platform the Java bytecode executes
on.

The contents of int variables can be cast to or from other numeric types.

The following example demonstrates declaration and assignment for an int variable:

private int iValueK;

iValueK = 1024;
interface

The interface keyword is used in the declaration of an interface. An interface can be


thought of as a template for a class that you may need to implement, but you don't
have to do all the design work yourself.

Interfaces differ from classes in the following ways:

• Interfaces cannot implement other interfaces. (They may extend other interfaces.)

• Interfaces cannot contain constructors, instance variables, class methods, or static


class initializers.

• All methods declared within an interface are implicitly declared to be public and
abstract. Methods within an interface cannot be declared as final, native, static, or
synchronized.

CS3 Java – Introduction to Java (Singhal) Page 36 of 52


• All variables declared within an interface are implicitly declared to be static and
final, and thus, must be assigned a constant value. Variables are also implicitly
public, and cannot be declared as either transient or volatile.

long

The long keyword is used to declare a primitive Java data type containing a value in
the range negative 9223372036854775808 to positive 9223372036854775807. A long
is defined as 64 bits in length, regardless of what platform the Java bytecode
executes on.

The contents of long variables can be cast to or from other numeric types.

The following example demonstrates declaration and assignment for a long


variable:

private long iLedgerBalance;

iLedgerBalance = 1234567890;

native

The native keyword is a modifier used in the declaration of a method to indicate


that the method is implemented in another programming language. Because a native
method is implemented outside of a Java program, the method declaration ends
with a semicolon rather than a method body.

Note that native methods cannot be declared with the keyword abstract.

new

The new keyword is used as an operator for creating a new object or array.

When new is used to create an object, it first creates an instance of the specified
class, then initializes all of the instance variables to their default values, and last
invokes the appropriate constructor for the class, depending on the arguments
provided in the argument list.

Using the new keyword to create a class object typically looks like this:

Button b = new Button("OK");

The new operator can also be used to allocate dimensional arrays for any numeric
or object type. Once an array has adequate space allocated, all the elements of the

CS3 Java – Introduction to Java (Singhal) Page 37 of 52


array are initialized to a default value, and it is then up to the programmer to
supply values other than the defaults.

Using the new keyword to create an array typically looks like this:

int array[] = new int[ 10 ];

null

The null keyword represents a special value that indicates a variable does not refer
to any object. The value null may be assigned to any class or interface variable to
aid garbage collection. (Assigning the value null to any of the items above indicates
to the garbage collection system that the object or variable is no longer in use.) It
cannot be cast to any other type, and should not be considered to have a known
numeric value.

package

The package keyword is used by Java to specify which package the code in the file is
located in. Java code that is part of a particular package has access to all classes in
the package, and all non-private methods and variables in those classes.

The package statement must come before anything else (except comments and
conditional compilation directives) in a Java file. If the package statement is omitted
from a Java file, the code in that file becomes part of an unnamed default package.

private

The private keyword is a modifier that can be used in the declaration of methods or
variables. (Note that the private keyword cannot be used in the declaration of local
variables.) Using the private modifier in the declaration for either of these types
hides the methods and variables so they cannot be directly referenced outside of the
class they're declared in. One exception to this rule is that private methods or
variables declared within a class can also be used by inner classes.

protected

The protected keyword is a modifier that can be used in the declaration of methods
or variables. (Note that the protected keyword cannot be used in the declaration of
local variables.) A protected variable or method is only visible within its class,
within its subclasses, or within the class package. Note that the subclasses may
reside within different packages, however.

CS3 Java – Introduction to Java (Singhal) Page 38 of 52


public

The public keyword is a modifier that can be used in the declaration of classes and
interfaces. (Note that the public keyword cannot be used in the declaration of local
variables.) The public keyword can also be used as a modifier in the declaration of
methods and variables. Classes or interfaces declared as public are visible
everywhere. Methods and variables declared as public are visible everywhere their
corresponding classes are visible.

Note that public classes must have a class name that exactly matches the name of the
.java file in which they appear.

return

The return keyword returns control to the invoker of a method or constructor. A


return statement used in a method can either return a value, or simply return to the
invoker without specifying a value. If a return value from a method is not needed,
the return keyword is followed immediately by a semicolon (rather than a value)
and the method's declaration must specify a return type of void. If a return value
from a method is needed, the method's declaration must specify a return type that
matches the type of value being returned.

Note that in constructors, return statements cannot return values.

short

The short keyword is used to declare a primitive Java data type containing a value
in the range negative 32768 to positive 32767. A short is defined as 16 bits in length,
regardless of what platform the Java bytecode resides on.

The contents of short variables can be cast to or from other numeric types.

The following example demonstrates declaration and assignment for a short


variable:

private short squareFeet;

squareFeet = 4600;

static

The static keyword is used as a modifier for methods and variables. The keyword
can also be used to define static initializing blocks.

When the static keyword appears in a method or variable declaration, it means that
there will be only one copy of the method or variable that each class object may

CS3 Java – Introduction to Java (Singhal) Page 39 of 52


reference, regardless of the number of instances of the containing class that are
created.

The static keyword can also be used to create a static initializing block of code that
runs only once, when the class object is first loaded into memory.

Strictfp

A modifier for the nonabstract java methods or nonabstract class, which when
applied will set a ACC_STRICT access flag set for the method in the class file. This
will allow for the fact that the intermediate results of a floating point operation do
not have to fit 32 or 64 bit size and can be larger than their final containment value.

super

The super keyword is typically used to access hidden variables or overridden


methods in a superclass. This keyword can also be used, along with an optional list
of arguments, as the first line in a constructor body to call a superclass constructor.

switch

The switch keyword is used along with the keyword case, and sometimes the
keyword default, to create a conditional statement. In a switch statement, the switch
keyword is followed by an expression within parentheses whose value must evaluate
to a primitive Java data type. Once the expression has been evaluated, its value is
compared against the label following each case statement within the switch
statement body. When a label has the same value, the lines following that case
statement are executed. An optional default label is included within the body of a
switch statement when there is no guarantee that the labels provided by each case
statement are the only values the switch expression may evaluate to.

The following example shows a typical switch statement construct:

switch ( someExpression )
{
case 1:
{
doCase1( );
break;
}
case 2:
{
doCase2( );
break;
}
case 3:
{
doCase3A( );
doCase3B( );

CS3 Java – Introduction to Java (Singhal) Page 40 of 52


}
default:
doDefault( );
}

The break keyword is also, at times, used within the body of a switch statement.
Once the lines following a case statement have executed, the break statement is
included to jump over the remaining body of the switch condition. Without a break
statement, subsequent case statements would continue being evaluated, and
eventually the default statement, if one were included, would execute.

this

The this keyword is used with instance methods and constructors to refer to the
current object. Use of the keyword this in the very first statement in the body of a
constructor means that another constructor in the same class is being called to assist
in creation of the object. For example:

public class MyClass


{

private long birthday;


private String name;

// first constructor
MyClass( String bDay )
{
birthday = formatBirthday( bDay );

// second constructor
MyClass(String nm, String bDay )
{ this ( bDay );

name = new String(nm);

}
}

Note The keyword this must appear as the first statement in the body of a
constructor, otherwise your code will not compile.

Use of the keyword this in an instance method is helpful when a variable using the
same name appears within the method body. For example, when you refer to a class
scope variable in a method containing the variable name x, the class scope variable
would be known as this.x.

CS3 Java – Introduction to Java (Singhal) Page 41 of 52


throw

The throw keyword is typically used within a try block to indicate that an
exceptional condition has occurred. The throw keyword is followed by an exception
object, derived from the class Throwable, indicating the type of exception being
thrown. A throw statement causes a program to immediately stop and resume at the
nearest catch statement that can handle the specified exception object. Hence, throw
statements may also be outside a try block, if the exception will be caught elsewhere
within the program.

The following example shows use of the throw keyword:

public void someMethod( int div ) throws Exception1


{
try
{
if ( div == 0 )
throw new Exception1( );
}
catch(Exception1 e1)
{
// Exception can be handled in this catch
// block
.
.
.
}
}
throws

The throws keyword is used in a method declaration to list any exceptions not
derived from Error or RuntimeException that a method can throw. (Exceptions
derived from type RuntimeException are typically avoidable. Exceptions derived
from type Error are usually related to serious system problems; thus, little can be
done about them.)

The following example shows a typical method declaration using the throws
keyword:

public int someMethod( int argument ) throws Exception1, Exception2


{
// This method may contain a try/catch block
// for detecting and possibly handling any caught
// exceptions.

CS3 Java – Introduction to Java (Singhal) Page 42 of 52


transient

The transient keyword is a modifier used in the declaration of variables. Use of this
keyword specifies that the current value of the variable need not be serialized (or
saved) along with other data stored in a class object.

The following example shows the declaration of a variable with the transient
modifier:

private transient int currentTime;


true

The true keyword can be used as one of the two possible boolean values. Strictly
speaking, true is not a keyword of the Java language; rather, it is a literal value that
is assigned to a variable of type boolean.

For an example of how the true keyword can be used, see the keyword boolean.

try

The try keyword is used to indicate a block of code in which an exception might
occur. For each try statement, there must be at least one corresponding catch clause.
If the exception occurs, the catch clause parameter is evaluated to determine
whether it is capable of handling the exceptional condition. If the exceptional
condition cannot be handled by any of the catch clauses corresponding to the try
statement, then control is transferred up the chain of method calls and all the
previous exception types are evaluated until one capable of handling the condition is
found.

Note that if the try statement has a corresponding finally clause, then the body of
the finally clause will be executed no matter whether the try block completes
normally or abruptly, and no matter whether a catch clause is first given control.

The following example shows a typical try/catch/finally construct:

try
{
// code within this block may cause an exception.
.
.
.
}
catch( Exception1 e1 )
{
// code within this block is executed only
// when an exception of type Exception1 occurs,
// otherwise it is skipped over.
.
.

CS3 Java – Introduction to Java (Singhal) Page 43 of 52


.
}
catch( Exception2 e2 )
{
// code within this block is executed only
// when an exception of type Exception2 occurs,
// otherwise it too is skipped over.
.
.
.
}
finally
{

// code within this block is always executed,


// regardless whether an exception within the
// try block occurs or not. This block is
// typically used for cleaning up.
.
.
.
}
void

The void keyword is used in the declaration of a method to indicate that the method
returns no value.

Note that Java provides only this very limited use of the void keyword. Unlike in the
C language, the void keyword cannot be used to declare the absence of method
parameters, void pointers, and so on.

volatile

The volatile keyword is a modifier used in the declaration of variables. Use of this
keyword specifies that the value the variable contains may change asynchronously,
and, therefore, the compiler should not attempt to perform optimizations with it.

while

The while keyword is used to create a loop construct. In a while loop, the expression
in parentheses immediately following the keyword is evaluated, and if the boolean
result is true, the statements appearing within the loop body are executed. If
multiple statements make up the body of the loop, they must be enclosed with curly
braces. Once the loop body has executed, control transfers back to the top of the
loop where the test is performed again, and the execution of the loop body is
repeated until the value of the expression evaluates to false.

The following example shows a typical while loop construct:

while ( i < 10 )

CS3 Java – Introduction to Java (Singhal) Page 44 of 52


{
// statements here execute if above expression is true
.
.
.
}

Appendix 2.2
The program below allows one to find the minimum and maximum value of certain
java primitive data type for a particular JVM implementation. The Screen shot
following the program gives the results of running this program. In this example the
Float class is used to get the sizes of float. Rest of the mapping is as follows:
Integer – int
Double – double
Short – short
And so on.
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public class JavaDataSizes
{
public static void main(String []args)
{
System.out.println(Float.MAX_VALUE);
System.out.println(Float.MIN_VALUE);
System.out.println(Double.NEGATIVE_INFINITY);
System.out.println(Float.POSITIVE_INFINITY);
System.out.println(Double.MAX_VALUE);

CS3 Java – Introduction to Java (Singhal) Page 45 of 52


System.out.println(Double.MIN_VALUE);
System.out.println(Float.NaN);
System.out.println(Integer.MIN_VALUE);
System.out.println(Long.MAX_VALUE);
System.out.println(Integer.MAX_VALUE);
System.out.println(Long.MIN_VALUE);
System.out.println(Short.MIN_VALUE);
System.out.println(Byte.MIN_VALUE);
System.out.println(Short.MAX_VALUE);
System.out.println(Byte.MAX_VALUE);
System.out.println(Boolean.FALSE.booleanValue());
System.out.println(Boolean.TRUE.booleanValue());
System.out.println(Long.MAX_VALUE + Long.MIN_VALUE );
System.out.println(Character.MIN_VALUE);
System.out.println(Character.MAX_VALUE);
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

CS3 Java – Introduction to Java (Singhal) Page 46 of 52


Questions
1. What is a byte-code?
2. What is a Java Virtual Machine (JVM)?
3. Explain as to why Java can fulfill “write once and run anywhere”
paradigm.
4. Write down the header of the method that must be included in a Java
program to execute the program.
5. What are the command line arguments?
6. What is the purpose of array of String that is used as an argument to
the main method (if included) in a Java class?
7. What is a compound statement?
8. Why would the Java code below not compile?
void print( )
{
System.out.println (“Hello from Print method”);
}
public class CallPrintMethod
{
public static void main(String [ ] args)
{
print( );
}
}
9. Why would the Java code below not compile?
int GlobalInteger = 10;
public class PrintGlobalInteger
{
public static void main(String [ ] args)
{
System.out.print(GlobalInteger);
}
}
10. Why would the Java Code below compile but will not run?
public class DoNothing{ }
11. Why would the two programs below give the same output, even
though the line including System.out.print is different in them?
public class HelloWorld{
public static void main(String [ ] args)
{
System.out.print (“Hello World”);
}
}
public class HelloWorld{
public static void main (String [ ] args)
{
java.lang.System.out.print (“Hello World”);

CS3 Java – Introduction to Java (Singhal) Page 47 of 52


}
}

12. A Java programmer whose name is John, likes his children so much
that he modifies the header of main method as follows:
public static void main (String [ [ JohnsChildren)
Do you think that John’s program with the modified header
for main method will still work? Explain your reason(s).
13. Which Java package is automatically included in every java program
and its explicit inclusion is not needed?
14. A Java programmer Tyron likes his Mom so much that on his
mother’s birthday, he saves the following Java class and program in a
file called HappyBirthDayMom.java. Will his program compile and
run? Assume that all the code lines inside the class below have no
compile and run time errors.
public class ComplexNumbers
{
//code that will compile
public static void main (String[]args)
{
//code that will compile
}
}
15. In the statement System.out.print (“Hello”); explain the followings:
A. What is System?
B. What is “out”?
C. What is print?
16. Which of the following company was responsible for development of
Java? (A) Microsoft (B) IBM (C) Sun Microsystems (D)
United States Air Force (E) Toyota Motor Company.
17. Java was developed in (A) 1990’s (B) 1940’s (C) 1920’s (D) 1890’s.
18. Will the following java program compile? If yes then what is the
output?
public class Class1{
public static void main (String/* This is needed*/ [] args){
System.out.println("Hello World");
}
}
a. Will compile and the output is:
b. Will not compile as Java does not allow inline comments.
19. Which one of the following is not a java keyword:
a. int
b. float
c. while
d. bool

CS3 Java – Introduction to Java (Singhal) Page 48 of 52


e. var
20. What will be the output of the following java program
class Class1{
public static void main (String [] args) {
int Integer=10;
Integer x = new Integer(10);
System.out.println("The sum is = " + Integer + x.intValue() );
System.out.println("The sum is = " + (Integer + x.intValue()));
}
}
a. The sum is = 20
The sum is = 20
b. The sum is = 1010
The sum is = 1010
c. The sum is = 1010
The sum is = 20
d. The sum is = 20
The sum is = 1010
e. None of above as program will not compile.

21. From the list of modifiers given below which one can be used for a locally
declared variable:
a. static
b. const
c. final
d. abstract
e. generic

Given below is the list of java keywords. Answer the question numbers 22 to 31
about this list.
List1
-----------------------------------------------------------------------------------------------
a. abstract, b. Boolean, c. break, d. byte, e. byvalue, f. case. g. cast, e. catch, f.
char, g. class, h. const, i. continue, j. default, k. do, l. double, m. else, n. extends, o.
false, p. false, q. final, r. finally, s. float, t. for, u. future, v. generic, w. goto, x. if, y.
implements, z. import, aa. inner, bb. instanceof, cc. int, dd. interface, ee. long, ff.
native, gg. new, hh. null, ii. operator, jj. outer, kk. package, ll. private, mm.
protected, nn. public, oo. rest, pp. return, qq. short, rr. static, ss. strictfp, tt. super,
uu. switch, vv. synchronized, ww. this,
xx. throw, yy. throws zz. transient, aaa. true, bbb. try, ccc. var, ddd. void,
eee. volatile, fff.while.
22. Which java keywords represent the primitives?
23. Which keywords represent the values of one of the java primitive?
24. Which java keyword if used must be the first uncommented keyword in the
java program?

CS3 Java – Introduction to Java (Singhal) Page 49 of 52


25. Which keywords relate to the control structures in java?
26. Which keywords are not used, but cannot be used as the identifiers?
27. Which three keywords are called visibility or access modifiers?
28. Which keywords cannot be combined with keyword public and vice versa?
29. Which keyword cannot be combined with keyword final?
30. Which are the only 3 keywords that can be used before declaring an outer
class?
31. Which is the only keyword that can be used as a modifier for a local variable
or object?

Given below is the list of java primitives. For question #32 to 37 mark the correct
answers from this list:

List 2.
a. int, b. float, c. double, d. short, e. char, f. byte, g. long, h. boolean

32. Mark the primitives that can have up to 16 bits size.


33. Mark the primitives that can have up to 32 bits size.
34. Mark the primitives that can have up to 64 bits size.
35. Mark the primitive that can have up to 8 bits size.
36. Mark the primitive that can only have two possible values.
37. Mark the primitive whose value cannot be cast to fit the other primitives.

Given below are the possible outputs that may be produced by some java code
fragments. For question numbers 38 to 55, indicate as to which code fragment will
produce which output.
List 3.
a. 3.4028235E38 b 1.4E-45 c. 1.7976931348623157E308 d. 4.9E-324
e. NaN f. Infinity g. -Infinity h. 9223372036854775807
i. 2147483647 j. -9223372036854775808 k. -2147483648 l. true m. -128
n. false o. 127 p. 32767 q. -32768 r. -1
Assume that the code structure is as follows and the structure of statement #1 is
different for each question from #32 to #38.
public class MyClass{
public static void main(String [] args){
statement #1 // See the various possible forms below
}
}
38. statement #1 is: System.out.println(Float.MAX_VALUE);
39. statement #1 is: System.out.println(Float.MIN_VALUE);
40. statement #1 is: System.out.println(Double.NEGATIVE_INFINITY);
41. statement #1 is: System.out.println(Float.POSITIVE_INFINITY);
42. statement #1 is: System.out.println(Double.MAX_VALUE);
43. Statement #1 is: System.out.println(Double.MIN_VALUE);
44. statement #1 is: System.out.println(Float.NaN);
45. statement #1 is: System.out.println(Integer.MIN_VALUE);

CS3 Java – Introduction to Java (Singhal) Page 50 of 52


46. statement #1 is: System.out.println(Long.MAX_VALUE);
47. statement #1 is: System.out.println(Integer.MAX_VALUE);
48. statement #1 is : System.out.println(Long.MIN_VALUE);
49. . statement #1 is : System.out.println(Short.MIN_VALUE);
50. . statement #1 is : System.out.println(Byte.MIN_VALUE);
51. . statement #1 is : System.out.println(Short.MAX_VALUE);
52. . statement #1 is : System.out.println(Byte.MAX_VALUE);
53. statement # 1 is : System.out.println(Boolean.FALSE.booleanValue());
54. statement # 1 is : System.out.println(Boolean.TRUE.booleanValue());
55. statement #1 is:
System.out.println(Long.MAX_VALUE + Long.MIN_VALUE );

56. What will be the output of the following java code snippets? The block of code
that differs is defined in answers a to h.
class Class1{
public static void main(String [] args){
//Block of code. See below for various possible code blocks
}
}
a. String x = null;
System.out.println(x);
b. String y= “null”;
System.out.println(y);
c. String x = null;
x+=x;
System.out.println(x);
d. String y= “null”;
y+=y;
System.out.println(y);
e. String x = null;
String y = "null";
y = y+x;
System.out.println(y );
f. Object y = null;
System.out.println(y );
g. Object x = null;
String y = new String();
y = (String)x;
System.out.println(y );
h. String x = null;
Object y = new Object();
y = (Object)x;
System.out.println(y );

CS3 Java – Introduction to Java (Singhal) Page 51 of 52


Make any notes below

CS3 Java – Introduction to Java (Singhal) Page 52 of 52


CS3 – Topic 3
Author: Satish Singhal, Ph. D.
Version – 1.0

Arithmetic Expressions, Type Conversions, Operators, Library


methods
In this chapter we attempt to accomplish the following goals:
Arithmetical Expressions – Construction and Evaluations
Precedence rules for Arithmetical Operators
Type Safety – Type coercion and Type conversion
Value Returning Functions in Java Program
Some Java Library Functions for Mathematical Applications
Void Functions
String Operations

Arithmetical Expressions – Construction and Evaluations


In a Java program, an expression is a valid arrangement of program variables,
program constants, and operators allowed by the language. We are familiar with
common arithmetical operators like plus (+), minus( - ), divide( / ), and multiply
( * ). Java arithmetical expressions can compute to the primitive data types that we
discussed in previous chapter. The arithmetical expressions in Java programs will
differ from normal arithmetical expressions in many ways. Let us take a simple
arithmetical expression for example:
X = 9 + y;
In normal arithmetic no attention will be paid to the data type of X. It could be a
whole number or a decimal number depending on the value of y. But in Java
program a data type will be assigned to X before the value of expression, found by
summing the right hand side, can be stored in the memory assigned to X. In this
expression we also use the plus arithmetical operator and an assignment operator.
Let us say few words about operators.

Operators
Operators operate on program variables to perform some operations. There are 3
types of operators in Java.
1. Binary operators: They operate on two variables or two expressions1. The
two variables or expressions are called operands. For example in expression
9 + 5, the 9 and 5 are operands and plus (+) is the operator. Binary
arithmetic operators are: plus (+), minus (-), division (/), multiplication (*),
and modulo or modulus (%).

1
In Computer Science a variable or constant is also at times called an expression. We may use the
name expression for an equation or for s single variable or constant.

CS3 Java – Arithmetical Expressions (Singhal) Page 1 of 58


2. Unary Operators: They operate only on one variable or expression. In
normal arithmetic, a plus, or a minus sign attached with a number can be
considered a unary operator. In Java, there are two other unary operators,
which we will discuss later on.
3. Ternary operators: Operate on 3 variables or expressions.
The Figure 3.1 summarizes the three kinds of operators that we can have.

Operand 1
Operand 2

FIG. 3.1
We will discuss more operators (like logical types) in future lectures. Java allows
the operators +, -, /, *, and % to be used for all integer and floating-
point data types as well as when operands for these operators are mixed
types. In Java these operators are not allowed to have boolean data
types as operands. For example the following line will give a compile error in
Java, but a similar expression in C++ will not2.
Compile error! boolean data types are
boolean data = true*false; not allowed to be operands to
arithmetical operators in Java!

Among arithmetic operators the division and modulus operators have some special
characteristics in Java. We therefore discuss them first.

Division (/)Operator
We are familiar with evaluations in normal arithmetic that 11/4 will be 2.75. But
will we get the same answer from our Java program? Let us run a short program
and see. Listing 3.1 below does that for us.

2
Corresponding expression in C++ would be:
bool data = true*false; // This will compile in C++.

CS3 Java – Arithmetical Expressions (Singhal) Page 2 of 58


public class PrimitiveDivisions1
1. Pure integer
{ division
public static void main(String [] args)
{
System.out.println ("According to Java 11/4 = " +11/4);
System.out.println ("However Java says that 11/4.0 = " +11/4.0);
System.out.println ("Of course in Java 11.0/4.0 = " +11.0/4.0);
System.out.println ("And also 11.0/4 = " +11.0/4);
}
}
2. Division includes one or more floating point number(s)

Listing 3.1
In above listing, we are asking the program to do four different divisions, 11/4,
11/4.0, 11.0/4.0, and 11.0/4. In a normal calculator operation all four will yield the
same results. But as shown by the program output below (Figure 3.2), first output in
this program will not be the same as would be shown by a calculator.

FIG. 3.2
Why is 11/4 = 2 and 11/4.0 or 11.0/4 or 11.0/4.0 = 2.75 in Java?
The reasons are as follows:
As we mentioned before that literal constants, like 11, 11.0, 4, 4.0 have an assumed
data types. When we enter a literal like 11, the program assumes it to be an integer.
But when we enter a literal as 4.0 then program assumes it to be a double. Therefore
the division operator looks at the data types of two operands and proceeds as
follows:
• If both numerator and denominator are integer data types, then division
operator carries out something called “Integer Division”. In integer
division only the number of times the denominator can fully divide the
numerator is reported. The remainder part is thrown away. For example in
case of 11/4, 4*2 = 8. So when we subtract 8 from 11, the remainder is 3. The
remainder is too small to perform another division by 4, so it is thrown away
in the integer division.
• However, if either the numerator or denominator is a floating-point type or
both are floating point types, then the division performed is normal
calculator type division, where remainder is turned into a fraction and added
to the integer division answer. Therefore the 11/4.0 and other divisions

CS3 Java – Arithmetical Expressions (Singhal) Page 3 of 58


where one or both operands are floating-point types, is 2.75, as we would
normally expect

Modulo(%) Or Modulus Operator


In modulus operation, the operand on the left hand side of modulo (%) is divided by
the operand on the right hand side and only the remainder from the division
operation is reported. In Figure 3.3 we show the results of modulus operator being
applied to two integers.

FIG. 3.3
In Java modulo operator can take any integral or floating-point types, as well as
mixed types as operands. For example can we get some thing meaningful out of
'z'%'A', 'Z'%2, 7.2%2.1, 11%4.2, or A%2.1? The Listing 3.2 below shows the
program and the results.
public class Modulus
{
public static void main(String [] args)
{
System.out.println ("The 11%4 in Java = " + 11%4);
System.out.println ("The 7.2%2.1 in Java = " + 7.2%2.1);
System.out.println ("The 11%4.2 in Java = " + 11%4.2);
System.out.println ("The A%2.1 in Java = " + 'A'%2.1);
System.out.println ("The \'z\'%\'A\'in Java = "+'z'%'A');
System.out.println ("The \'Z\'%2 in Java = "+'Z'%2);
System.out.println ("The 9.9%9 in Java = "+9.9%9);
System.out.println ("The 99.9%\'A'\' in Java = "+99.99%'A');

}
}

CS3 Java – Arithmetical Expressions (Singhal) Page 4 of 58


Listing 3.2
The results for the expressions involving floating point data would be approximate.
When arithmetical expressions involve a character literal (such as ‘a’, ‘W’, ‘5’),
then Java first converts the character into its integral ASCII value, and then
performs the necessary arithmetic. Let us analyze as to how we achieve some of the
above results. In performing a division or modulus example the ASCII values for z,
Z, and A and the computational results are given in Table 3.1.
Character ASCII ‘z’/’A’ = ‘z’%’A’ = ‘Z’/2 =90/2 ‘Z’%2 =
Value 122/65 122%65 90%2
Z 90
A 65 1 57 45 0
z 122
Table 3.1
Similarly, the plus (+), minus (-) and multiplication operators can be applied to all
integral and float types as well as mixed types.

Question: What will be the output of following Java code fragment? Would any of
the lines cause a compile error?
System.out.println('z'-'A'); System.out.println(145.6%’v’);
System.out.println('z'-2); System.out.println(true*false);
System.out.println('Z'*2); System.out.println('P'%23.4);
System.out.println('a'-'A');
Table 3.2

CS3 Java – Arithmetical Expressions (Singhal) Page 5 of 58


Evaluation of Arithmetical Expressions and Operator precedence
If we define variables such as:
Area_Of_Circle = Area of a Circle whose radius is “Radius”;
Circumference = Circumference of a circle of radius “Radius”.
Then the formulae for the area and circumference are given below
Area_Of_Circle = 3.14159*Radius*Radius;
Circumference = 2.0*3.14159*Radius;
If we define variables such as Radius, Area_Of_Circle, and Circumference as
floating-point types and use literal constants such as 3.14159, or 2.0 then we can see
here that these expressions have “data homogeneity”. That means that we did not
mix the integral and floating-point data types in above expressions3. Also apart from
assignment, the above two expressions had only a single arithmetical operator the
multiplication operator (*). Now we look at the more complex expressions, which
have more than one operator but they still have data homogeneity (no mixing of
integral and floating point data types).

Let us take an example where we mix one pound of water of zero degree
temperature with half pound boiling water. The goal is to calculate the average
temperature of the mixture. Let us define some program variables below, all being
assumed as double data types.

avg_temp = Final temperature of the mixture,


FREEZE_POINT = The Temperature of water about to freeze,
BOILING_POINT = The Temperature of Water about to boil.

Then a simple physics rule can tell us that if one-pound water with temperature
equal to FREEZE_POINT was mixed with half-pound water of temperature equal
to BOILING_POINT, then the temperature of mixture, avg_temp is given by
expression:

avg_temp = FREEZE_POINT + BOILING_POINT/2.0

In above expression on right hand side we have two binary operators the plus (+)
and the division (/). The question arises as to which operator will be resolved first.
Would the program do the operation FREEZE_POINT + BOILING_POINT first.
Or would it do BOILING_POINT/2.0 operation first. This issue is decided by
something called rule of operator precedence, which gives us information as to how
tight the operators bind in comparison to each other.

Figure 3.4 below gives us the precedence rules for some of the Java operators.

3
You may type the Circumference equation as Circumference = 2*3.14159*Radius;
meaning 2 to be an integer. But compiler takes that literal integer and widens it to a
floating-point type when the multiplication with 3.14159 is done.

CS3 Java – Arithmetical Expressions (Singhal) Page 6 of 58


Unary
Method call or forcing eval order

Same
preced-
Binary
ence

FIG. 3.4
We will discuss the method call operator later on, however, one must understand
that the pair of parentheses operator also forces the evaluation order as the
expressions in the innermost parentheses are evaluated first. We see from above
chart that after parenthesis, the unary operators have highest precedence and the
assignment the lowest. That means that among all operators the
assignment binds weakest. Therefore assignment will be done after all
other operators have been resolved. Operators between a pair of
horizontal lines have the same precedence. For example plus (+) and minus
(-) have same precedence. Operators with equal precedence bind with equal
tightness. The unary operators such as unary plus (+) and unary minus (-) apply
only to non-character literal constants or when assigning the value to a named
constant. The white spaces between the operands and operators in case of binary
operators are ignored. As we add more operators to the list shown in Figure 3.4, we
shall upgrade the Figure accordingly.

Operator Associativity
All Binary operators shown above associate from left to right. 4For example in
2%3*4 the scanning will be done from left to right. 2%3 will be evaluated first,
which is 2, and result 2 multiplied by 4, so final result is 8. Left to right associativity
requires scanning left to right. The Figure 3.5 below discusses left to right
associativity in more detail.

4
The unary negation (-) associates from right to left.

CS3 Java – Arithmetical Expressions (Singhal) Page 7 of 58


FIG. 3.5

Based on the rules surmised in the Figures 3.4 and 3.5 above, we can analyze that
how the operations will be performed in the expression

avg_temp = FREEZE_POINT + BOILING_POINT/2.0

Since operator divide (/) binds tighter than the binary addition (+) the first
operation performed will be BOILING_POINT/2.0. Let us assume that

Temp = BOILING_POINT/2.0

Then we see that binary addition (+) binds tighter than the assignment (=), therefore
FREEZE_POINT + Temp will be performed next. Let us assume that

RHS = FREEZE_POINT + Temp

Then finally the assignment will be made as

avg_temp = RHS

CS3 Java – Arithmetical Expressions (Singhal) Page 8 of 58


Let us take a look at the Listing 3.3 to see that how an expression having a mixture
of unary and binary operators is resolved. Would this program compile? It does and
the results are 0 for both y and z.
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public class Operators1
{
public static void main(String [] args)
{
int y = -5 - -5;
int z = -5 + - -5;
System.out.println ("-5 - -5 = " + y);
System.out.println (" -5 + - -5 = " + z);
}
}

Listing 3.3
For the first expression, reading from left to right unary minus has the highest
precedence and it associates from right to left. Therefore, a memory location is
created for first –5 and then for the second –5. Then in the second pass (again
reading from left to right) the binary minus binds tighter than the assignment
operator. Therefore second –5 is subtracted from first one. The result is 0 and is
stored into another temporary memory. Finally in the third pass (reading from left
to right) the memory location y is given a value of 0, which is the evaluated result of
the right hand expression.

The second expression in Listing 3.3 cannot be evaluated with out answering the
following question. In expression -5 + - -5, is the second minus sign from
the left a unary operator or a binary operator?
The compiler parses the above expression as follows:

-5 + (-(-5))

Therefore the last 2 minus signs are considered unary minuses


converting the second 5 to a positive number. The resulting sum is again
zero.

CS3 Java – Arithmetical Expressions (Singhal) Page 9 of 58


More Examples:
Let us look at expression

6*¾ *5

It has operators multiply (*) and divide (/), both of which bind with equal tightness
(same precedence) and both associate operands from left to right. Therefore
scanning from left to right, 6*3 is done first, which results in 18. Then scanning
again from left to right 18/4 is done next, which results in 4. Finally 4*5 yields 20.
Parenthesis has highest precedence among the operators shown in Figure 3.4.
Therefore using the parenthesis can alter the order of evaluations. For example the
expression 6 *(¾)* 5 will evaluate differently. Because of parenthesis having
highest precedence, the ¾ will be evaluated first. The result is 0. The 6*0 is 0 and
finally 0*5 is 0. Therefore be very careful in applying the operators and understand
the rules of precedence thoroughly. Slight change and placement of parenthesis can
change the value of expression drastically. We will do few more expressions after we
have understood type coercion and type conversion clearly. But let us see few more
examples right now:
Error! Not a valid link.
Evaluate the following expressions

7 * 10 –5 %3 * 4 + 9
Additional use of parenthesis is shown by the following presentation.
Error! Not a valid link.

CS3 Java – Arithmetical Expressions (Singhal) Page 10 of 58


Increment and decrement operators
There are operators in Java, which allow one to increment or decrement the value
of an integral or floating-point variable by one. The increment is performed by
appending a pair of plus (+) sign to the variable name, whereas in decrementing a
pair of minus sign (-) is used. Operator name and its action on the variable depend
upon whether increment/decrement operator is appended before the variable name
or after it. When a ++ sign is appended before the variable name, it is called a pre-
increment operator.

int val = 5; Pre-increment


++val; operator.

Table 3.3 shows the syntax and meaning of four increment and decrement
operators.
Operator Syntax Name Action
++val Pre-increment Increase value of val by one and store in
val
++ val++ Post-increment Increase the value of val by one after the
current action involving val is complete.
--val Pre-decrement Decrease value of val by one and store in
val
-- val-- Post- Decrease the value of val by one after the
decrement current action involving val is complete.
Table 3.3: val could be any integral or floating point type

When the pair of plus sign is appended to the front of a variable name, it is called
pre-increment operator. When it is appended to the end of variable name it is called
a post-increment operator. When a pair of minus sign is appended to the front of an
operator, it is called a pre-decrement operator, and it is called a post-decrement
operator when it is appended to the end of a variable name (Table 3.3). Let us first
observe as to what changes are made to the storage location (such as val in Table
3.3) when pre-increment and pre-decrement operators are applied. The Figure 3.6A
shows this action

CS3 Java – Arithmetical Expressions (Singhal) Page 11 of 58


Pre-Increment/Decrement
Operators in Java
int val = 5; 5
val

++val; 6
val

--val; 5
val
FIG. 3.6A
In first line of the code fragment in Figure 3.6, a storage location val is created and
int five is stored in it. The second code line;

++val;

increases the stored value to 6. Then the third code line;

--val;
decreases the stored value back to 5. Meaning of pre-increment or pre-decrement
operations is clear. In these operations the value stored at the variable location must
be modified (increased or decreased) by one, before variable can be used for any
other purpose. The application of post-increment and post-decrement operators
requires that the variable value be changed, after the current action on it is
completed. . Listing 3.4 would clarify as to how the pre and post operators affect
variable values.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public class PrePostFixOperators
{
public static void main(String [] args)
{
int val = 5;
System.out.println ("Current value of val = " + val);
System.out.println ("The operation ++val sets val = " + ++val);//line 3
System.out.println ("The operation --val sets val = " + --val);//line 4

CS3 Java – Arithmetical Expressions (Singhal) Page 12 of 58


System.out.println ("The operation val++ does not print a different"
+ " value for val and val = " + val++);//line 6
System.out.println ("But if we print val now, then val = " + val);//line 7
}

}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

Listing 3.4
In Listing 3.4 on line #3 we print the value of variable ++val. Since a pre-increment
operator is used the value of val is increment before it is outputted to the console.
The output shows that the val is increased to six before it is printed to the console.
In line #4 the value of variable –val is printed. The outputted value of five shows
that the value of val is decremented by one before it is outputted.

Situation is different, however, when in line #6 we output value of val++. The output
shows that the value of val printed to console is no different than the previous
output. This expected because the post-increment operator only increases the value
of val, after its current value (five) is outputted. However, if we print the val after
the operation val++ is allowed to complete (line #7) then we get an incremented
value of six. The pre-increment or pre-decrement operators are also given a generic
name called pre-fix operators. Similarly the generic name for post-increment and
post-decrement operators is post-fix operators. When the variable is to be used as a
stand-alone variable, one is free to use pre-fix or post-fix form. However, as seen
from Listing 3.4, when variable is used in some way, then pre-fix operator would
work on the variable before its use, and post-fix after its use. Figures 3.6B and 3.6C
show additional examples as to how the use of pre-fix and post-fix forms alters the
program results.

CS3 Java – Arithmetical Expressions (Singhal) Page 13 of 58


Figure 3.6B use of pre-increment increases num by one before
multiplying with three
Figure 3.6B shows that pre-incrementing num increases it by one before the
multiplication operation takes place, resulting in a value of 42 for alpha.

FIG. 3.6C

CS3 Java – Arithmetical Expressions (Singhal) Page 14 of 58


On the other hand if num is post-incremented and then multiplied by three, then
alpha has a value of 39, because the num is incremented after its use in the
calculation for alpha value (Figure 3.6C).

We would like to caution you that it is never advisable to use increment


and decrement operators inside the expressions and method calls, the
way we have done in Listing 3.4 and in Figures 3.6B and 3.6C. That is
patently a bad-programming practice. We have used these examples
only to illustrate the meaning of post-fix and pre-fix operators. In actual
code writing one must use pre or post fix operators prior to or after
using the variables in arithmetic expressions or in method calls.

Precedence and associativity for pre and post fix operators


Java language specification (JLS) does not give an operator precedence chart.
Rather it is stated that operator precedence rules must become clear from the
narrative in the specification. Therefore, horrible confusion exists in Java literature
as where to place pre and post fix operators in the operator precedence chart. The
common agreement is that of course they have higher precedence than all the binary
arithmetical operators. In fact JLS discusses the use of postfix operators as
expressions, separate from unary operators thus granting them a different status.
However the pre-fix operators are called the unary operators and they are given the
same precedence as the unary negation or positive. Taking our clue from JLS, we
for now, do not include post-fix operators in the operator precedence chart and use
another Java guarantee for their evaluation when they are used in the arithmetical
expressions. This Java guarantee is called “order of evaluation”. Before we
discuss the order of evaluation, however, we would like to provide the modified
form of Figure 3.4, which includes the pre-fix operators. The modified operator
precedence table is shown in Figure 3.7.

CS3 Java – Arithmetical Expressions (Singhal) Page 15 of 58


Operator Description Associativity HIGHER
Method call or forcing
( )
evaluation order

- Unary Negation
++ Pre-Increment Right-to-Left
-- Pre-Decrement

* Multiply
/ Divide Left-to-Right
% Modulus

+ Plus
Left-to-Right
- Binary Minus

= Assignment Right-To-Left LOWER


FIG. 3.7
Order of Evaluation
In JLS Java designers state “The Java programming language guarantees that the
operands of operators appear5 to be evaluated in a specific evaluation order, namely.
From left to right”. What that means is that left hand operand of a binary operator
appears to be fully evaluated before any part of right hand operand is evaluated.
Take the Listing 3.5 for example. It must give output for j = 9 and b = 12.

5
The word “appear” may have been used, because an exception may be thrown prior to the
completion of any evaluation, thus terminating the program abruptly. We shall discuss exceptions
and their handling in subsequent chapter.

CS3 Java – Arithmetical Expressions (Singhal) Page 16 of 58


/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public class OrderOfEval
{
public static void main(String [] args)
{
int i = 2;
int j = (i=3)*i; // Line #1
System.out.println (j);
int b = 9;
b = b + (b=3);//Line #2
System.out.println (b);
}
}//Listing 3.5
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Both examples (Line #1 and 2) in Listing 3.5 have an unspecified behavior in C
language. However, Java guarantees that in line #1 of above code i is set to 3 before
the multiplication operator is applied. Similarly, in line #2, B is set to 3 after its
value of 9 has been saved to perform the addition.
Question: What would be the output for j if the line #1 in Listing 3.5 is altered as
follows:
int j = i*(i=3);

Another related guarantee from Java (stated in JLS) is that every operand of an
operator (except the conditional operators6) appears to be fully evaluated before any
part of the operation itself is permitted. The significance of both above Java
guarantees will become clear soon with few examples. Take for example the code
snippet:

int x= 6;
System.out.println (x++ + ++x);

The above code produces an output of 14, because evaluating from left to right, first
the current value of x (=6) as one of the operand is saved for the binary plus
operation. Then since Java guarantees that each operand of an operator must be
fully evaluated before the operation is performed, the post-increment is done on x,
raising its value to 7. Then since the right operand must be evaluated as well, the
pre-increment increases the value of x to 8. The operands are thus 6 and 8, sum of
which is 14. In evaluating the expression in code snippet above we used the
precedence rule that unary ++ has a higher precedence than binary +. However, the
behavior and application of post-increment operator ++ is deduced from Java
guarantee that all operands of an operator be fully evaluated before performing the
operation. A more complex code snippet is given below:

6
Conditional operators are &&, ||, and ? :, which will be discussed later.

CS3 Java – Arithmetical Expressions (Singhal) Page 17 of 58


int y = 6;
System.out.println( ++y + (10 * y++ ) );

The output of above code snippet is 77. This is because, following the evaluation
order left to right; left operand ++y must be evaluated fully, which sets y = 7. The
right operand is parenthesized and involves a postfix operation on y. Therefore the
current value of y is used, giving 10*7 = 70. Performing plus operation will give a
result of 77. However, the post-increment is then done on y and its value is set to 8.
The incremented value of y does not affect the output here. What if we altered the
above code slightly as below?

int y = 6;
System.out.println( y++ + (10 * ++y) );

The output now changes to 86 because of the left to right evaluation order and full
operand evaluation before the operation. Scanning from left to right, the current
value of y = 6, which is saved to be used as the left operand before the plus operator.
However, the next operation on y is a pre-increment. Therefore the post-increment
++ is done before the next operation of pre-incrementing can be done. This sets the
value of y = 7. In evaluating the right operand of +, which is 10*++y, the pre-
increment must be done before multiplication can be done. Indeed here we do use
the rule of operator precedence shown in Figure 3.7, which shows unary pre-fix
operation having a higher precedence than the binary multiplication. The pre-
increment in the expression 10*++y, sets the y = 8. Thus 10*++y evaluates to 80. The
sum of saved value of left hand operand (=6) and right hand operand (80) gives us
an answer of 86.

Once again we warn user to not write code, the way we have shown in
code snippets on last page. All pre and post-fix operations must be done
before or after the variables are used in the expressions or making the
method calls!

Compound Binary Operators in Java


Java provides many compound binary operators; description of some of them is
given in the Table 3.4 below.

CS3 Java – Arithmetical Expressions (Singhal) Page 18 of 58


Operator Description Example
(Space is not
allowed between
the operator
symbols)
+= Addition and then int Val =5;
assignment int Num = 10;
Val+=Num;
Value stored in Val is 15.
+= Addition then assignment String Name1 = “John”;
for a String String Name2 = “ Doe”;
Name1+=Name2;
Name1 stores “John
Doe”
-= Subtraction and then int Val =5;
assignment int Num = 10;
Val-=Num;
Value stored in Val is -5.
*= Multiplication and then int Val =5;
assignment int Num = 10;
Val*=Num;
Value stored in Val is 50.
/= Division and then int Val =5;
assignment int Num = 10;
Val/=Num;
Value stored in Val is 0.
%= Get modulo and then int Val =5;
assignment int Num = 10;
Val%=Num;
Value stored in Val is 5.
All compound operators associate from right to left. All of them have
lowest precedence (lower than simple assignment). In Figure 3.7, the
compound operators will be placed at the bottom.
Table 3.4
Question:What will be the output of the following code snippet?
int val = 9;
val+=(val=3);
System.out.println (val);

CS3 Java – Arithmetical Expressions (Singhal) Page 19 of 58


Type coercion Or Implicit type conversion
We saw in the example of Listing 3.1, that Java correctly evaluated the mixed type
expression 11/4.0 to be 2.75. In doing this evaluation Java first converts the int 4 to a
double 4.0, and then it performs the division between two double type numbers.
This process, where Java does the type conversion on the fly is called type
coercion or automatic type conversion or implicit conversion. While
performing the automatic type conversion in evaluating the right hand side of an
arithmetical expression, Java ascertains that the final result is of the data type
whose range is large enough to hold the value of the evaluated expression. When
operands of binary arithmetical operators are of mixed type, then Java
automatically widens the operand of the lower data range to match the operand of
the higher data range. For example in evaluating 11/4.0, the 11 an int (lower range),
is automatically widened to double 11.0 (higher range). Thus in binary arithmetical
operation the final value is of type of the highest storage range of the operands
involved. This process is also called “numeric promotion”. Java performs this
automatic numeric promotion (in evaluating the right hand side of an arithmetical
expression) based on the ranking of data types given by the chart in Figure 3.6. Such
automatic conversion is also sometimes called as “widening conversion”, as in
doing so, the datum of lower range is automatically widened to the datum of higher
range.

Though char is 2 bytes


and byte is 1 byte, they
have the same highest
value of 127. (For char
we are using Unicode
FIG.3.6 system).
Notice that, when executing the code fragment7 such as:

7
For whole literal numbers, Java uses an assumed data type int, whereas for non-whole literal
numbers the assumed data type is double. The L and F are needed though not always required to
specify data types other than the assumed types. L indicates that data type of the whole literal
number be taken as long and F indicates to take the data type of non-whole number to be of type
float.

CS3 Java – Arithmetical Expressions (Singhal) Page 20 of 58


long my_long = 2456L;
float my_float = 2.998F;
System.out.println (my_long*my_float);
the data type of expression my_long*my_float will be of type float and not long,
even though long data type is eight bytes and float is only four bytes. This is because
the range of float data type is large enough to contain the range of long data type.
Therefore in applying the binary arithmetical operator to the operands, the
conversion is done based on the range of data type, and not based on its byte value.

Automatic type conversion during assignment operation


Java uses almost the same system as described above, when assigning the evaluated
results of an arithmetical expression to store in a memory location. Another way to
show the chart of Figure 3.6 is depicted in Figure 3.7.

FIG. 3.7

CS3 Java – Arithmetical Expressions (Singhal) Page 21 of 58


Figure 3.7 indicates, that if the right hand side of an expression evaluates to the type
shown in an inner rectangle, then the result can be stored into the memory of the
type of any of its outer rectangles. For example if the final result of a calculation is
of type short, it can be automatically stored into the memory types int, long, float,
and double.

In order to understand the automatic type conversion or type coercion during


assignment, let us first take an example where type coercion does not take place. See
the code fragment below (Figure 3.8):
No type coercion
8.5 because both a and b
//*********************************************************
double a; are double type storage
double b; 9.37 locations, and 8.5, 9.37
a = 8.5; are also double types.
b = 9.37;
//*********************************************************
FIG. 3.8: No Type conversion needed.
This is the example where, the declared data type matches the value provided on the
right hand side8. The compiler has no problem in making this assignment because
the data type on both sides of the assignments operator match exactly.

But let us take a look at next code fragment, where storage wise things are a bit
different.
//*********************************************************
double my_double; Value undefined
Type
my_double= 8;
Coercion
int 8 is coerced into double type
8.0 and is stored.
//*********************************************************
FIG 3.9: Automatic type conversion or type coercion needed.

In Figure 3.9, first a double type of memory called my_double is created. However,
since no assignment is made, the value stored is undefined. In the next line
assignment my_ double = 8 is made. Since 8 is int type (lower range), compiler does
an “Implicit type coercion (therefore conversion) for you and stores the value 8.0 in
the storage location my_double and widens the datum to double data size (wider
range). This type conversion is implicit because we did not tell compiler to do it.
Such conversion is another example of Widening Conversion discussed earlier.

Following facts can be summarized for widening conversion.

8
Recall that the assumed data type for floating point literals in Java is of type double.

CS3 Java – Arithmetical Expressions (Singhal) Page 22 of 58


• When a binary operator has mixed data type on its two sides, then Java
automatically does the type conversion by widening the low range operand to
the level of high range operand.
• In storing a value in a memory location if the right hand side of the
expression evaluates to a data type of lower range, compared to the storage
location on left hand side, then the former is automatically widened to match
the size of storage location.
• Widening conversion is safe as no loss of information takes place in widening
a low range data into a high range state and possibility of inaccurate results
is minimized.
• In some widening conversions, such as assigning a long to a float storage
location, some loss of precision may take place, as in floating point format;
the numbers are not stored accurately. Listing 3.6 shows an example of such
loss of precision.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public class PrecisionLoss
{
public static void main(String [] args)
1. An integer is stored in
{ memory called big.
int big = 1234567890;
2. The value of int big is
assigned to the float type
float approx = big; storage location. The compiler
will accept this because range
of float is large enough to hold
all int values.

3. From int big we


subtract the whole
numbers stored in the
System.out.println (big - (int) approx);
}
float storage approx.
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4. The output of Listing
3.6.

Listing 3.6
In Listing 3.6, first we assign create an int called big with a value 1234567890
(bubble#1). Then we assign the value of big to a float storage called approx (bubble
#2). Java will compile this because in data ranking (Figure 3.6, 3.7) float ranks
higher than int. Then we subtract from big the whole number portion of approx
(bubble #3), and print the result. The output, -46, suggests that there was a loss of

CS3 Java – Arithmetical Expressions (Singhal) Page 23 of 58


precision when int, big, was stored in the float approx (bubble #4). We will discuss
shortly that the meaning of expression:

(int)approx

is simply that from approx discard the fractional portion and extract only the whole
numbers.

Question:
What will be the result of the following expression? Is the final result floating point
type or Integer type? Is there any widening conversion in this expression? If yes
then explain as to what value is being widened to what type? Is this expression safe?
10.0 / 3.0+5 * 2

Question
What will be the result of the following expression?
55.112 + 'z'%'B' + ','/1.9
Indicate as to what values are being widened to what? Is this expression safe?

Implicit(Automatic) Narrowing conversion


The purpose of Java’s automatic data conversion is that no loss of information shall
take place. Widening conversion is always safe as a lower range datum is stored in a
higher range storage location9. However, Java allows some safe automatic
“narrowing conversions” as well, where the loss of information does not take place.
We indicated earlier that in Java the assumed data type for whole literal numbers is
of type int, and for non-whole literal numbers is of type double. Therefore in
assignment:
No compile error, as value 120 though
byte my_byte = 120; an int, is lower than the maximum
limit of byte type memory.

the whole number 120 is of type int, but the storage location, where the number is
being stored my_byte, is of type byte. In making this assignment, Java will
effectively convert number 120 from type int to type byte, and then in location
my_byte, the “narrowed” 120 is stored. Java allows this storage and assignment
because the number being stored is lower than the maximum limit of byte type
memory. Such “narrowing conversion” is safe and is done automatically. However,
the following will cause the compile error in Java:

byte my_byte = 300; Compile error, as value 300 is higher than


the maximum limit of byte type memory.

9
As shown in Listing 3.4, this at times may not prevent the loss of precision, however.

CS3 Java – Arithmetical Expressions (Singhal) Page 24 of 58


When programmer tries to store a value 300 in the memory of type byte, then Java
issues a compile error because there is no safe way to store 300 into the byte type
memory. This unsafe narrowing conversion is declined by Java and a compile error
is issued. We can reach the following conclusion from above discussion. Java will
do automatic type conversion or type coercion during assignment and
during evaluation of an arithmetical expression, as long as no loss of
information during such process takes place. A compile error is issued if
loss of information is detected. In safe automatic type conversion – both
widening and narrowing conversions may take place.

Explicit Type Conversion or Type Casting


All examples we have shown so far were, where the type coercion either by
narrowing or by widening is done implicitly. It was implicit because we let compiler
decide as how it will handle the expressions that had mixed data types in it. At
times, either for the purpose of executing special algorithms, or for creating easy to
read code, one may need to actually convert one type of primitive into another
type10. Java provides the mechanism for programmer controlled explicit type
conversion, which is also called type casting. Listing 3.6 showed one example of type
casting, where the float was cast into an int. In type casting a data type reserved
word inside the parenthesis is used to cast the value of the argument to the right of
parenthesis. Figure 3.10 shows an example where programmer does an explicit
narrowing conversion from double to int.
//*********************************************************
int my_int; Value undefined
my_int= (int) 8.5; Explicit
8 is stored Type
Casting
//*********************************************************
FIG. 3.10: Example of Explicit narrowing conversion and type Casting

The Figure 3.10 does the narrowing conversion but makes it explicit, thus making
code more readable, and allowing for a modification, should such conversion lead to
inaccurate results. Some examples of explicit type casting are given in the Figure
3.11 below.

10
boolean primitive cannot be converted to any other type. Reverse is also true.

CS3 Java – Arithmetical Expressions (Singhal) Page 25 of 58


First
evaluates
5.0f integer
expression
7/4 to int
1.0f value 1

1.75f
Then
widens
1 to 1.0f
First widens 7 to 7.0f and 4 to 4.0f and then
performs the float division.
FIG. 3.11
Most of the results of Figure 3.11 are self-explanatory. The operation (float)7/4
will
also give 1.75f because first 7 will be converted explicitly to 7.0f, and
then implicit type coercion will widen 4 to 4.0f, thus 7.0f/4.0f giving
1.75f.

Understand that Java will give a compile error if one would use the C++ style of
type casting given below.
Acceptable in C++ but compile error
int val = int (4.8); in Java.

One may use a form of type casting which will work both in Java and C++. This is
shown below.
Will work in both, Java and C++.
int val = (int)(4.8);
Explicit Type Casting as a Part of problem solving algorithm
Let us see one more example of explicit type casting, where we use the type casting
mechanism to round off currency numbers to nearest cents. Let us say that you
went to supermarket and you bought Cabbage and Oranges. Then you would need
to pay for 2 items and let us say that variables declaring their costs are (Figure
3.12):

CS3 Java – Arithmetical Expressions (Singhal) Page 26 of 58


//*********************************************************
double Cost_Of_Cabbage = 0.0;
double Cost_Of_Oranges = 0.0;
//*********************************************************
FIG. 3.12
Let us assume the price of cabbage per pound is $0.51 and you bought (for your big
party) 24.2 pounds of cabbage. Then cashier’s calculator calculates your cost of
cabbage to be
Cost_Of_Cabbage = 0.51*24.2;
Cost_Of_Cabbage = 12. 342 // $12.342
Then you buy oranges, which are $0.98 per pounds and for all the orange lovers in
your party you buy 12.6 pounds of oranges. So your cost of oranges is calculated to
be
Cost_Of_Oranges = 0.98*12.6;
Cost_Of_Oranges = 12.348 // $12.348
Now if you go to the kind of stores I end up with, they will round off both (for me
any ways) $12.342, and $12.348, each to $12.35 and I will end up paying $24.70(a
penny more than I should have to). But let us say you go to some better store and
they ask you – Mr. Computer programmer, can you write a program for me, so that
it will automatically do rounding off for me so that any thing less than $0.005 gets
dropped and any thing more than $0.005 and less than $0.009 gets rounded off to 1
penny? (And they give you 5% discount on your grocery bill for writing this
program). So you put your computer programmer hat on and you come up with this
algorithm:
1. Prompt to enter the price per pound (Price_Per_Pound)
2. Get/store price per pound in dollars
3. Prompt to enter weight of product (Weight)
4. Get /store weight
5. Calculate the total price (Total_Price = Price_Per_Pound * Weight)

Now since you are supposed to round off to a penny, you might as well get the
cost in pennies first.
6. Calculate cost in pennies (Cost_In_Pennies = Total_Price*100)

Now here is the crucial step. If fractional penny is less than 0.5 then you want it
to drop but if it is 0.5 or more then you wish it to round off to 1 penny. (We do
not care about the 1/100th part of a penny). So what you do is that you just add
0.5 penny to the Cost_In_Pennies calculated in step 6. If penny at the first
decimal place was 0.5 or more then adding 0.5 penny will add 1 penny and some
fraction to the total. (Example 0. 62 + 0.5 = 1.12). But if penny at the first
decimal place was smaller than 0.5, than adding 0.5 penny will graduate it to no
more than 0.9 at that decimal place. So step 7 is:

7. Add 0.5 penny to the Cost_In_Pennies (Cost_In_Pennies = Cost_In_Pennies +


0.5)

CS3 Java – Arithmetical Expressions (Singhal) Page 27 of 58


So it is clear that if you add 0.5 penny to your cost calculated in step 6, then if
the fractional penny was 0.5 or more, the cost will increase by a full penny,
otherwise it will not. So now only if we can drop whatever penny is left at the
first decimal point, then we are done. At least we will get the cost rounded off to
the first penny. This is where you can use your newfound knowledge of explicit
type casting. You know that if you use the int operator on a float data the
narrowing conversion drops the fractional part of the float and only stores the
full part. So step 8 becomes:
8. Cost_In_Pennies = (int)(Cost_In_Pennies)
9. Convert Cost_In_Pennies back to dollars
Total_Price = (float)(Cost_In_Pennies)/100
10. Display Total_Price
11. End the program
Listing 3.7 below gives the coded algorithm.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
import javax.swing.*;
public class ExplicitConversiosn2
{
public static void main(String [] args)
{
final int Dollar_Penny_Conv_Const = 100;
double Price_Per_Pound = 0.0;
double Weight = 0.0;
double Total_Price = 0.0;
double Cost_In_Pennies = 0.0;
String Input = JOptionPane.showInputDialog(null,
"Please enter the price per pound in dollars: ");
Price_Per_Pound = Double.parseDouble(Input);
Input = JOptionPane.showInputDialog(null,
“Please enter the weight of product in pounds: ");
Weight = Double.parseDouble(Input);
Total_Price = Price_Per_Pound*Weight;
Cost_In_Pennies = Total_Price*Dollar_Penny_Conv_Const;
//Modify to next penny by adding 0.5
Cost_In_Pennies = Cost_In_Pennies + 0.5;
//Do explicit narrowing conversion to drop decimal
//pennies
Cost_In_Pennies = (int)(Cost_In_Pennies);

Explicit narrowing conversion


//Convert back to dollars
Total_Price = Cost_In_Pennies/Dollar_Penny_Conv_Const;
System.out.println("The cost you will pay is = $"+Total_Price);
System.out.println ("Please run the program again to round off” +
“another cost, otherwise have a great day.");
System.exit(0);
}
}//Listing 3.7
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

CS3 Java – Arithmetical Expressions (Singhal) Page 28 of 58


Listing 3.7 actually shows you that how explicit narrowing conversion is used in
programming algorithm, to discard un-needed data or information. In Listing
3.7 we broke down our calculations into many steps, so that we can clearly
understand them. In fact all calculation steps can be done in 1 step by the
following formula:
Total_Price = (double )((int) (Price_Per_Pound* Weight*
Dollar_Penny_Conv_Const + 0.5))/ Dollar_Penny_Conv_Const;

Understand that Java will not protect you from intentional


typecasting, which allows the loss of information! For example, the
first assignment below will give compile error, but the second one
will not.
Compile error!
short val = 90000;

short val1 = (int)(90000); No compile error! val1 have the


number resulted from overflow.

CS3 Java – Arithmetical Expressions (Singhal) Page 29 of 58


Static Methods in Java
The static methods in Java use the keyword static in their header. Inside a class, the
static methods can only call other static methods directly by the method name.
Methods in Java classes can be placed in any order, as Java has no function proto-
types like C++. For example in the class given below (MyClass), the two coding
styles are treated same by Java (Listing 3.8).
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Coding style 1
public class MyClass
{
public static void main(String []args)
{
//code for main method
//main method may call method print
}

public static void print( )


{
//code for print method
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Coding style 2
public class MyClass
{
public static void print( )
{
//code for print method
}
public static void main(String []args)
{
//code for main method
//main method may call method print
}
}//Listing 3.8
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
In Listing 3.8, the main method can call the other static void method print, simply
by using the stand-alone program statement:

print ( );

In this sense, in Java, the static methods that are members of the same class can call
each other in the manner similar to the functions calling each other in a C program.

CS3 Java – Arithmetical Expressions (Singhal) Page 30 of 58


Static methods are also called “class methods”. We will discuss the reason behind
this name later on.

Value returning methods


The concept of methods is central to Java programming. You have already seen that
every Java program must have at least one method called main. main however is a
void method. Void methods only cause a side affect, which may modify the standard
input output, or may communicate with a database etc. Java programs may need
methods that do some calculations or data processing, and return the result of such
calculations. We now discuss these value returning static methods in Java programs.
We can use mathematics to understand the concept of methods and their return
values. The Figure 3.13 attempts to do that for us. Understand that what we call
method in Java is called function in mathematics.

In Java functions are


called methods.

FIG. 3.13
If we write a function f(x) = 5*x – 3;
Then we have the following components.
1. Name of function/method – in this case simply f.
2. Parameter of the function – x, enclosed in parenthesis. We can call this a formal
parameter, as it just tells us the parameter name.
3. Definition of the function/method – in this case statement 5*x – 3 is the
definition;
The function/method f shown in Figure 3.13 will create a return value based on
actual value is substituted for x. You can say that when formal parameter x is
replaced by an actual parameter say x= 1, we get the following:

CS3 Java – Arithmetical Expressions (Singhal) Page 31 of 58


f(1) = 5*1-3 = 2. So we can say that function/method returned a value of 2. In this
case an actual calculation was done to return a value. Most value returning methods
in Java will do something similar, which is return a value based on some
calculations or some other constraints. Figure 3.14 shows the blocks of a Java
program with several methods in it.
Methods
May call
square
function or
Method cube function
as needed

Method Will return the


value of square of
number sent to it

Method Will return the


value of the cube of
number sent to it

FIG. 3.14
Let us say that the signatures11 of square and cube methods are as follows:
public static double square (double)
public static double cube (double)
This is shown in Listing 3.9 below.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
import javax.swing.*;
public class ValueReturningMethods1
{
public static void main(String [] args)
{
double number = 0.0;
String Input = JOptionPane.showInputDialog (null,
"Please enter the number to be squared and cubed: ");
number = Double.parseDouble(Input);

11
The method name and its formal argument list is called its signatures. For example main has
signatures as main(String [] args). No two class member methods can have same signatures.

CS3 Java – Arithmetical Expressions (Singhal) Page 32 of 58


System.out.println ("The square of "+number+" is = "

1. Call to the static member


+square (number)); method with name square.

System.out.println ("The cube of "+number+" is = "


+cube (number));
System.exit (0); 2. main temporarily
} transfers control to
function square or
public static double square(double number) cube
{
return (number*number);
}

public static double cube(double number)


{
return (number*number*number);
}
} Listing 3.9
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
In main, the program execution proceeds sequentially and the user input is stored in
memory location called number. In the System.out.println method call, the portion

square (number)

transfers the control to method square. The method square takes the value of
number passed to it and performs operation (number*number) and returns the
value to main. main displays the value to the user. Similar sequence involving
method cube is repeated when a call is made to it and the cube of the number is
displayed. Finally main takes the control back and exits the execution. Notice that in
the main method one may call the method square using the following syntax as well:

double square_value = square(number);

The square_value can then be displayed. Thus value returning methods can be
called as an argument to another method or they can be called as the right hand
part of an expression in Java. The nature of void methods is different, which we
discuss next.

CS3 Java – Arithmetical Expressions (Singhal) Page 33 of 58


Void Methods
void methods do not return any values by return mechanism. So they cannot be part
of an expression. They just perform some procedure, whose side affects can be seen
either in the input output or they could change values of some program variables,
which are called Java Objects12. In java main method can only be coded as a void
method. The Figure 3.15 below makes a comparison between the value returning
and void methods. We will look at methods in much more depth in later chapters.

methods

FIG. 3.15
Let us look at some of the methods that Java libraries provide for us and help us in
writing complicated programs.

Method name overloading in Java


As mentioned earlier, Java allows its class to have member methods with same name
as long as the signatures of each method are different. The signature of a method
constitute the following components:
• Method name
• Number of parameters passed to the method
• Order and Data types of method parameters
No two methods can have all of above three components to be identical. For example
in Java it would be a compile error to declare two methods like below:
public int myMethod (int val1, String name, double score)
{ //method body} Compile
public float myMethod (int val1, String name, double score) error
{ //method body}
12
We shall discuss Java Objects in future chapters.

CS3 Java – Arithmetical Expressions (Singhal) Page 34 of 58


Notice that method’s return type is not part of its signatures. However, the four
methods having name myMethod as shown below have different signatures and no
compile error is issued.
No
public int myMethod (int val1, String name, double score) Compile
{ //method body} error as all
methods
public int myMethod (String name, int val1, double score) have
{ //method body} different
signatures
public int myMethod (int val1, double score, String name)
{ //method body}

public int myMethod (int val1, String name)


{ //method body}

The first three methods have same number of parameters, and their types, but the
order of parameters is different, making them identifiable by their signatures. The
last method has fewer numbers of arguments than other three – thus having
different signatures from the all others. This process, where Java allows many
methods to have same name is called “method name overloading”. The ability
to overload method names allows programmers to use the same name for methods
whose algorithms or actions are similar. This facilitates the “economy” of inventing
the method names in Java.

CS3 Java – Arithmetical Expressions (Singhal) Page 35 of 58


Java Library Methods
Just like you can borrow books from library and use them, Java has many methods
in its set of library, which you can borrow and use to simplify your task of coding
complex algorithms. In Java the methods are always part of some class, and classes
are stored in so called packages! You would recall that in C programming you could
not perform an output without using the header file stdio.h. (Similar header file in
C++ is iostream.h, or simply iostream). How is it that you are able to print a
message such as Hello World by including a line in main?

System.out.println (“Hello World”);

This is so because while compiling a Java program, the compiler will automatically
import a java package called java.lang into users program. The important classes
included in java.lang package are as follows (Table 3.5).

Summary Of Important Classes From java.lang Package


The Boolean class wraps a value of the primitive
Boolean
type boolean in an object.
The Byte class wraps a value of primitive type
Byte
byte in an object.
The Character class wraps a value of the
Character
primitive type char in an object.
The Double class wraps a value of the primitive
Double
type double in an object.
The Float class wraps a value of primitive type
Float
float in an object.
The Integer class wraps a value of the primitive
Integer
type int in an object.
The Long class wraps a value of the primitive type
Long
long in an object.
The class Math contains methods for performing
basic numeric operations such as the elementary
Math exponential, logarithm, square root, and
trigonometric functions.

CS3 Java – Arithmetical Expressions (Singhal) Page 36 of 58


The Short class wraps a value of primitive type
Short
short in an object.
String The String class represents character strings.
The System class contains several useful class
System
fields and methods.
Table 3.5 Important classes from java.lang package
As discussed earlier, the classes Byte, Character, Boolean, Integer, Float, Double,
Short, and Long are the wrapper classes for the primitive data types provided by
Java. We have made use of wrapper classes to get user input for primitive data
(integer and floating point), where the inputted user String is parsed to get the
numerical value. System class has been used to output data to the standard output.
Math class is another important Java class, which has static methods allowing user
to perform many complex calculations with ease. Table 3.6 gives the summary of
member methods from Math class in java.lang package.

Summary Of Static Methods in class java.lang.Math


static param abs(param num)
Returns the absolute value of num. The param can be of
type double, float, int and long.
static double acos(double a)
Returns the arc cosine of an angle, in the range of 0.0
through pi.
static double asin(double a)
Returns the arc sine of an angle, in the range of -pi/2
through pi/2.
static double atan(double a)
Returns the arc tangent of an angle, in the range of -pi/2
through pi/2.
static double atan2(double y, double x)
Converts rectangular coordinates (x, y) to polar (r, theta).
static double ceil(double a)
Returns the smallest (closest to negative infinity) double
value that is not less than the argument and is equal to a
mathematical integer.
static double cos(double a)
Returns the trigonometric cosine of an angle.

CS3 Java – Arithmetical Expressions (Singhal) Page 37 of 58


static double exp(double a)
Returns Euler's number e raised to the power of a
double value.
static double floor(double a)
Returns the largest (closest to positive infinity) double
value that is not greater than the argument and is equal to a
mathematical integer.
static double IEEEremainder(double f1, double f2)
Computes the remainder operation on two arguments as
prescribed by the IEEE 754 standard.
static double log(double a)
Returns the natural logarithm (base e) of a double value.
static param max(param num1, param num2)
Returns the greater of two param type values num1 and
num2. The param can be of type double, float, int and long.
static param min(param num1, param num2)
Returns the greater of two param type values
num1 and num2. The param can be of type double, float, int and
long.
static double pow(double a, double b)
Returns the value of the first argument raised to the
power of the second argument.
static double random()
Returns a double value with a positive sign, greater than
or equal to 0.0 and less than 1.0.
static double rint(double a)
Returns the double value that is closest in value to the
argument and is equal to a mathematical integer.
static long round(double a)
Returns the closest long to the argument.
static int round(float a)
Returns the closest int to the argument.
static double sin(double a)
Returns the trigonometric sine of an angle.
static double sqrt(double a)
Returns the correctly rounded positive square root of a
double value.

CS3 Java – Arithmetical Expressions (Singhal) Page 38 of 58


static double tan(double a)
Returns the trigonometric tangent of an angle.
static double toDegrees(double angrad)
Converts an angle measured in radians to an
approximately equivalent angle measured in degrees.
static double toRadians(double angdeg)
Converts an angle measured in degrees to an
approximately equivalent angle measured in radians.
Table 3.6 Some of the static methods from Math
class
Many computer problems require mathematical computations, like using
trigonometric calculations, or finding powers of number etc. Table 3.7 below shows
that how some of the java.lang.Math class static methods can be used to make
calculations.
static Method from Math Example of call Return
class statement value
abs ( i ) : i can be int, long, Math.abs(-6) 6
double or float.
pow ( x , y ): (read note1 below) Math.pow (2.0,3.0) 8.0
sqrt( x ) : (Read Note2 below) Math.sqrt(100.0) 10.0
Math.sqrt(2.0) 1.41421..
log ( x ) : (Read Note2 below) Math.log(2.0) 0.69314..
min ( x , y): x, y can be of type Math.min (20,55) 20
int, long, float, and double
max ( x , y): x, y can be of type Math.max (20.01f, 29.5f
int, long, float, and double 29.5f)
ceil ( x) : (Read Note 2 below) Math.ceil ( 3.01) 4.0
floor ( x) : (Read Note 2 below) Math.floor ( 3.99) 3.0
Note1: x, y can only be double type. Automatic type conversion will be
done if other types are passed.
Note2: x can only be double type. Automatic type conversion will be
done if other types are passed.
Table 3.7
From Table 3.7, you would notice that some of the Java Math class methods, such as
sqrt, pow, and log perform in a manner similar to their counter parts in cmath

CS3 Java – Arithmetical Expressions (Singhal) Page 39 of 58


library in C++. The difference in Java is that method call syntax needs the fully
qualified name of the method, such as Math.pow (2.0, 3.0) etc.

Let us take a closer look at the use of sqrt (x) method of class java.lang.Math. This is
shown in Figure 3.16.

Method arguments can be:


• Literal constant Calling sqrt (x) with
in the call to sqrt is
Math.sqrt (4); OK, because
according to
• Variable or named constant precedence rules, the
Math.sqrt (x); inner call will be made
first, and then the
• Legal expressions and call to other outer call is made.
methods
Math.sqrt (Math.sqrt (x));
Math.sqrt (3 –FIG. 3.16
6*x);
FIG. 3.16
The arguments to the methods can be named or literal constants, variables, and
expressions. A value returning method can be a part of an expression.

Non-static or Instance methods in Java


Apart from static methods, Java classes may contain methods, which do not have
the word static in their method header. The non-static methods are called instance
methods. These methods cannot be called inside the static methods directly by their
names. One must create an instance of the class first and then qualify the instance
method to be called by using the dot operator. We have been creating instances of
String class with out calling them by that name. Take for example the declaration:

String Name = “JOHN DOE”; Name is an instance of class String,


which stores “JOHN DOE” in it.

All the instance methods of the String class can be called by using the instance
variable Name created by the declaration above. For example, the String class has
an instance method called toLowerCase ( ), whose purpose is to convert all
characters in a particular string to lower case. If one makes a call to method
toLowerCase with the syntax given below, the result will be that all characters in the
variable called Name will convert to lower case.

CS3 Java – Arithmetical Expressions (Singhal) Page 40 of 58


Instance methods must be qualified
Name = Name.toLowerCase( ); by the instance, which is used to
invoke them.

Instance
Instance method being invoked.
name

Notice that to call the instance method (in this case the method toLowerCase) one
must qualify it by dotting it with the instance of the String object, which is making
the call. Without such qualification, the instance methods cannot be invoked outside
a class or inside any static method. Soon we show use of some instance methods in
Java class called String.

String Class
Strings are very important in programming. They have become even more
important, with the ubiquitous Internet programming. All the web sites, which offer
web services, may use, user name and a password. These are stored in String data
type forms. Operations on strings, like finding the length of a string, finding a sub
string inside another string, getting a portion of a string returned as a substring are
all important string operations. Java treats all strings as final objects, for example
once created; a java string can never be altered. This type of “string safety” is the
corner stone of java’s excellent security system, a feature missing in practically all
other programming languages, where strings are alterable. We first show the
summary of important methods available in the String class (Table 3.8), and then
we discuss some of them in more detail.

Summary Of Some Methods in class java.lang.String


char charAt(int index)
Returns the character at the specified index.
int compareTo(String anotherString)
Compares two strings lexicographically.
int compareToIgnoreCase(String str)
Compares two strings lexicographically, ignoring case
differences.
String concat(String str)
Concatenates the specified string to the end of this string.

boolean endsWith(String suffix)


Tests if this string ends with the specified suffix.

CS3 Java – Arithmetical Expressions (Singhal) Page 41 of 58


boolean equals(Object anObject)
Compares this string to the specified object13.
boolean equalsIgnoreCase(String anotherString)
Compares this String to another String, ignoring case
considerations.
int indexOf(int ch)
Returns the index within this string of the first occurrence
of the specified character.
int indexOf(int ch, int fromIndex)
Returns the index within this string of the first occurrence
of the specified character, starting the search at the specified
index.
int indexOf(String str)
Returns the index within this string of the first occurrence
of the specified substring.
int indexOf(String str, int fromIndex)
Returns the index within this string of the first occurrence
of the specified substring, starting at the specified index.
int lastIndexOf(int ch)
Returns the index within this string of the last occurrence
of the specified character.
int lastIndexOf(int ch, int fromIndex)
Returns the index within this string of the last occurrence
of the specified character, searching backward starting at the
specified index.
int lastIndexOf(String str)
Returns the index within this string of the rightmost
occurrence of the specified substring.
int lastIndexOf(String str, int fromIndex)
Returns the index within this string of the last occurrence
of the specified substring, searching backward starting at the
specified index.
int length()
Returns the length of this string.

13
Object is a class is Java, from which all other classes are derived. This will be discussed in the
chapter on inheritance. Till then you can think that in executing the method equals(Object
anObject), one can pass a String to check whether the contents of the String passed are same as
String being compared.

CS3 Java – Arithmetical Expressions (Singhal) Page 42 of 58


String replace(char oldChar, char newChar)
Returns a new string resulting from replacing all
occurrences of oldChar in this string with newChar.
String replaceAll(String regex, String replacement)
Replaces each substring of this string that matches the
given regular expression with the given replacement.
String replaceFirst(String regex,
String replacement)
Replaces the first substring of this string that matches the
given regular expression with the given replacement.
boolean startsWith(String prefix)
Tests if this string starts with the specified prefix.
boolean startsWith(String prefix, int toffset)
Tests if this string starts with the specified prefix
beginning a specified index.
String substring(int beginIndex)
Returns a new string that is a substring of this string.
String substring(int beginIndex, int endIndex)
Returns a new string that is a substring of this string.
String toLowerCase()
Converts all of the characters in this String to lower
case using the rules of the default locale.
String toString()
This object (which is already a string!) is itself returned.
String toUpperCase()
Converts all of the characters in this String to upper
case using the rules of the default locale.
String trim()
Returns a copy of the string, with leading and trailing
white space omitted.
static String valueOf(param d) // param can be of types double, float,
int, long, boolean, char, an array of char, and Object
Returns the string representation of the param argument

Table 3.8
Here we discuss just a few methods available for strings in Java and we will discuss,
rest of them as we proceed further in this book.

CS3 Java – Arithmetical Expressions (Singhal) Page 43 of 58


Finding The Length of a String:
Databases very often store data on customers and vendors in string form. Examples
of string data are, names, address, phone numbers. Practically any data not needing
arithmetical operations may be stored as a string. Often length of such data is fixed
at an upper limit. For example the name field may be limited to 30 characters or
less. Therefore, before such data are inputted into the database, a check is needed as
to its conformance with the length restriction. A Java program may need to do such
check and chop off characters above the size limit for the string. Finding string
length is important for such applications. Listing 3.10 below shows how the length of
a string can be determined in Java.
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public class StringOperation1
{
Finding the string
public static void main(String [] args)
{ length by calling the
String Name = "John Q Public"; instance method
length in String
int length = Name.length( ); class.

System.out.println ("The number of characters in name "


+"John Q Public (including spaces) is = " + length);
}
} Listing 3.10
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
The output of the above program is a statement:

The number of characters in name John Q Public (including spaces) is =


13

Calling the length instance member method of the String class returns the number
of characters (including spaces) in the string.

Converting all characters in a string to all lower case or all upper case
Some times it is easier to compare strings, when both of them have all lower case
letters or upper case letters. String class instance methods toLowerCase and
toUpperCase perform these operations. Example is shown in Listing 3.11.
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public class StringOperation2 1. Method toLowerCase
{ converts all characters in
public static void main(String [] args)
{ its caller to lower case.
String Name = "JOHN Q PUBLIC";

String Name_Lower = Name.toLowerCase( );

CS3 Java – Arithmetical Expressions (Singhal) Page 44 of 58


System.out.println ("The lower case form of name "
+Name + " is : " + Name_Lower );
System.out.println ("The upper case form of name "
+Name_Lower + " is : " + Name_Lower.toUpperCase( ));
}
} Listing 3.11
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
The output of the above program is:

The lower case form of name JOHN Q PUBLIC is : john q public


The upper case form of name john q public is : JOHN Q PUBLIC

The call to method toLowerCase converts all characters in String “JOHN Q


PUBLIC” to lower case (bubble #1), thus displaying the result “john q public”.
Reverse happens when the method toUpperCase is called.

Returning the String representation of Java Primitive Types


Java String class has nine static overloaded methods called valueOf, seven of which
take a primitive type as an argument and return its String representation. The
general signatures of these seven methods is given by the generalized method
header:

public static String valueOf (param data)

The param can be replaced by any of the seven primitive data types: byte, char,
short, int, long, float, and double. Listing 3.12 shows a trivial application of the
overloaded method valueOf. We need to wait to learn graphics programming in
Java for more potent applications of method String.valueOf.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
{
public static void main(String [] args)
{ Returns the String containing
long $long = 10000L; number $long*100.9

String Number = String.valueOf ($long*100.9);

valueOf is a static or
class method.
Number= " = " + Number;
System.out.println ("The multiplication of "+$long+
" and " + 100.9+ Number);

CS3 Java – Arithmetical Expressions (Singhal) Page 45 of 58


}
} Listing 3.12
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
The output of Listing 3.12 is:

The multiplication of 10000 and 100.9 = 1009000.0

Finding the position of a given character or a Sub string with in a


string
Another common operation on strings is to find whether a particular substring
occurs with in certain string or not. For example in your database of customers you
may wish to find whether customer name field has certain last name in it or not. Let
us say that we wish to find whether last name JonesJ is present or not in a certain
name. Then we can use the String class overloaded instance method indexOf for this
purpose. Listing 3.13 shows how the last name JonesJ could be searched in the
string “Adam JonesJ”. The instance method indexOf is called on Object My_Name,
which contains the string “Adam JonesJ”. The method takes the string “JonesJ” as
an argument. If substring passed is present in the String (in this case My_Name)
then the index of its first character, where the first occurrence of string begins is
retuned. If the substring is not present in the string then a value of –1 is returned.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public class StringOperation4
{
public static void main(String [] args) 1. Instance method
{ indexOf is called on
String My_Name = "Adam JonesJ"; instance My_Name

int index1 = My_Name.indexOf ("JonesJ");

System.out.println ("The substring \"JonesJ\" occurs in "


+My_Name+" starting at index = " + index1);

index1 = My_Name.indexOf('J');
System.out.println ("The first occurrence of character\'J\'"+
" in "+My_Name+" is at index = " + index1);

index1 = My_Name.lastIndexOf('J');
System.out.println ("The last occurrence of character\'J\'"+
" in "+My_Name+" is at index = " + index1);
}
} //Listing 3.13
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

CS3 Java – Arithmetical Expressions (Singhal) Page 46 of 58


FIG. 3.17
Figure 3.17 shows the output of the Listing 3.13. The substring “JonesJ” starts at
the index five in the string “Adam JonesJ”. Therefore a call to method indexOf in
front of bubble #1 gives a result of five. Note that index starts at zero, which is the
index of the first character in the string. Overloaded instance method indexOf can
also take a character as an argument, in which case it finds and returns the index of
the first character matching its argument or return –1. Therefore the call to method
indexOf with an argument ‘J’ also returns five.

Another useful method is lastIndexOf, two versions of which can take a character or
a string as an argument and return the last index in the string, where the string or
character passed as an argument is found. lastIndexOf works in manner similar to
the method indexOf. In last example in Listing 3.13, the method lastIndexOf is
called by the String My_Name with an argument ‘J’, which returns 10, the index of
last ‘J’ in the string “Adam JonesJ”.

Comparing the contents of two strings


On Internet on a web site providing web services, the user should be provided entry
if the user name and passwords match. Java provides the methods that can compare
the contents of two strings and determine if their contents are identical or not. One
of such instance methods is equals, which can take any object, including a String as
an argument. If the string passed as an argument is identical to the caller string then
equals method returns a true value. Otherwise it returns a false. We cannot show
the power of this method until we have covered the control structures if/else.
However, the Listing 3.14 gives a general idea.
00001 import javax.swing.*;
00002
00003 public class StringOperation5
00004 {
00005 public static void main(String [] args)
00006 {
00007 String My_Name = "Adam JonesJ";
00008 String Input = JOptionPane.showInputDialog (null,
00009 "Please enter your name");
00010 boolean info = My_Name.equals(Input);
00011 System.out.println ("It is " + info + " that your name is "
00012 + My_Name);

CS3 Java – Arithmetical Expressions (Singhal) Page 47 of 58


00013
00014 System.exit (0);
00015 }
00016 }//Listing 3.14
In above listing a String object My_Name is created on code line #7 with contents
“Adam JonesJ”. Then user is prompted to input their name (lines 8 and 9), which is
stored in the string Input. The String My_Name with an argument Input calls
Method equals, and return value is stored in the boolean variable info. If the user
input matches the one shown in the pop up box in Figure 3.18A, then a true value is
stored in the variable info and the output for Listing 3.14 is shown by Figure 3.18B.

FIG. 3.18A

FIG. 3.18B
However if user input is different from the contents of the string My_Name then
boolean info stores a false value and corresponding message is displayed (Figure
3.19).

FIG. 3.19A

CS3 Java – Arithmetical Expressions (Singhal) Page 48 of 58


FIG. 3.19B
Method compareTo can also compare the caller string with the string passed as an
argument. It will return zero only if the contents of the string passed as an argument
are identical to the caller string. Otherwise a negative or positive number will be
returned based on whether caller string is lesser in lexicographical14 order or larger
than the string passed as an argument.

Getting a substring from a string


String class also has the overloaded instance method called substring, one of whose
form can get the substring from a string beginning at certain index and extending to
the string end. Examples of use of method substring are given below.

"unhappy".substring(2) returns "happy"


"Harbison".substring (3) returns "bison"
"emptiness".substring (9) returns "" (an empty string)

Notice that even literal strings can call the instance methods of the String class.
Another form of the method substring takes two integers as arguments and returns
a substring, which begins at the index equal to the first argument and ends at the
second one. The method header and examples are given below.

public String substring(int beginIndex, int endIndex)

"hamburger".substring(4, 8) returns "urge"


"smiles".substring(1, 5) returns "mile"

Note that to get a valid substring, the endIndex must be at least one more than the
beginIndex.

Replacing characters in a string


Method replace takes two character arguments, and replaces it in the caller string
with the second argument. The method header and examples are shown below.

public String replace(char oldChar, char newChar)

Examples:
"mesquite in your cellar".replace('e', 'o')
returns "mosquito in your collar"

14
The lexicographical ordering method of string comparison will be discussed later.

CS3 Java – Arithmetical Expressions (Singhal) Page 49 of 58


"the war of baronets".replace('r', 'y')
returns "the way of bayonets"
"sparring with a purple porpoise".replace('p', 't')
returns "starring with a turtle tortoise"
"JonL".replace('q', 'x') returns "JonL" (no change)

Questions (In multiple choice questions, more than one answers may be
correct. Choose all that are correct)
1. Answer the questions given in Figure 3.20 below. What value is returned by each
method call?

FIG. 3.20
2. A C++ programmer, while practicing Java writes the following code thinking that
the boolean variable must_be_true would have a value true. Instead he gets the
output shown in Figure 3,21, where variable must_be_true has a false value. Explain
the output for this listing (3.15).
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public class Questions1
{
public static void main(String [] args)
{
String Last = "Doe";
String Result = ("John Doe").substring(5);
boolean must_be_true = ( Result == Last);
System.out.println("Boolean variable must_be_true = " + must_be_true);
}
}//Listing 3.15

CS3 Java – Arithmetical Expressions (Singhal) Page 50 of 58


/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

FIG. 3.21
3. Consider the following code snippet
String river = “Columbia”;
System.out.println (river.length( ));
What is printed?
A. 6
B. 7
C. 8
D. Columbia
E. river

4.You read the following statement in a Java program that compiles and
executes.
submarine.dive (depth);
What can you say for sure?
A. depth must be an int
B. dive must be a method.
C. dive must be the name of an instance field.
D. submarine must be the name of a class
E. submarine must be a method.

5. After the following code fragment, what is the value in a?


String s;
int a;
s = "Foolish boy.";
a = s.indexOf ("fool");

6. Which of the followings will give compile error in Java?


A] int n2 = 4096L;
B] short s1 = 32000;
C] short s2 = 33000;
D]
short s3 = 20000;
short s4 = 22000;
short s5 = s3*s4;
E] byte b1 = ‘A’ +’A’ ;
F] byte b1 = ‘A’ ;

CS3 Java – Arithmetical Expressions (Singhal) Page 51 of 58


7. What will be printed by the following Java program?
char c1 = ‘\u0057’;
char c2 = ‘W’;
char c3 = (char)87;
System.out.println (c1+c2+c3);

8. What will be printed by the following Java program?


char c1 = ‘\u0057’;
char c2 = ‘W’;
char c3 = (char)87;
System.out.println (c1+””+c2+””+c3);

9. A programmer writes the following code to try to print the name of 2001 Space
Odyssey computer HAL 9000. What would this program really print? Can you
correct programmer’s error simply by making changes inside the call to print
method? Show how?

System.out.println ( ‘H’+’A’+’L’+’ ‘+9000);

10. What will be printed by the following Java snippets? Explain your answers.

A] System.out.println (5 + ‘5’ + “5”);


B] System.out.println (""+5 + '5' + "5");
C] System.out.println (5 + "5"+ '5' );
D] System.out.println ( "5"+5+ '5' );
E] System.out.println (‘5’ +(5+ “5”));
F] System.out.println (5 + "5".length( )+ '5' );
G] System.out.println (5 + "5".indexOf (‘5’)+ '5' );
H] System.out.println (5 + "5".indexOf (‘6’)+ '5' );
I] System.out.println (5 + "5".indexOf (“5”)+ '5' );

11. The following two programs, first from Java, and second from C++ may appear
to give same output. However, they do not as the sequence of numbers printed is
reverse of each other (tested on Windows OS). What would be the output from Java
program? Why does Java output comes out as expected?
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public class MyClass
{
public static void main (String [ ] args)
{
int num = 5;
print(++num,++num);
}

public static void print (int val1, int val2)


{

CS3 Java – Arithmetical Expressions (Singhal) Page 52 of 58


System.out.println (“val1 = “ + val1);
System.out.println(“val2 = “ + val2);
}
}//Listing 3.16
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include <iostream>
using namespace std;

void print(int val1, int val2)


{
cout<<“val1 = “ << val1<<endl;
cout<<“val2 = “ << val2<<endl;
}

void main( )
{
int num = 5;
print(++num,++num);
}//Listing 3.17
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

12. Which of the following statements is true concerning Java variables and
assignment?

a. A long can be stored in a float.


b. A float can be stored in a long.
c. A long can be stored in an integer.
d. A double can be stored in a float.

13. Here is a line of Java code: weeks_in_year = (int) tax_rate; Without having
seen the types of the variables given during declaration, what is the most
reasonable guess concerning them?

a. weeks_in_year is an int and tax_rate is not.


b. tax_rate is an int and weeks_in_year is not.
c. Both weeks_in_year and tax_rate are ints.
d. Neither weeks_in_year nor tax_rate are ints.

14. Arithmetic with a mixture of variable types in Java:

a. Is accomplished by treating all variables as if they were of the type


present in the expression, which can hold the most information.
b. Is accomplished by treating all variables as if they were of the type
present in the expression, which can hold the least information.
c. Is accomplished by truncating all non-integral values.
d. Is not allowed.

CS3 Java – Arithmetical Expressions (Singhal) Page 53 of 58


15. Here is a Java operator: %. This operator:

a. Gives the remainder upon integer division.


b. Gives the percent.
c. Gives a printing format.
d. Is the escape character.

16. Here are some declarations and initializations:


double result;
double value = 5.0;

Which of the following lines of code correctly uses a method of the Math class?

a. result = Math.sqrt(value);
b. result = value.sqrt();
c. Math.result = sqrt(value);
d. result = Math.value.sqrt();

17. Here are two lines of code:


String mystring = “Hello”;
String newstring = mystring.substring(j, k);
What values of j and k are needed in order for newstring to contain “Hell”?

a. 0, 4
b. 1, 4
c. 1, 5
d. 0, 5

18. Here are 4 lines of code:


int myint = 2;
String mystring = “ab”;
String newstring = myint + mystring;
System.out.println(newstring);
What is the output of this?

a. 2ab
b. A compiler error.
c. A run time error.
d. 212

19. Here is one line of code:


String mystring = “”;

a. The contents of mystring are referred to as the empty string.


b. The contents of mystring are referred to as the null string.

CS3 Java – Arithmetical Expressions (Singhal) Page 54 of 58


c. This gives a compiler error.
d. This gives a run time error.

20. Here are 3 lines of code:


String mystring = “3.5”;
double mydouble = Double.parseDouble(mystring) + 4.0;
System.out.println(mydouble);
What is the output of this?

a. 7.5
b. 3.54
c. “3.5”4
d. This gives a compiler error.

21. Which of the following is illegal:


A] int i = 32;
B] float f = 45.0;
C] double d = 45.0;

22. When the program containing the following code in main method is run and the
command line arguments entered are: four four
then what is the output of this code?

int argument1 = args[0].length( );


int argument2 = args[1].length( );

System.out.println ( argument1*argument2 – Math.pow(4,2));

What is the data type of the expression passed as an argument to method println?

23. What gets printed when the following program is compiled and run. Select the
one correct answer.

public class incr


{
public static void main(String [ ]args)
{
int i , j;
i = j = 3;
int n = 2 * ++i;
int m = 2 * j++;
System.out.println(i + " " + j + " " + n + " " + m);
}
}

CS3 Java – Arithmetical Expressions (Singhal) Page 55 of 58


A. 4486
B. 4488
C. 4466
D. 4386
E. 4388
F. 4468

24. Given two non-negative integers a and b and a String str, what is the number
of characters in the expression str.substring(a,b) . Select the one correct answer.

A. a+b
B. a-b
C. b-a-1
D. b-a+1
E. b-a
F. b

25. Given the following declarations, which of the assignments given in the options
below would compile. Select the two correct answers.

int i = 5;
boolean t = true;
float f = 2.3F;
double d = 2.3;

t = (boolean) i;
f = d;
d = i;
i = 5;
f = 2.8;

CS3 Java – Arithmetical Expressions (Singhal) Page 56 of 58


References
1. Link for Java’s widening and narrowing conversions
2. More on Widening and narrowing conversions

CS3 Java – Arithmetical Expressions (Singhal) Page 57 of 58


Make Notes Here

CS3 Java – Arithmetical Expressions (Singhal) Page 58 of 58


CS3 – Topic 4
Author: Satish Singhal, Ph. D.
Version – 1.0

Java Classes And Objects

So far in this book we have used Java classes only as a wordy way of writing C type
programs, which were limited only to, either main method or additional static
methods. In this chapter we explore the true power of Java as an object oriented
programming language. However, we would extend our effort to use Java in C-like
manner, just a bit longer, so that we can illustrate some key Java principles of
object creation and their storage. Suffice to say at this point that in Java, classes are
the templates to create objects of user defined data types, which can store data and
methods in them for data processing1.

We write a simple class called Customer, which is similar to a C struct in the sense
that it has only data members, which are all public. Listing 4.1 shows the class
Customer. This class is a small version of more sophisticated Customer classes,
which may be written in enterprise software development environment.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class Customer
{
public String name; //stores name of customer
public long phone_num; //stores phone number
public char credit_rating; //stores credit rating
public String address; //stores street address
public String city; //stores city
public long zip_code; //stores zip code
public String credit_card_num;//stores credit card number
}//Listing 4.1
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
To make members of class Customer, accessible in a manner like member access in
C struct, we use the keyword public in front of each of them. This allows one to
access them by using the familiar dot operator. Some useful operations involving
class Customer may require:
1. Creating an instance or object of class Customer.
2. Inputting data into the object created in step one.
3. Printing the information stored in Customer object.
4. Changing the information stored in Customer object.
The first step requires a Java declaration, which will create an object or instance of
class Customer. Other three steps require operations on such object. All of above

1
Struct in C are not allowed to store methods in them, however, the struct in C++ is just like a class,
except that default access level in C++ struct is public.

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 1 of 78


are done in another class, whose member methods use the Customer class, the way a
C program would use a struct.

Creating and storing objects in Java programs


You would recall that you were able to create an object of class java.lang.String,
simply by making the declaration:

String Name = “John Doe”;

In above declaration, the variable Name is actually not the name of storage location
in memory, where the string “John Doe” is stored. Rather it is a reference (or a
pointer), which stores the address of that part of memory, where string “John Doe”
is stored. Schematically we can represent the relationship between the variable
Name, and location where string “John Doe” is stored by the Figure 4.1 below.

Reference (pointer) called


Name, which is capable of
holding the address of
String type data.

Name 5000
“John Doe”
5000
Stores the address
5000 in it

Address of string “John


Doe” in the memory.
FIG. 4.1
If Java stores the string “John Doe” at a memory address, 5000, then the single line
assignment statement: String Name = “John Doe”; stores 5000 as the content of
reference variable called Name. In this sense Java reference are similar to C
pointers.

However, before we can even get into explanation of how to create objects of user
defined classes, other than String, in Java, we need to take a slight detour and

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 2 of 78


explain as to what types of storage locations are involved in program execution and
how Java uses them.

The memory available to the operating system or device is divided into two types of
region:
• Stack Memory
• Heap Memory
During execution of Java program all the local variables are stored on the stack,
whereas all the objects are stored on the heap. The stack memory is used just like a
stack data structure, which uses the Last-In-First-Out (LIFO) protocol. This means
that the variables created last on the stack memory are destroyed first, when they go
out of scope. Stack memory uses the memory addresses sequentially. There is no
strict sequence followed in the use of heap memory. Java stores all primitive
data types and references to objects on the stack and all objects on heap.
Let us show an example of the use of two types of memories in a Java code snippet
and how data declared in it are stored in the program memory (Figure 4.2).
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
int val = 6;
int num; // not initialized yet
String Name = “John”; Bottom of stack
double data = 5.005;
String City = null;

Stack Heap Memory


memory
Beginning address of
val 6 memory location, where
2000 “John” is stored.
num ??

Name 2000 “John”

data 5.005
FIG. 4.2
City null

Figure 4.2 shows two partitions in the memory – on the left the stack memory and
on right the heap memory. As program proceeds sequentially, it creates storage for
the declared data, on stack sequentially. For example the int variable val is declared
first on the stack (bottom of the stack) and a value of six is placed in its storage
location. The next variable num has a storage location but it is not initialized,
therefore its contents are undefined. Then we declare a String object called Name,
and store the data “John” in it.

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 3 of 78


Notice the stark difference between the way Java stores primitives and objects.
Primitive data such as val is stored on the stack. However, for the objects, such as
Name, the actual storage (“John”) is not created on the stack. Rather it is done in
another part of the memory called heap. Variable “Name” in Figure 4.2, only stores
the beginning memory address of that part of the heap memory, where actual object
“John” is stored. For example, “Name” stores a value 2000, which in our schematic
representation is the beginning memory address of object “John” on the heap. As
stated earlier, the variable Name stores only the address of object “John”, therefore,
we may say that Name is the pointer to string “John”. In Java we call such pointers
as references2. However, they are different from C/C++ pointers as no “pointer
arithmetic” can be performed on them. Also Java references are deleted
automatically, when they no longer point to any object. We can thus draw following
conclusions:

• In Java, primitive data are stored on the stack in the sequence in


which they are declared, whereas the objects are stored on the
heap.
• References (pointers) to objects are stored on the stack.
• Objects are accessible only through the references, which store
their address!
• All objects in Java are “no name objects”. Only the references
storing their address have names.

Continuing with the Figure 4.2, after declaration of String Name with value “John”,
we declare a double variable called data (=5.005), which is stored on the stack.
Finally we declare another String reference called City, but we set it equal to null3,
and a null value is stored in that reference.

null value in Java: Unlike C++, null does not have a zero value in Java. A null
value can only be assigned to object references and not to the primitives. The null
keyword represents a special value stored in an object reference, which does not
refer to any object on the heap. null cannot be cast to any other type, and should not
be considered to have a known numeric value. A null value can also be seen as a
fundamental initializer for objects, just the way zero value is for integral data types.

Creating objects of class Customer (Dynamic Allocation)

Now we come back to the procedure of declaring the objects for the class Customer
defined in Listing 4.1. We were able to create a Java String object, using a simple

2
All references are 4 bytes in size.
3
A null value in Java can only be assigned to object references. Primitive data types cannot be
assigned pointers or references in Java, a paradigm vastly different from C/C++ languages.

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 4 of 78


declaration such as: String Name = “John Doe”. However, for the customer data
type we are not able to create its instance on the heap; the way Java allows us to
create String objects. A Declaration such as below (Figure 4.3) is required to create
a storage location for the object of type class Customer:

Customer My_Customer = new Customer ( );

Hidden “method”
Variable
added to the class
name
Customer by Java

Data type
Java operator

FIG. 4.3

The left hand side of above declaration is not different from standard declarations
we have used so far. It consists of the data type (in this case Customer), followed by
the variable name (My_Customer). My_Customer is a Java reference, which is
four bytes in size and it is capable of storing the address of a Customer type object,
which would be created on the heap. However, to actually allocate the storage on
heap memory, Java requires the expression: new Customer ( ): on the right hand
side. The use of keyword new followed by class name and parentheses tells
Java to create the storage and its contents for this object on the heap, when the
program runs. Therefore the decision of what to store in an object in Java is only
made when program runs. This type of storage is called “dynamic allocation”. The
dynamically created variables can be deleted, and memory reclaimed, even before
the variables have gone out of scope. In Java such memory reclamation is done by a
process called “garbage collection”, which we would discuss in detail later. Although
when we declare a String object such as:

String Last_Name = “Doe”;

we are able to do it with out using the keyword new, yet the storage for string “Doe”
is created on the heap at run-time. This facility, where one can create an object with
out using the keyword new is only provided for String class, as its objects are
created so often in Java programs. Creation of all other objects must use the
keyword new.

Class Constructor

Let us analyze the expression for creating an object of class Customer in more
detail. Consider the following Java declarations in a program:

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 5 of 78


int val = 6;
Customer Cust = new Customer ( );
String Name = “John”;
double data = 5.005;
String City = null;

Figure 4.4 shows the memory map at the run time when the program consisting
above declarations is executed.

FIG. 4.4

Notice that use of statement:

Customer Cust = new Customer ( ) ;

created an Object of type Customer on the heap. What you may be shocked to
discover is that the right hand side of declaration of object Cust resembles like a
method call (Customer ( )), yet the class definition in Listing 4.1, contains no
methods at all. All Java classes automatically are provided a hidden “method”
whose name is same name as the class name, and it has no return type, and takes no
arguments. This “method” is called by a special name “constructor”. Therefore

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 6 of 78


even though there are no methods visible in class Customer in Listing 4.1, Java adds
the following special method in class Customer automatically:

Constructor has same name as the


public Customer ( ) class and has no return type.
{

/*code to initialize all members of class Customers to their

fundamental values. Java provides this code automatically.*/

The special hidden “method” or constructor added by Java by default is also called
a default constructor. The default constructor provided by Java initializes all class
data members to some fundamental values. In order to show action of this
constructor, and other program details, we design another class called
DriverCustomer, which has main4 and other helper methods that either take a
Customer object as parameter or return it by return mechanism. Listing 4.2 shows
the classes Customer and DriverCustomer; both placed in a file named
DriverCustomer.java. There are certain rules for placing more than one class in the
same java file.

Rules for placing more than one class in a java file


Java allows more than one class to be placed in the same file as long as:
• Only one of the classes in the file can be declared public.
• The file name can be name of any of the java classes in the file.
• If program is compiled from the command line, then the name of the class,
which bears the file name, must be used. For example if classes MyClass,
YourClass, TheirClass – all are included in one file and the name of file is
MyClass.java, then compile command line should be:

>javac MyClass.java
or
>javac *.java

• All Java classes are allowed to have the main method in them. In a file
containing multiple classes, the main method of any of them may be executed

4
We could have included the main method in class Customer also, but in the spirit of Object
Oriented Programming (OOP) it is considered a better design when the class that is used as a user
defined data type is tested and used by the methods in another class. Such classes are called client
classes.

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 7 of 78


by the appropriate command line execution. For example if in the example
above, assuming that all three classes (MyClass, YourClass, TheirClass) have
main method in them, then any of them can be executed by the command line
such as:
Executes the main method in
>java MyClass class MyClass

>java YourClass Executes the main method in


YourClass
>java TheirClass

• Order of placement of classes in the same java file is unimportant. However,


Java still requires that all import statements be placed before any class
definitions begin.

Now we discuss Listing 4.2 and its output.

00001 import javax.swing.*;


00007 class Customer
00008 { 1. Class
Customer
00012 public String name;
00016 public long phone_num;
00020 public char credit_rating;
00024 public String address;
00028 public String city;
00032 public long zip_code;
00036 public String credit_card_num;
00037 }
00042 public class DriverCustomer
00043 {
00051 public static void main(String [] args)
00052 {
00053 Customer Cust = new Customer( );
00054 printSeparator();
System.out.println("Printing customer information stored in empty customer object:");
00056 printCustomer(Cust);
00057 printSeparator();
00058 Cust = getCustomer( );
00059 System.out.println("Printing customer information after data input:");

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 8 of 78


00060 printCustomer(Cust);
00061 printSeparator();
JOptionPane.showMessageDialog(null,"Will change customer data now. Click OK");
00063 changeCustData(Cust);
JOptionPane.showMessageDialog(null,"Will print customer data again. Click OK");
00065 System.out.println("Printing customer information after changing data:");
00066 printCustomer(Cust);
00067 printSeparator();
00068 System.exit(0);
00069 }
00070
00077 public static Customer getCustomer( )
00078 {
00079 Customer Cust = new Customer();
String Input = JOptionPane.showInputDialog(null, "Enter customer name");
00081 Cust.name = Input;
00082 Input = JOptionPane.showInputDialog(null, "Enter customer address");
00083 Cust.address = Input;
00084 Input = JOptionPane.showInputDialog(null, "Enter customer City");
00085 Cust.city = Input;
Input = JOptionPane.showInputDialog(null, "Enter customer credit card number");
00087 Cust.credit_card_num = Input;
Input = JOptionPane.showInputDialog(null, "Enter customer Phone number");
00089 Cust.phone_num = Long.parseLong(Input);
00090 Input = JOptionPane.showInputDialog(null, "Enter customer Zip Code");
00091 Cust.zip_code = Long.parseLong(Input);
00092 Input = JOptionPane.showInputDialog(null, "Enter customer credit rating");
00093 Cust.credit_rating = Input.charAt(0);
00094 return Cust;
00095 }
00096
00102 public static void printCustomer(Customer cust)
00103 {
00104 System.out.println("The customer name = "+cust.name);
00105 System.out.println("The customer phone number is: "+cust.phone_num);
00106 System.out.println("The customer credit rating is: "+cust.credit_rating);
00107 System.out.println("The customer address is : "+cust.address);
00108 System.out.println("The customer city is : "+ cust.city);
00109 System.out.println("The customer zip code is: "+cust.zip_code);
System.out.println("The Customer credit card number is: " +
cust.credit_card_num);

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 9 of 78


00111
00112 }
00118 public static void changeCustData(Customer cust)
00119 {
cust.name = JOptionPane.showInputDialog(null, "Enter new customer name");
cust.address = JOptionPane.showInputDialog(null, "Enter new customer address");
00122 cust.city = JOptionPane.showInputDialog(null, "Enter new customer city");
00123 cust.credit_card_num = JOptionPane.showInputDialog(null,
00124 "Enter new customer credit card number");
00125 cust.phone_num = Long.parseLong(
00126 JOptionPane.showInputDialog(null, "Enter new customer phone number"));
00127 cust.zip_code = Long.parseLong(
00128 JOptionPane.showInputDialog(null, "Enter new customer zip code"));
00129 cust.credit_rating = (JOptionPane.showInputDialog
00130 (null, "Enter new customer phone number")).charAt(0);
00131
00132 }
00136 public static void printSeparator( )
00137 {
00138
System.out.println("=================================================");
00139 }
00140 }//Listing 4.2

Table 4.1 gives a summary of all member methods of class DriverCustomer.

Summary Of Methods For Class DriverCustomer


static void changeCustData(Customer cust)
Prompts user to change customer data and changes it as per
user input.
static Customer getCustomer()
Gets customer data from user input and returns to the caller
method.
static void main(java.lang.String [] args)
Calls necessary methods to:
1. . Get customer data
2. Print customer data
3. Alter Customer data
Informs user accordingly.
static void printCustomer(Customer cust)
Prints customer data to standard output.

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 10 of 78


static void printSeparator()
Prints a separator line on standard output.
Table 4.1

It contains five static methods, including the main. The methods getCustomer,
printCustomer, and changeCustData, populate, print, and change a Customer
object respectively. The main method calls the other four methods. In Listing 4.2,
we create an object of class Customer by making the call to its default constructor
(Line 53). Java creates a reference Cust, which holds the memory address of the
location where the Customer object5 thus created is located on the heap. Then
program calls (Line 56) the printCustomer method and pass the object Cust to it, to
print its contents created by the default constructor provided by Java (Figure 4.5).

Object created
by default
constructor.

Data in object
Cust after line
58 is executed

Data in object
Cust after line
63 is executed
FIG. 4.5 : Output of Listing 4.2

5
The address of this object in heap memory can be printed by using the code:
System.out.println (Cust.hashCode( )); The source of this and other hidden method in class
Customer will become clear after we have discussed inheritance in Java. However, the address of all
Java Objects cannot be printed by using this method.

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 11 of 78


Top portion of output prints the contents of the object Cust created by the default
constructor provided by Java. One notices that all the String data members have
been set to null, whereas the long (integral data types) have been set to zero. The
default constructor provided by Java initializes the class data members that are
primitives and objects, to fundamental values, according to the scheme shown in
Table 4.2 below.

Data type Initialization value


char ‘ ‘ (blank space) Java provided default
byte, short, int, long 0 constructor initializes all
float, double 0.0 object data members to
boolean false null value.
All Objects null
Table 4.2

Notice that String data type is not initialized to an empty String. Rather all Java
objects are initialized to a null value. In Figure 4.4, we did not show the inner details
of the object Cust on the heap. We can do so now (Figure 4.6).

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 12 of 78


S tru c tu re o f O b je c t C u s t in H e a p M e m o ry

Stores Zero
z ip _ c o d e Stores null

c ity
Stores ‘ ‘
a d d re s s

c re d it_ ra tin g

phone_num

nam e

c re d it_ c a r d _ n u m

FIG. 4.6 “Schematic” map of the object Cust after being created by the
call on line 53 in Listing 4.2

In Figure 4.6 we have shown all the String data types of same length on X-axis, as
their initial size with null stored in them is expected to be the same. This is also true
of long data types (phone_num and zip_code). The credit_rating, which is the char
data type, will be smaller in size than all others. Upon further program execution,
the map of object Cust remains essentially unchanged except that values in the data
members are altered.

Program calls the method getCustomer (Line 58) to populate the customer fields
with user-inputted values. A second call to method printCustomer prints these
values (Figure 4.5). Then program calls the method changeCustData (Line 63) and
passes to it the customer object Cust, created and populated in the main method.
The method gets user input for new values for the fields of Customer object passed
to it. The main then calls printCustomer again (Line 66) to print the altered
Customer object (lower portion of Figure 4.5).

Passing of Objects to Method in Java


You may recall from previous chapter that all parameters in Java are passed by
value, as it lacks the C++ type mechanism for pass by reference. You may then
argue, that how is it that method changeCustData is able to alter the values stored in
Object of type Customer? Understand that in method call on line 63

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 13 of 78


changeCustData (Cust); Cust is not the Customer type object itself (which is located
on the heap). Rather Cust is a reference (pointer to it), which stores the address of
the Customer object on the heap. Method changeCustData is passed this address by
value, and that remains unaltered in the main. However, since we have an access to
the fields of this no-name object, through its reference Cust, we are able to change
the values of its fields. The objects, which allow modification to them after being
created, are called mutable objects. There are Java objects, however, which cannot
be modified, and they are called immutable. All Java wrapper classes and String
class objects are immutable6. We emphasized in the early part of this chapter that
all Java references, once initialized, either store null or the address of no-name
object on the heap memory. If the data outputted in Figure 4.5 are used as input,
then schematically the state of Cust before being passed to method changeCustData
(before line 63) and after line 63 looks like Figures 4.7A and 4.7B.

FIG. 4.7A: Object Cust in main method before line 63 is executed


The state of the object7 Cust as returned by method getCustomer is shown in Figure
4.7A (after execution of line 58 in Listing 4.2). Assume that memory address
assigned to it is 3000. You would notice that String type fields such as name, city,
etc., do not store the string directly. Rather they store the memory address on heap
where the particular String is stored. For example, since the field name is actually a
reference to a String type object, which stores “John Doe” in it, its address 5000 is
stored in it. The primitive data fields store the value directly in them. For example

6
We shall discuss later as to what makes objects immutable.
7
We assume that data shown in the output in the Figure 4.5 are used.

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 14 of 78


the zip_code field stores 90509 directly in it. Conclusion is of course that all String
type fields only store the memory address of actual string object on heap, whereas
all primitives store the value directly in the storage location.

The method changeCustData alters the data values in the Customer type object
passed to it. The state of object after execution of line 63 in Listing 4.2 is shown in
Figure 4.7B. Once again we assume that the data outputted in Figure 4.5 was used
as input.

FIG. 4.7AB: Object Cust in main method after line 63 is executed

In comparing the Figures 4.7A and 4.7B, you would notice that the address stored in
Cust, for the Customer type object on heap remains unchanged. However, all values
(data and addresses) stored in the fields of the object themselves have changed. We
expect the values stored in fields like zip_code and phone_num to change as they are
storing primitive data types. But, why would the addresses stored in the String fields
also change? This has to do, once again, with the immutability of Strings in Java.
Inside the method changeCustData, when we make an assignment such as:

cust.name =
JOptionPane.showInputDialog (null, "Enter new customer name");

The method showInputDialog of JOptionPane class actually returns a new String


with the new memory address (8000 in Figure 4.7B), which is stored in the field

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 15 of 78


cust.name, and old string (“John Doe”) is deleted by the Java Virtual machine
through a process called garbage collection.

What if we add the following line as the first line in the body of method
changeCustData (just before line 119), that is before any data input is done?

cust = new Customer( );

Do we still expect the method changeCustData to change the data of Customer and
pass it back successfully to the main method? Figure 4.8 shows the output when we
make just this change in Listing 4.2 and recompile and run the program.

FIG. 4.8 Output after adding the line in method changeCustData (See
text).

The results of Figure 4.8 are a bit astounding. Just by adding the line

Customer cust = new Customer ( );

as the first statement in method changeCustData disables the process of data update
and the object Cust in main method remains unaltered. This is because in the above
statement the reference cust stores a new value supplied by the constructor call on
the right hand side. Since all parameters in Java are passed by value only, this new
value stored by reference cust stays a local value, and the values stored by the object

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 16 of 78


pointed by reference Cust (created on line 58 in Listing 4.2) in main remain
unchanged.

You would recall that pass by value mechanism sends only a copy of the variable in
the caller method to the called method. Therefore, when method changeCustData
receives, from main, a reference to Customer type object, an additional reference is
attached to the Customer object on heap, which is then passed to the method being
called. Just before the code execution begins in method changeCustData, the state of
object pointed to by Cust in main can be shown by the Figure 4.9.

Reference
Cust in the
main
method

cust 3000

Copy of Cust in main


passed to method
changeCustData FIG. 4.9A

Notice here, because in call by value mechanism, only a copy of the variable is
passed to the called method, the object with name “John Doe” in it has two
references Cust and cust attached to it. Cust is in main method and its copy cust is
passed to the changeCustData method. But, as soon as the method changeCustData
executes the code line:

Customer cust = new Customer ( );

the state of system changes to Figure 4.9B.

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 17 of 78


Reference
Cust in the
main Now the
method object in
main
cannot be
changed!

No longer a copy of New


Cust in main passed Customer
to method
Object
changeCustData

cust 12000

FIG. 4.9B: State of system after the statement cust = new Customer( ) is
executed in the method changeCustData as its first statement

Once the reference passed to a method is assigned to a new object on heap (as in
Figure 4.9B) then any changes made by the method are only done locally to this new
object. It is no longer attached to the object, whose reference was passed to it at the
time of call.

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 18 of 78


We can thus draw the following conclusions about passing objects as method
arguments in Java:

• If the object is mutable, then the method getting the object as an


argument can change its inner state as long as prior to change
that reference is not assigned to a new object.
• The state of immutable objects, such as Strings and wrapper
classes cannot be changed after their construction. Passing them
to a method is no exception to this rule.
• If the method to which object is passed assigns that object
reference to another object, then all changes made after that are
local and are not reflected back in the caller method.

Confusion between an object and its reference


In C++, the objects can be created on the stack, which is impossible in Java.
Therefore some C++ programmers at times have difficulty in understanding the
difference between objects and their references in Java. Because in Java all objects
are no-name objects, we at times end up using the name of the reference to an object
as the name of the object itself. A C++ programmer may look at the method header
as below and conclude that since Customer object is being passed by value, it cannot
be changed by the method changeCustData.

public static void changeCustData (Customer cust)

Key to remember is that it is not the object that is being passed to the method.
Rather it’s the pointer or reference to the object (on heap) that is being passed to the
above method. And Java’s pass by value mechanism ascertains that method
changeCustData cannot alter the memory address stored in the reference cust in the
caller method. However, subject to the conditions that Customer object is mutable,
and method changeCustData does not assign the reference passed to it to another
memory location, the data in the object pointed to by its argument cust can be
changed. We show a simple example in Appendix 4A (Listing A4.1), where we print
the memory address of an object (MyObject an instance of class MyClass) before
passing its reference to the method myMethod, in the method locally and after the
call to MyMethod is finished. All three addresses are same. That proves that in
Java, when we pass reference to an object to a method, the data stored in that
reference is passed by value, which cannot be altered in the caller method by the
method being called.

Pitfall: Attempts to use an object reference, which stores a null value


In Java all local variables or constants must be initialized before they can be used.
For example the following will be a compile error in Java.

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 19 of 78


Compile error. Attempting
String First_name; to use a local variable
int length = First_name.length( ); before its initialization.

The below will not give a compile error, yet the program will crash upon execution,
with a cryptic message similar to the one shown in Figure 4.10.

String First_name = null; No compile error.


int length = First_name.length( ); However, the program will
crash when it is run.

FIG. 4.10
Most important word to notice in the above message is the word
“NullPointerException” This is Java’s way of telling you that in your program, you
have attempted to use an object reference which has a null value stored in it. In our
code snippet above we tried to call the length ( ) member method of class String
using a String type reference which has a null value stored in it. We show another
example of use of a null reference, which is connected Binky Pointer Fun Video
illustrating the hazard of using Java references with null value in them. Let us look
at the code in Listing 4.3.

class IntObj
00002 {
00003 public int value;
00004 }
00005
00006 public class DriverIntObj
00007 {
00008 public static void main(String [] args)
00009 {
00010 IntObj X = null;
00011 IntObj y = null;
00012
00013 X = new IntObj( );
00014
00015 X.value = 42;
00016 /*Uncommenting and compile/running the line below will
00017 crash the program with NullPointerException message*/
00018 //y.value = 13;
00019 // The line below will work as y points to the pointee of x.
//This is called sharing

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 20 of 78


00020 y= X;
00021
00022
00023 y.value = 13;// Now 13 is stored in the field called value.
00024
00025 }
00026 }//Listing 4.3
Table 4.3 explains the code in Listing 4.3 in detail. In this description, we are calling
the creation of object on heap by making a constructor call by name pointee. For
example in line 13 of Listing 4.3, the reference X has a pointee created by the
constructor call made for the class IntObj.
Description Code Picture of Program memory
1. Allocate two
references x and y. IntObj x = Both x
and y
Allocating the null; store null
references does not
allocate any IntObj
pointees. (Lines y=null;
10,11)
2. Allocate a pointee
x = new
and set x to point to
IntObj( ) Still stores null!
it. (Line 13).
3. Store 43 into the
value field of the
x.value = 42;
pointee of x. (Line
15)
4. Try to store 13 in
y.value. This
crashes because y
does not have a
y.value
pointee -- it was = 13;
never assigned one.
(Line 18)
5. Assign y = x;
so that y points to
x's pointee. Now x y = x;
and y point to the
same pointee -- they

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 21 of 78


are "sharing".
(Line 20)
6. Now try to store
13 in the value field
of y. This time it
works, because the y.value = 13;
previous assignment
gave y a pointee.
(Line 23)
Table 4.38: Details of Listing 4.3 and Binky Video

Watch the Binky Video now.

Listing 4.3 shows that when a memory location is shared by more than one
reference, then any of them can alter its contents.

Question:
1. For Customer class in Listing 4.1, we write the following code in the main
method:

Customer Cust1 = new Customer ( );


int length = (Cust1.name).length ( );
Explain what will happen when this code is compiled. Explain what will happen
when it is run. What kinds of error or results are expected (if any) in each case?

2. What will be the output if the following lines are added on lines 24 and 25 of
Listing 4.3.
y.value+=y.value;
System.out.println (x.value);

Member access Control in Java classes


All modern enterprises need data to support their business functions. For example,
a marketing department in a company would need data on existing and prospective
customers. Billing department may need data on existing customer’s account
number and preferred billing methods. The enterprise may store such customer
data in files or databases. When retrieving customer data from files or database, the
data processing software may use an array9 of customer objects to process it

8
Thanks to Professor Nick Paralente at Stanford University, who is original author of the Binky
Video and the Table 4.3.
9
Other possible storage techniques may include linear data structures, such as linked list or non-
linear structures, such as binary trees or graphs. These topics are discussed in a data structure
course.

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 22 of 78


further. Considering the Listing 4.1 as a template for the customer data, different
departments in the company may need different portions of it to support their
business functions. For example, the marketing department may only need the
name, address and phone number. The sales department may need contact
information and credit rating. The billing department may need access to entire
customer record, including the credit card number. The central question then is that
should marketing department have an access to customer’s credit card number,
even though it would not need it. Yet, if customer data are stored in a class like
Listing 4.1, where all data members are declared public, then using the dot
operator, all of class members become accessible to all people. Java added an extra
facility, which allows programmer to block read and write access to any class
member, such that using the dot operator could not access the member. One such
access mechanism is called private access. If in class Customer, we wish to remove
direct access to credit card number then Java allows us to declare that field private.

Declaring a class member private blocks direct read and write access to
it by using the dot operator.

The modified customer class will then be written as follows (Listing 4.4).
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class Customer
{
public String name; //stores name of customer
public long phone_num; //stores phone number
public char credit_rating; //stores credit rating
public String address; //stores street address
public String city; //stores city
public long zip_code; //stores zip code
private String credit_card_num;//stores credit card number
}//Listing 4.4. The access to field credit_card_num is made private
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

Notice that now the code snippet shown below in main would give a compile error.

Customer Cust1 = new Customer ( ); Compile error! The field


Cust1.credit_card_num = “12345667”; credit_card_num is no longer
permitted direct access.
The process in which Java allows programmer to control the access to the members
of a class is called “Access Control”.

Access Control is important, because it restricts the unauthorized people from


having the access to the data they may not need, and introduces the first layer of

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 23 of 78


security in the software implementation. However, the data hidden from user by
using the keyword “private”, must be made visible some how to those personnel,
who actually need those data. For example, the billing department will need the
customer’s credit card number. How should one make this field of customer data,
visible to billing department? Java allows an interface or a public method to be
written as a part of class, which will facilitate the access to the private data
members. For example, we can write an instance member method called
getCreditCardNumber, which will return customer’s credit card number as a
string. In the manner similar to data being class members, Java allows the methods
to be class members as well. How would the method getCreditCardNumber look
like? It is very simple actually, as it has only one return statement as below.
public String getCreditCardNumber( )
{
return credit_card_num;
}
Methods, which allow the client an access to the private data members, are called
public interfaces. Similarly, a method setCreditCardNumber will also be required to
change the customer credit card number if needed at some point. This method
would look like the Listing below.
public void setCreditCardNumber( String New_Card_Num)
{
credit_card_num = New_Card_Num ;
}
The methods that allow read access to a restricted (private) data member are some
time called “getters”. Similarly, the methods, which allow the write access to
restricted data members, are called “setters”. The class Customer, including the
getter and setter for the private field credit_card_num would look like the Listing
4.5 below.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class Customer
{
public String name; //stores name of customer
public long phone_num; //stores phone number
public char credit_rating; //stores credit rating
public String address; //stores street address
public String city; //stores city
public long zip_code; //stores zip code
private String credit_card_num;//stores credit card number
public String getCreditCardNumber( )
{
return credit_card_num;
}

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 24 of 78


public void setCreditCardNumber( String New_Card_Num)
{
credit_card_num = New_Card_Num ;
}
}//Listing 4.5
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Notice that now the private data member credit_card_num of an object of class
Customer may be written into, or may be read using the following type of code in
the main method of another class10.
Invokes the code in method
Customer Cust1 = new Customer ( ); setCreditCardNumber and
sets the private member
credit_card_num to new value
12345667.

Cust1. setCreditCardNumber (“12345667”);

System.out.println (“The customer credit card number is = “ +


Cust1.getCreditCardNumber( ));
Invokes the code in method
getCreditCardNumber to print the
private member credit_card_num.

Messenger Receiver Relationship


One can conceive the relationship between an object calling the non-static member
method by using the dot operator, and the method as a receiver and messenger
relationship. Object is the receiver of the message from the method, which is the
messenger. In response to the message from member method, the object may do one
of the followings:
1. Alter its state. For example, the state of the object Cust1 is
altered, when the following method call is made.
Cust1.setCreditCardNumber (“12345667”);
The method setCreditCardNumber sends a message to the receiver Cust1,
asking it to change its field credit_card_num to a new value passed as an
argument. The object Cust1 gets the message and changes its state

10
Classes, which use other classes in their code or as data members, are called client classes. For
example the Customer class is the client of String class.

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 25 of 78


accordingly. The member methods, which alter the state of the
object, are called “mutators” or transformers.
2. Observe its state with out changing it. The object may cause a side
affect as needed by the method or return some information about
it. The method getCreditCardNumber falls in this category. If we wrote a
Customer class member method called printCustomer as to print Customer
data, it would cause a side affect of displaying customer data, and would be
also be called an observer.

Only instance methods have messenger/receiver relationships with the class objects.
For example when one calls the Math library static method sqrt in the manner
below:

double root = Math.sqrt (4.0);


neither is any change being made to an object of Math class, nor is any member
datum of Math class being observed or printed. We can therefore conclude that
static methods “have no receivers”; the way instance methods do.

Questions
1. In the code snippets below, which identifier or portion is the messenger and which
one is a receiver?

A]
String Greeting = “Hello”;
int len = Hi.length ( );
B]
String Distance = "Smile".substring (1, 5);

C]
int val = (new Integer (55)).intValue ( );

Would the code in snippet C compile?

Java classes, encapsulation, and Data Abstraction


Before introduction of classes, for example in C programming, the data, whether
they were local variables, or user defined (like C struct), were passive entities, as
they were acted upon by the methods defined globally. Data, and the program
intelligence to process them (i. e. methods) were separated. Introduction of classes
in programming languages, allowed the methods, which must act on the data to
become part of the class, or overall user defined data type. This allowed the data
and its intelligence to be encapsulated together in one class definition. This
process of putting the data and the methods relevant to their processing

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 26 of 78


in one entity (called class) is termed encapsulation. For example, take the
Object Customer, which we have been discussing in this chapter so far. Apart from
data or attributes, what other intelligence the object Customer may need, so that it
can be taught to do certain things for itself, such that methods external to the class
Customer would not be needed to perform those functions? Some things that we
may wish the object Customer to do by itself can be as follows:
1. Print the object Customer to standard output.
2. Fills an instance of class Customer with user inputted data.
3. Determine if two instances of Customer class have same content.
4. Be able to access the private data members and return them to the
calling code.
5. Be able to change the state of object Customer by altering its
private fields.
All of above capabilities can be imparted to the object Customer by writing
proper member methods for the class Customer. For example, the goal #1 can be
accomplished if we write a member function printCustomer, such that it can
print the customer object to standard output. Goal #2 can be accomplished by a
member method, which is similar to the method getCustomerData, in Listing
4.2. Goal #3 can be accomplished by a member method, which compares each
field of this customer with the other and returns true if all fields of two
customers are same11. Goals #4 and #5 can be accomplished if we provide “get”
and “set” functions for private members of the Customer class, so that, the
methods with name starting with “get” can return the value stored in the private
field in the object. The methods with names starting with “set” can take an
argument and set the particular private field of the object, to the value passed to
the method. Before we even write this expanded Customer class, we write the
documentation to describe all of its member methods, data members. Table 4.4
gives the summary of public member methods of expanded class Customer.

Summary of Methods For expanded class Customer


String getAddress()
Return the address for the customer

String getCity()
Return the city for the customer
String getCreditCardNumber()
Return the credit card number for the customer
char getCreditRating()
Return the credit rating for the customer

11
We will skip coding of methods of this type, until we have learned about control structures in Java.

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 27 of 78


void getCustomer()
Gets the Customer data from user input.
String getName()
Returns the name of the customer.
long getPhoneNumber()
Return the phone number for the customer
long getZipCode()
Return the zip code for the customer
void printCustomer()
Prints the customer data to the standard output.
void setAddress(String address1)
Sets the value of field address.
void setCity(String city1)
Sets the value of field city.
void setCreditCardNumber(String credit_card_num1)
Sets the value of field credit_card_num.
void setCreditRating(char credit_rating1)
Sets the value of field credit_rating.
void setName(String name1)
Sets the value of field name.
void setPhoneNumber(long phone_num1)
Sets the value of field phone_num.
void setZipCode(long zip_code1)
Sets the value of field zip_code.
void transferData(Customer Customer1)
The method transferData copies the data from Customer
object passed as a method argument to the caller object.
Table 4.4
Understand that the client of class Customer does not need to see its source code in
order to be able to use it. After all so far we have been able to use java.lang.String
class, with out seeing any of its source code. However, we have information and
specifications on how to create objects of class String and how to use its member
methods to process Strings. This technology, where user is only provided the
details of how to use a class with out seeing its source code is called
“information hiding”. Information hiding is important because it hides the
complex details of a software component from the client and present to them only
the details of their interest. Information hiding is closely related to data abstraction.
The process of providing client using a class, the abstract view of the

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 28 of 78


class, its members, and methods is called data abstraction, which has
grown as a new paradigm in the object-oriented programming.

Listing 4.6 gives the code for expanded class Customer and its driver class.
00001 import javax.swing.*;
00005 class Customer
00006 {
00011 private String credit_card_num;
00015 private String name;
00019 private long phone_num;
00025 private char credit_rating;
00030 private String address;
00034 private String city;
00038 private long zip_code;
00039
00040 //member methods
00045 public String getCreditCardNumber( )
00046 {
00047 return credit_card_num;
00048 }
00049 //************************************************
00054 public void setCreditCardNumber(String credit_card_num1)
00055 {
00056 credit_card_num = credit_card_num1;
00057 }
00058 //***********************************************
00063 public String getName()
00064 {
00065 return name;
00066 }
00067 //***********************************************
00072 public void setName(String name1)
00073 {
00074 name = name1;
00075 }
00076 //***********************************************
00081 public long getPhoneNumber()
00082 {
00083 return phone_num;
00084 }
00085 //***********************************************
00090 public void setPhoneNumber(long phone_num1)
00091 {
00092 phone_num = phone_num1;
00093 }
00094 //***********************************************

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 29 of 78


00099 public String getAddress()
00100 {
00101 return address;
00102 }
00103 //***********************************************
00108 public void setAddress(String address1)
00109 {
00110 address = address1;
00111 }
00112 //***********************************************
00117 public char getCreditRating()
00118 {
00119 return credit_rating;
00120 }
00121 //***********************************************
00126 public void setCreditRating(char credit_rating1)
00127 {
00128 credit_rating = credit_rating1;
00129 }
00130 //***********************************************
00135 public String getCity()
00136 {
00137 return city;
00138 }
00139 //***********************************************
00144 public void setCity(String city1)
00145 {
00146 city = city1;
00147 }
00148 //***********************************************
00153 public long getZipCode()
00154 {
00155 return zip_code;
00156 }
00157 //***********************************************
00162 public void setZipCode(long zip_code1)
00163 {
00164 zip_code = zip_code1;
00165 }
00166 //***********************************************
00170 public void printCustomer ( )
00171 {
00172 System.out.println ("The customer name = "+ name);
00173 System.out.println ("The customer phone number is: "+
phone_num);

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 30 of 78


00174 System.out.println ("The customer credit rating is: "+
credit_rating);
00175 System.out.println ("The customer address is : "+ address);
00176 System.out.println ("The customer city is : "+ city);
00177 System.out.println ("The customer zip code is: "+ zip_code);
00178 System.out.println ("The Customer credit card number is: " +
credit_card_num);
00179 }
00180 //***********************************************
00184 public void getCustomer()
00185 {
String Input = JOptionPane.showInputDialog (null, "Enter customer name");
00187 name = Input;
00188 Input = JOptionPane.showInputDialog (null, "Enter customer address");
00189 address = Input;
00190 Input = JOptionPane.showInputDialog (null, "Enter customer City");
00191 city = Input;
Input = JOptionPane.showInputDialog (null, "Enter customer credit “
+” card number");
00193 credit_card_num = Input;
Input = JOptionPane.showInputDialog(null, "Enter customer Phone number");
00195 phone_num = Long.parseLong(Input);
00196 Input = JOptionPane.showInputDialog(null, "Enter customer Zip Code");
00197 zip_code = Long.parseLong(Input);
Input = JOptionPane.showInputDialog(null, "Enter customer credit rating");
00199 credit_rating = Input.charAt(0);
00200 }
00207 public void transferData(Customer Customer1)
00208 {
00209 address = Customer1.address;
00210 city = Customer1.city;
00211 credit_card_num = Customer1.credit_card_num;
00212 credit_rating = Customer1.credit_rating;
00213 name = Customer1.name;
00214 phone_num = Customer1.phone_num;
00215 zip_code = Customer1.zip_code;
00216 }
00217 }
00219 public class DriverCustomer3
00220 {
00221 public static void main(String [] args)
00222 {
00223 Customer Cust1 = new Customer();
00224 printSeparator();
System.out.println("Printing customer information stored in empty “ +
“customer object:");

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 31 of 78


00226 Cust1.printCustomer();
00227 printSeparator();
00228 Cust1.getCustomer();
00229 System.out.println("Printing customer information after data input:");
00230 Cust1.printCustomer();
00231 printSeparator();
00232 System.out.println("Changing customer data now");
00233 System.out.println("The current customer name = " +
Cust1.getName());
00234 Cust1.setName(JOptionPane.showInputDialog(null, "Input new name"));
00235 System.out.println("The current customer address = " +
Cust1.getAddress());
00236 Cust1.setAddress(JOptionPane.showInputDialog(null, "Input new
address"));
00237 System.out.println("The current customer city = " +
Cust1.getCity());
00238 Cust1.setCity(JOptionPane.showInputDialog(null, "Input new
city"));
00239 System.out.println("Printing customer information after changing
data:");
00240 printSeparator();
00241 Cust1.printCustomer();
00242 printSeparator();
00243 System.exit(0);
00244 }
00248 public static void printSeparator()
00249 {
00250
System.out.println("=============================================");
0025}
00252 }//Listing 4.6
Notice that in the source code for class Customer we placed data members first and
then we code the class member methods. Though Java allows placing of class data
and methods in any order one wishes, still it is important that data be placed first
and the methods following them. This is because the reader of source code will
quickly become aware of the data design included in the class, which is important to
understand the class design.

The diagram in Figure 4.11A abstracts the details of the class Customer12.

12
This is actually an incomplete diagram as the methods inherited from the java.lang.Object class
are not shown. We would discuss that after study of inheritance.

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 32 of 78


printCustomer private data: 2003
phone_num 423511
“Nell Dale”
name 2003
getCustomer
zip_code 90009

Setters 3000
City 3000

O ther fields not show n to


“Austin”
getters im prove clarity.

Custom
. er ( )
.
Java provided
. default constructor

FIG. 4.11A
Since, in addition to the data members, now class Customer contains member
methods, we show them in while ovals lying half way in the class and outside it. This
indicates that these public methods form the interface between the class and its
external client. The oval setters represents all the set methods in the class (Figure
4.11B), and getters as all the get methods (Figure 4.11C).

Fig. 4.11B
Setter oval in
Figure 4.11A

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 33 of 78


Fig. 4.11C
Getter oval in
Figure 4.11A

Member selection inside the class instance methods


Let us now discuss some details of the member methods of the class Customer (lines
170 t0 179 in Listing 4.6). Notice that this member method accesses the private data
members of its own class by using the syntax reflected in the statement on line 172
as
System.out.println ("The customer name = "+ name);
In above statement, the name is the String field of the class Customer. This simply
means that instance member methods of a class can access all of its members
directly. Static member methods can only access static members directly, and they
can access non-static members after creating an instance of class locally and then
using dot operator for member selection.

Reference to self or “this” reference


Java embeds a reference (pointer) in each class, which points to itself. This reference
is hidden in the sense that it is automatically passed as a hidden argument to all
non-static member methods. This reference to self, if one chooses, may be used for
the selection of non-static class members inside the body of non-static methods. For
example the line 172 of Listing 4.6 may be re-written equivalently as (Figure 4.12):
---------------------------------------------------------------------------------------------------
System.out.println ("The customer name = "+ this.name );

Self reference (pointer) to


class Customer provided Selected non-static
by Java data member called
name
FIG. 4.12
---------------------------------------------------------------------------------------------------

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 34 of 78


The utility of this reference will become clear when we use it in constructor
chaining, which allows Java to pass default arguments to constructors. Another
simple application of this reference would be in writing the setter methods in a
simpler way as follows (Figure 4.13).
public void setName(String name)
{
this.name = name; Local variable
} called name

Qualified name of
class instance variable
called name FIG. 4.13
------------------------------------------------------------------------------------------------------------
Code in Figure 4.13 is simpler at least in one way, that the programmer can use the
identifier for the argument to the method setName, same as the identifier for the
instance variable to store customer name. This simplifies the process of name
selection. We already mentioned that this reference is not available inside the static
member methods. It also cannot be used to select static class members. This is the
summary of the characteristics of this reference:
• All non-static member methods and constructors in Java
are provided a reference to the class itself indicated by the
reserve word this13.
• this reference can be used to perform member selection for
only non-static members, inside only instance or non-static
methods/blocks14.
• this reference is not available outside the declared class. In
this sense, it can be considered as a hidden argument passed
to all non-static class member methods and blocks.
Understand that if we replace the code in Figure 4.13 as below (Figure 4.14), it will
not be a compile error!

13
A bit later we shall see that this keyword can also be used as to make constructor calls, in which
case it acts like a class name.
14
Inside a class, Java allows declarations of blocks, which can be static or non-static. Blocks are
essentially unnamed member methods, which have no-names and cannot take any arguments. They
can only be used to cause some side affect (input, output) or set the values of class level data
members. We discuss them later on after we discuss constructors.

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 35 of 78


------------------------------------------------------------------------------------------------------------
public void setName (String name)
{ Not a compile
name = name; error!
}
FIG. 4.14
In this instance, the program will simply reassign the current value of local variable
name to itself, and the class variable name remains unaltered (thus failing the goal
of method setName). Therefore, the local variable using the same identifier as the
one used by class member shadows the class level identifier. Therefore if a local
identifier has the same name as the class level identifier, then one must use this
reference to select the class level identifier or member providing the latter a
qualified name See Figure 4.13).

Member selection in Objects passed as an argument to member


methods
Inside the non-static methods the non-static members of a class can be selected
directly by their names or by qualifying them by using the self reference this. There
are situations where an object of the class itself is passed to a member method. The
member selection in the passed object of same type is done simply by using the
familiar dot operator. We take an example from the method transferData, whose
header is given below:

public void transferData(Customer Customer1)

This method simply copies the data in Customer type object Customer1 into the
calling object. The line 209 in Listing 4.6 shows the necessary syntax (Figure 4.15).

address = Customer1.address;

The address field of


The address field of the Customer
the instance that instance passed to
will call method method transferData
transferData.
Alternate syntax:
this.address is also Instance of Customer class
OK. passed to method transferData

FIG. 4.15
-----------------------------------------------------------------------------------------------

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 36 of 78


In process of copying the data fields of Customer1, a Customer type object, the dot
operator is required to get read and write access to the members of Customer1. The
left hand side (variable address in Figure 4.15) identifies the caller object, and right
hand side identifies the address field of the object passed as an argument to the
method transferData. Note that this “courtesy”, where a dot operator can be used
for member access is only extended to the objects that are same15 class type. Private
data members of classes different from Customer, which are passed to its member
methods cannot be selected by using the dot operator. Rather a public interface or
method to access such data would be needed. Let us show this by an example.
Assume that we have a method setZip, in class Customer which takes as an
argument of LongObj class shown in Figure 4.16 below.

public class LongObj


{
private long data;

public void getData ( )


{
return data;
}
}

Method setZip presumed to be added in Customer class.

public void setZip( LongObj zip1) Compile error! No direct


{ read/write access to private data
zip_code = zip1.data; members of those classes which
are not of type Customer.

zip_code = zip1.getData ( ); This is OK, as the public


interface to get the value
} of private member called
data is being used.
FIG. 4.16
------------------------------------------------------------------------------------------------------------
The first code line in the Customer class member method setZip will cause a compile
error, as data is a private field in a class (LongObj), which is not of type Customer.
However, the second line assignment is ok as now a public interface called getData
is being used to access the private member data of class LongObj.

15
Borrowing the term from psychology, we can call the same type of object passed as a method
argument as “gregarious object”.

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 37 of 78


Output From Listing 4.6
None of the methods of class Customer in Listing 4.6 involve any complex
algorithm. Therefore we proceed to discuss the output from the main method of
class DriverCustomer3, which tests the class Customer.

The main method of driver class DriverCustomer3, creates an object of class


Customer at line 223. It calls the printCustomer method (line 226) to print the
object Cust1 created by default constructor provided by Java. The results are no
different from the top portion of the output shown in Figure 4.5. Then main calls the
member method of Customer class getCustomer (line 228) to populate the fields of
pointee or object of Cust1 with the user inputted data. The contents of the object so
populated is printed by code line 230. Since in this new Customer class, there is no
method that changes all Customer fields at once, we first print the current value of a
field and then use the set method for that field to change it to a new value. For
example code line 233 prints the current name of the customer stored in object
Cust1. Line 234 calls the setName method to change the name of the Customer
stored in object Cust1.

In this call we can see the messenger/receiver relationship between a method and its
object rather clearly. Here the messenger, the method setName sends a message to
its object Cust1, asking to change its name field from current value to the user
inputted one. Receiver Cust1 obliges by changing its name field as the code in its
method setName executes. Figure 4.17 shows the dynamics of messenger/receiver
relationship between object Cust1 and its method setName.

FIG. 4.17A

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 38 of 78


The messenger setName sends a message to its receiver Cust1 that change your
name field to “Mary Doe” (Figure 4.17A). The receiver object obliges by executing
the code in its messenger method (in this case setName) and alters its state in which
name field is set to Mary Doe (Figure 4.17B).

FIG. 4.17B
In Similar fashion the receiver object Cust1 interacts with messengers setAddress
and setCity on code lines 236 and 238 and changes them to the user inputted values.
Finally the line 241 prints the altered object Cust1. The results of the execution of
Listing 4.6 are shown in Figure 4.18 below.

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 39 of 78


FIG. 4.18
We remove the output caused from the lines before line 227 as that simply shows the
data stored in the constructor initialized object.

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 40 of 78


Concept of invariants in software and component design
The invariants are important in Software engineering as they help eliminate
software bugs. What are invariants? Invariants are conditions that maintain certain
state and obey certain requirements inside a software block, method, component or
inside a class object. You perhaps know little bit about invariant inside a pretest or
posttest loop. In a pretest loop the invariant is that pretest condition must be true at
the loop entry point for its next iteration to take place. In similar manner in a
posttest loop the invariant is that the post-test condition must evaluate to true for
the next loop iteration. We illustrate the concept of invariant for classes by taking
an example a class that may be written to manage your account in the bank. For the
sake of simplicity we consider only three member methods in this class, which code
the following processes that a bank account may undergo to make it usable. These
are:
1. Deposit money in account
2. Withdraw money from the account
3. Inform as to what the balance is?
For now we are ignoring the complexity of calculating and adding the interest on
deposit and assume that it is an account where no interest is paid. Let us write a
blank body of our minimal bank account class below (Figure 4.19 ).
------------------------------------------------------------------------------------------------------------
public class BankAccount
{
private double balance; // current balance in the account

public double getBalance ( ) // gets the current balance


{
return balance;
}

public void withdraw( double amt) // withdraws amt from the balance
{
//code to be filled
}

public void deposit( double amt) // adds amt to balance


{
//code to be filled
}
}//FIG. 4.19
------------------------------------------------------------------------------------------------------------
Assume that bank is generous and allows you to maintain a zero minimum balance
in your account, which means that you can open an account even if you have zero
dollars in it. Then what would be an invariant for class BankAccount, which must

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 41 of 78


always be true for all objects of its type? Obviously the invariant is that data
member balance can never be negative (otherwise bank is stuck trying to get its
money back from people who carry negative balance). This also means that:
• At the entry and exit points of all class member methods the
invariant (balance >=0) must be maintained.
• The invariant may not hold temporarily for a short while inside a
member method. However it must be maintained before the
method exits.
Let us see if Java provided default constructor maintains the invariant that balance
not be negative. Recalling the fact that all double type data members are set to 0.0
by default constructor, it would maintain the invariant because as soon as we create
the object of type BankAccount as:

BankAccount My_Account = new BankAccount ( );


The invariant is maintained at the end of constructor call. The method getBalance is
not a mutator, as it simply returns the value of the balance. Therefore it also
maintains the invariant. However, things are not that simple for methods withdraw
and deposit. What if the amount withdrawn amt, which is passed to the method
withdraw is larger than the balance available? Code inside the method withdraw
would have to be written in such a manner that upon its entry point and exit point
the invariant is maintained and balance does not go below zero! Similar arguments
can be applied to the method deposit. What if by mistake the data entry clerk enters
a negative number which is passed as an argument to the method deposit? It is
method’s responsibility16 that upon entry to it, and upon exiting from it that the
invariant (balance not negative) is maintained. How that is done in the code is an
implementation detail to be considered in later chapters.

Question:
If the bank using the BankAccount class here introduced a condition that every
customer has to maintain at least $25 minimum balance in their accounts, then
would the default constructor provided by Java maintain the class invariant?

16
Methods, which put no responsibility on user of any kind are called total methods in computer
science. A total method will handle all errors that are caused by the user data input. Total methods
cannot be written with out the use of a technology called “exception handling”, which we discuss
later. All methods cannot be written to behave as total methods.

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 42 of 78


Explicit constructors17 (Role in creating immutable objects, maintaining
invariants and program testing)
The default constructor provided by Java may not be sufficient for one or more of
the following reasons:
1. It may fail to maintain the invariant required for the class objects.
2. The immutable objects in Java are created in their final state only
by their constructor (as after their birth, they can never be
altered), and Java provided default constructor may not be able
to construct the state of the object in useful form(s) needed by the
user.
3. Testing of program for a class with large number of data
members may require more than one constructor to create objects
in different states.
4. Java default constructor is always either public or package-
private18. However there are situations that one may not wish
instantiation of a class, in which case the constructor must be
declared private.
We gave example earlier that as soon as a BankAccount class would require that the
balance field always conform to some positive minimum amount, the Java provided
default constructor will fail the invariant as it always sets floating point and integral
data members to some zero value. Another example is, let us say we write a class
called Fraction, which has two fields – numerator and denominator. Knowing that
the value of fraction is always:

numerator/denominator

one can surmise the invariant for the Fraction class. This invariant is that
denominator can never be zero! Obviously Java provided default constructor for
class Fraction will fail to maintain this invariant.

In second reason in the list above we mention that immutable objects are created in
their final state by the constructor. If variety of final states are required for an
immutable object, then obviously one constructor would be inadequate. Imagine if
the class java.lang.String , which creates immutable objects had only Java provided
default constructor? No one would be able to create a String other than the one that
contains empty character set.

17
Most books define explicit constructor as the one which carries one or more arguments. We extend
this definition to include those constructors, which have private or protected access levels, even if
they are argument-less. We define the explicit nature of a constructor lying in the fact that it is
explicitly different from the default constructor that Java would automatically provide.
18
The package private members of a class are allowed read and write access using the dot operator
with in all classes in that package. Making a member package private requires leaving out the access
control specifier in the member declaration.

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 43 of 78


There are situations where a class is used only as a package for its static methods. In
such case one should not be able to instantiate an object of such class as it has no
instance methods. Take for example the class java.lang.Math, whose sole purpose is
to provide static methods facilitating arithmetical calculations. It explicitly declares
its constructor private, to prevent its instantiation as the default constructor
provided by Java can only be either public or package private.

Having established that in our class design we may need user defined constructors,
we explain how they are designed. An explicit constructor carries one or more
parameter in its argument list or is declared private or protected19. Foe example
take the case of class java.lang.String. Apart from having a constructor such as:
String Empty = new String ( ); // creates a zero length string

It has an explicit constructor of the form

String Name = new String (“John”); //works the same was as = “John”
Which creates a string with contents “John”. This technology, where a class is
provided more than one constructor is also called “constructor overloading”.
Table 4.5 shows some examples of explicit constructors, and constructor overloading
from various Java classes.
Java Class Explicit ConstructorAction by constructor
java.lang.Math private Math ( ) Prevents instantiation
of Math class
public String (String Str) Instantiates a String
object with string Str
java.lang.String public Instantiates a String
String(StringBuffer buffer) object with contents
same as String Buffer
object buffer
public Integer (int value) Sets the int field of
Integer object to the
value int
java.lang.Integer public Integer (String Str) Creates an Integer
object whose int field
has the numerical value
contained in String Str
Table 4.5

19
Protected access control is provided by the keyword protected, which we shall discuss in more
detail in chapter on inheritance.

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 44 of 78


We now show the creation and testing of an explicit constructor and constructor
overloading for our class Customer. This time we also separate out the class
Customer file from its java file as that is how we intend to test our future classes.
The source code for the explicit constructor designed by us for Customer class is
given below in Listing 4.7A.
00001 import javax.swing.*;
00005 class Customer
00006 {
Argument-less constructor is
00011 private String credit_card_num;
needed to compile/run to run the
00015 private String name;
code like :
00019 private long phone_num;
Customer Cu = new Customer( )
00025 private char credit_rating;
00030 private String address;
00034 private String city;
00038 private long zip_code;
00039 Explicit
00040 //member methods constructor
00046 public Customer ( )
00047 {
00048 //no code needed
00049 }
00061 public Customer(String credit_card_num1, String name1,long
phone_num1,char credit_rating1, String address1, String city1, long zip_code1)
00063 {
00064 address = address1;
00065 city = city1; Sets the address field of
00066 credit_card_num = credit_card_num1; the object to the
00067 credit_rating = credit_rating1; argument address1.
00068 name = name1;
00069 phone_num = phone_num1;
00070 zip_code = zip_code1;
00071 }

//Assume that we have filled the code lines 45 to 216 from the //Listing
4.6 here.
}
Listing. 4.7A
The explicit constructor shown by code lines 61 to 71, simply takes all seven fields of
Customer class as arguments, and sets each field to the corresponding value passed
to it. For example the first code line sets the address field to the address1, the value
passed to the constructor call. You would notice that we have included in the Listing
4.7A, an argument-less constructor shown in code lines from 46 to 49. Currently we
put no code in this constructor. The reason for including this code-less & argument-
less constructor is as follows. Java provides a default constructor for a class, as long
as no user written constructors are present. However, as soon as user includes even
a single class constructor, then Java takes away the constructor it would have

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 45 of 78


provided otherwise. You would see that if we take away the argument-less
constructor we have included here and then try to make a constructor call as follows
in the driver program, then we would get a compile error20.

Customer Cust = new Customer ( ) ; Would cause a compile error if


the argument-less constructor
on lines 46 to 49 (Listing 4.7A)
is not included.

Listing 4.7B shows the class DriverCustomer4 used to test our explicit constructors
in two forms.
00001 import javax.swing.*;
00002 public class DriverCustomer4
00003 {
00004
00005 public static void main(String [] args)
00006 {
00007 printSeparator( );
00008 Customer Cust1 = new Customer ("22334455","John Doe",9142367789L,
00009 'A',"1122 Pine Avenue", "Georgia",90509);
00010
00011 Cust1.printCustomer( );
00012 Customer Cust2 = new Customer(
00013 JOptionPane.showInputDialog(null, "Enter customer credit card number"),
00014 JOptionPane.showInputDialog(null, "Enter customer name"),
Long.parseLong(JOptionPane.showInputDialog(null, "Enter customer Phone number")),
JOptionPane.showInputDialog(null, "Enter customer credit rating").charAt(0),
00017 JOptionPane.showInputDialog(null, "Enter customer address"),
00018 JOptionPane.showInputDialog(null, "Enter customer City"),
Long.parseLong(JOptionPane.showInputDialog(null, "Enter customer Zip Code")));
00020 printSeparator( );
00021 Cust2.printCustomer( );
00022 System.exit(0);
00023 }
00027 public static void printSeparator( )
00028 {
00029
System.out.println("=============================================");
00030 }
}//Listing 4.7B

20
This is one of the major Java Gotcha for students. They would write a code without any
constructor, and all the code calling default constructor works fine. Then instructor may suggest that
include an explicit constructor in the code as an added functionality. All of a sudden the code lines
calling the default constructor cause compile error. This simply because upon inclusion of any user
coded constructor Java takes away the default constructor it provided.

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 46 of 78


In Listing 4.7B we create an instance of class Customer by calling explicit
constructor (lines 8 and 9), where we have hard coded all the constructor arguments
passed to it. However, another advantage of explicit constructor is that it can be
called to construct an object in its final state directly by taking the user input. We
do that in call to create object Cust2 in code lines 12 to 19. Let us take a portion of
this constructor call and analyze it. The lines 12 and 13 are:

Customer Cust2 = new Customer(


JOptionPane.showInputDialog(null, "Enter customer credit card number"),
………. //Other arguments

Notice that here we are calling the method showInputDialog of JOptionPane class
directly inside the call to constructor to get the user input for the customer credit
card number. Above forms of use of explicit constructors are shown only for
understanding their functioning. In enterprise software development, extensive data
validation is done before those data are passed to the constructor. After object
Cust2 is created by direct user input from user it is also printed to console. The
output of Listing 4.9B is similar to the bottom two third of Figure 4.5. We
summarize the function of Java constructors as follows21:

• Constructors have the same name as their class


• Constructors have no return type
• Constructors have zero or more arguments
• Constructors are not methods! You can only call a constuctor
using "new ClassName"
• Constructors are called when objects are created (using "new")
• new BankAccount( arg1, arg2 ) will call the BankAccount
constructor with two arguments
• Like methods, the argument list used (actual parameters) must
match the constructors definition (formal parameters)

Alternate Initialization techniques


Java allows two more techniques for the initialization of instance variables, These
are called:
• Direct assignment
• Using initialization blocks
Both above techniques are better suited for initialization of static class data
members, however, Java would allow you to use them for instance variables as well.
We take a simple example to illustrate as to how the three (direct assignment,
initialization block, & constructor) work. Assume that we define a class called

21
Thanks to Roger Whitney at SDSU, from whose web site this summary is taken from.

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 47 of 78


LongObj, which has only one data member called num which is long type. We show
Listing 4.8A, where direct assignment for num is used.
class LongObj
{ 1. Syntax for direct
private long num = 1000L; assignment.
public long getLong()
{
return num;
}
}

public class LongObjDriver 2. Notice that the form


{ of constructor call
public static void main(String [] args) remains unchanged!
{
LongObj My_Long= new LongObj( );
System.out.println(My_Long.getLong());
}
}//Listing 4.8A
------------------------------------------------------------------------------------------------------------
Listing 4.8A shows the syntax for direct assignment (bubble #1). In making this
assignment the class dada member is set equal to a literal constant or to a named
constant. Upon execution the program in Listing 4.8A will print 1000 to the
standard output.

We can also use an initialization block to initialize the value of instance variable
num. In using initialization block the class LongObj of Listing 4.8A will change to
the one shown in Listing 4.8B
------------------------------------------------------------------------------------------------------------
class LongObj
{ 3. Initialization block.
private long num ;

{
num = 1000L;
}
public long getLong( ){
return num;
}
}
// add the code for class LongObjDriver from Listing 4.8A here
//Listing 4.8B

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 48 of 78


An initialization block is just a piece of code enclosed in a pair of curly braces. The
variable being initialized inside the initialization block must be defined before the
physical placement of the initialization block. For example, the following order of
placement would be a compile error!
------------------------------------------------------------------------------------------------------------
class LongObj
{ 4. Compile error! The
{ variable being initialized is
num = 1000L; being defined after the
} initialization block.

private long num ;


public long getLong( ){
return num;
}
}
Listing 4.8B will also print 1000 to the standard output. The initialization block can
call any of the class member methods, and the placement of them with respect to the
location of block is unimportant.

Order of Evaluation
Java allows one to use all three techniques, direct assignment, initialization block,
and constructor call to initialize class instance variables. However, it follows certain
order of evaluation. In object construction, the following order of evaluation is
followed.
1. Direct assignment is executed first.
2. Then the assignment or any other code in the initialization blocks
is executed. There is no limit on number of initialization blocks
used. Initialization blocks are executed in the order from top to
bottom.
3. Finally the constructor is called. If constructors are chained, then
they are called in the order of their chaining.
If all three initialization methods are used, then the final value of the instance
variable will be the one dictated by the last constructor call. Listing 4.8C shows the
example for class LongObj.

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 49 of 78


00001 1. Cosntructor: prints the value of
00002 class LongObj num assigned in initialization
00003 { block and finally the new value set
00005 public LongObj( )
00006 {
on line nine.
00007 System.out.println (
00008 "The value of num from Initialization block = " + num);
00009 num = 3000L;
00010 System.out.println (
00011 "The value of num at the end of constructor call = " + num);
00012 }
00013 2. Direct
00014 private long num = 1000L; assignment
00015
3. Initialization
block.
00016 {
00017 System.out.println (
00018 "The value of num from direct assignment = " + num);
00019 num = 2000L;
00020 }
00021
00022 public long getLong()
00023 {
00024 return num;
00025 }
00026
00027 }
00028
00029 public class LongObjDriver
00030 {
00031 public static void main(String [] args)
00032 {
00033 LongObj My_Long= new LongObj();
00034
00035 System.out.println("The value of num in Driver class = " +
00036 My_Long.getLong());
00037 }
00038 }//Listing 4.8C

In Listing 4.8C, we have placed constructor call before variable declaration on


purpose to show that the location of the constructor body in the class code is
unimportant. As we said before, however, the initialization block must be placed
after the declaration of variable(s) that are used in the initialization block.

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 50 of 78


Following the order of evaluation discussed on page 49, first the direct assignment
sets the value of num to 1000 (Line 14 in Listing 4.8C). The Figure 4.20 shows the
output from the Listing 4.8C.

FIG. 4.20
Then since the initialization block is executed next in order, the code in the block
(line 17 & 18) prints the value of num initialized during the direct assignment. Then
line 19 sets the value of num to 2000. Since constructor is executed last, the control
shifts to line # 7, which is the first line in constructor body. The value of num set in
the initialization block is printed (line 8). Then constructor initializes the num to a
value of 3000 (line # 9) and this value is printed by the call to method println on
lines 10 & 11. In the main, the final value of the num field of constructed object
My_Long is printed on line 35 & 36, which is the same as set by the constructor.

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 51 of 78


Chaining constructors
Java does not have the C++ like facility for passing default arguments to methods
and constructors. In situations, where one needs to get the benefits of default
arguments, Java allows one to chain the constructors together, so that the default
values, different from the Java provided constructor may be set. In constructor
chaining, the argument-less constructor calls the one argument constructor, which
calls the two argument constructor.. and so on. The process goes on until the
constructor with largest number of arguments has been called. The operator this is
used almost as a void method call and given necessary arguments to call the next
constructor in the call chain. We show constructor chaining by expanding our
BankAccount class discussed earlier. In expanding this class, we add customer’s
name, and number of accounts maintained by the customer in the bank. (The
balance field now shows the net balance of all accounts). The class would now have
the fields shown by Table 4.6A.

Summary of Fields for class BankAccount


private double balance
Net balance in dollars for all the accounts in
customer's name.
private Name
java.lang.String Name of the bank customer.
private int num_acts
Number of accounts maintained by the customer.
Table 4.6A
Notice that in chaining constructors, you need number of constructor in a class one
more than the number of instance variables in the class. Our class BankAccount has
three fields, therefore it would require four chained constructors. Since the
invariant to be maintained by the class is that balance >=0.0, we must decide the
default values for the other fields. For name a good default value may be just the
string “name to be entered”, so that we know that this account does not have a
customer name yet. Default value for the number of accounts or num_acts is one as
any new customer would need to begin with at least one account. Table 4.6B gives
the design summary of the four constructor that we would need.

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 52 of 78


Constructor Summary for class BankAccount
BankAccount()
Sets the name to an empty character set, balance to 0.0 and num_acts to one.
BankAccount(java.lang.String name1)
Takes the input for customer name but sets the balance to 0.0, and number
of accounts or num_acts to one.

BankAccount(java.lang.String name1, double balance1)


Takes input for customer name and balance, but sets the number of accounts
num_acts to one.
BankAccount(java.lang.String name1, double balance1,
int num_acts1)
Takes input for customer name, balance, and number of accounts num_acts.
Table 4.6B

The expanded BankAccount class also has the getters, which simply return the vale
of the private data members of the class. We also add a method printAccount, which
simply prints the contents of the object of type BankAccount We design a class
DriverBankAccount to test the chained constructors of our BankAccount class. Both
classes are shown in Listing 4.9 below.
00001 public class BankAccount
00002 {
00006 private String Name;
00010 private double balance;
00014 private int num_acts; 1. Argument-less
00015
constructor
00020 public BankAccount( )
00021 {
00022 this("name to be entered");
00023 System.out.println ("From argument-less constructor.");
00024 }
2. One argument
00031 public BankAccount(String name1) constructor.
00032 {
00033 this(name1,0.0);
00034 System.out.println ("From one argument constructor.");
00035 }

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 53 of 78


3. Two Argument
constructor

00042 public BankAccount(String name1, double balance1)


00043 {
00044 this(name1,balance1, 1);
00045 System.out.println ("From two argument constructor.");
00046 }
4. Three Argument
constructor
public BankAccount(String name1, double balance1, int num_acts1)
00056 {
00057 Name = name1;
00058 balance = balance1;
00059 num_acts = num_acts1;
00060 System.out.println ("From three argument or last constructor in chain.");
00061 }
00065 public void printAccount( )
00066 {
00067 System.out.println("The customer name = " + Name);
00068 System.out.println("The account balance = " + balance);
00069 System.out.println("The number of accounts = " +num_acts);
00070 }
00071 }
//Listing 4.9A The BankAccount Class
The four overloaded constructors for class BankAccount are shown in Listing 4.9A
(code lines 20 to 61 and bubbles #1 to 4). Note that the first three have the first
statement in their body which is of type:

this ( )
where the parentheses include one or more arguments. Using the syntax

this("name to be entered");
the argument-less constructor (code line 22) calls the one argument constructor
which begins on line 31. This almost appears like a void method call, except it is not.
The operator this now acts like a replacement for the class name. We notice that
argument-less constructor calls (line 22) one argument constructor, which calls
(line33) the two argument constructor , which calls (line 44) the final constructor in
chain and the three argument constructor then initializes all the class data members
(lines 57 to 59). We show the action of these chained constructors through the
Listing 4.9B class DriverBankAccount.

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 54 of 78


public class DriverBankAccount
00002 {
00008 public static void main(String[] args)
00009 {
00010 printSep ( );
00011 System.out.println("Section 1");
00012 callDefault ( );
00013 printSep ( );
00014 System.out.println("Section 2");
00015 callExplicit1 ( );
00016 printSep ( );
00017 System.out.println("Section 3");
00018 callExplicit2 ( );
00019 printSep ( );
00020 System.out.println("Section 4");
00021 callExplicit3 ( );
00022 printSep ( );
00023 }
00024 public static void callDefault ( )
00025 {
00026 BankAccount Act1 = new BankAccount ( );
00027 Act1.printAccount( );
00028 }
00029 public static void callExplicit1 ( )
00030 {
00031 BankAccount Act1 = new BankAccount ("John Doe");
00032 Act1.printAccount( );
00033 }
00034 public static void callExplicit2 ( )
00035 {
00036 BankAccount Act1 = new BankAccount ("Mary Doe", 1000.00);
00037 Act1.printAccount();
00038 }
00039 public static void callExplicit3 ( )
00040 {
00041 BankAccount Act1 = new BankAccount ("Miss Informed", 9000.00, 2);
00042 Act1.printAccount();
00043 }
00044 public static void printSep ( )
00045 {
00046 System.out.println ("====================================");
00047 }
00048
00049 }
//Listing 4.9B The class to test BankAccount class

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 55 of 78


The main method in class DriverBankAccount calls five helper methods to test the
chained constructors in the class BankAccount. Table 4.6C gives the summary of all
the static methods in the class DriverBankAccount.

Summary of Methods in class DriverBankAccount


static void callDefault()
Creates a BankAccount object using argument-less
constructor and prints the object.
static void callExplicit1()
Creates a BankAccount object using one argument
constructor and prints the object.
static void callExplicit2()
Creates a BankAccount object using two argument
constructor and prints the object.
static void callExplicit3()
Creates a BankAccount object using three argument
constructor and prints the object.
static void main(java.lang.String[] args)
Calls the four constructors for the class BankAccount and
prints the values stored in its field after each constructor call.
static void printSep()
Prints a line separator like "======="
Table 4.6C
The methods callDefault, callExplicit1, CallExplicit2, and CallExplicit3 create and
print an object of BankAccount type by calling the default, one argument, two
arguments, and three arguments constructors respectively. The example of
constructor call syntax is given by lines 26, 31, 37, and 42 of Listing 4.9B. The
instance method printAccount of class BankAccount is used to print the contents of
its objects. The results are given by the Figure 4.21 below.
====================================
Section 1
From three argument or last constructor in chain.
From two argument constructor.
From one argument constructor.
From argument-less constructor.
The customer name = name to be entered
The account balance = 0.0
The number of accounts = 1
====================================
Section 2
From three argument or last constructor in chain.
From two argument constructor.

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 56 of 78


From one argument constructor.
The customer name = John Doe
The account balance = 0.0
The number of accounts = 1
====================================
Section 3
From three argument or last constructor in chain.
From two argument constructor.
The customer name = Mary Doe
The account balance = 1000.0
The number of accounts = 1
====================================
Section 4
From three argument or last constructor in chain.
The customer name = Miss Informed
The account balance = 9000.0
The number of accounts = 2
FIG. 4.21
------------------------------------------------------------------------------------------------------------
The output is divided into four sections, the section 1 related to the object created by
argument-less constructor, section 2 to the one created by one argument constructor
and so on. In all sections we see that the last constructor in chain (the one with three
arguments) is always called as it is the last link in the chain of constructors. We
analyze the section 1 of the output created by call to method callDefault, as that has
the maximum number of constructor calls in it. callDefault method calls the
argument-less constructor (line 26, Listing4.9B) as:

BankAccount Act1 = new BankAccount ( );

This triggers a chain of constructor and output calls illustrated by Figure 4.22
below.

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 57 of 78


FIG. 4.22
The fist line in the argument-less constructor calls the constructor BankAccount
(String name). Thus control transfer to its first line. This constructor in turns calls
the constructor BankAccount (String name1, double balance1), thus control
transfers to its first line. This constructor calls the last constructor BankAccount
(String name1, double balance1, int num_acts1). The last box in the Figure 4.22
shows that last constructor assigns the class data members to the values passed to it.
Then the last line in last constructor is executed , which creates the first output line
under section1 (Figure 4.21). The control is then passed back to second line of the
constructor BankAccount (String name1, double balance1), which prints the 2nd
output line in section1. Control is then passed to the 2nd line in the constructor
BankAccount (String name) creating the 3rd line of output.. and so on. Once the last
line of first constructor is executed, the chain of constructor calls and outputs from
them is completed. Therefore when the constructors are chained and the largest
number of arguments are N, the call order is:

Constructor (0 args) Æ Constructor (1 args) Æ…. Constructor (N args)

The completion of execution of each constructor takes place in the exact opposite
sequence.

Chaining constructor is a great way to provide special default values to the class
variables and have the flexibility of leaving some variables at default values, while

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 58 of 78


setting others to different values. Chained constructors, however, have a method call
overhead built into them, For example the call to argument-less constructor would
activate a call to all the constructor in the entire chain. This method call overhead
may slow down program execution. The use of chained constructor is done best
when they help maintain some special algorithmic invariant or other special
conditions.

Java requires that no program statements precede the call to constructor using the
keyword this and it must be the first line in the constructor body. For example the
following would be a compile error:
Compile error! No
public BankAccount( ) statements can
{ precede the call
System.out.println ("Argument-less constructor."); using this as a
this("name to be entered"); constructor.
}
However value returning static methods from same class, or instance and static
methods from other classes can be called to provide one or more arguments passed
to this. Of course the argument type and method return types must match or Java
must be able to do a safe implicit conversion. Assume that we add a static method
called setDefaultName ( ) as a member of class BankAccount as follows:

public static String setDefaultName()


{
return "name to be entered";
}

Then we modify the code of argument-less constructor as follows:

public BankAccount( ) This is OK! Call to static methods of


{ same class or value returning
this(setDefaultName( )); methods of other classes can provide
} arguments passed to this.

One can use the call to static methods of the same class inside the call to this because
the static part of an object is already built prior to building the dynamic part using
the constructors.

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 59 of 78


In another rather contrived example we may write the two argument constructor
for the BankAccount class in the following manner.
Call to intValue ( )
public BankAccount(String name1, double balance1) instance method of
{ Integer class.
this(name1,balance1, new Integer(1).intValue( ));
System.out.println ("From two argument constructor.");
}
In above example the object of Integer type is created by the call to constructor new
Integer (1) on the fly and then its instance method intValue ( ) is called to return the
value stored in the Integer object that was created.

Returning this as a value from an instance method


There are situations, where the object in its current state must be returned from an
instance method. In such case returning this can accomplish the objective. Let us
write a form of suggested method deposit in BankAccount class so that the method
returns the BankAccount object after the deposit is added to the balance. One such
form is shown below in Figure 4.23.
public BankAccount deposit ( double amt)
{
/*
code to error check that a negative value of
amt is not entered
*/
balance += amt;

return this;
}//FIG. 4.23
The method deposit here returns a BankAccount type object after adding the amt to
the balance and then returns the current state of the object by returning the self
reference this.

How can one use this form of method deposit? One can cascade several calls to
deposit method when the code snippet given below is executed in the main method
(Figure 4.24).
------------------------------------------------------------------------------------------------------------
BankAccount Act1 = new BankAccount("John Doe",0.0, 1);

Act1 = Act1.deposit(100).deposit(200).deposit(300).deposit(400);

Act1.printAccount( ); Cascaded calls to


//FIG 4.24 method deposit.

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 60 of 78


The output of the code snippet in Figure 4.24 is shown in the Figure 4.25 below.

FIG. 4.25
In the code snippet in Figure 4.24 the second line makes the cascaded calls to the
method deposit. Parsing from left to right, the first call Act1.deposit(100) returns
the object after incrementing the balance by 100. Then this returned object makes
the second call to the deposit method as deposit (200), which returns the object with
balance equal to 300. This returned object then makes the third call to the method
deposit as deposit (300) which returns the object with balance equal to 600. This
process goes on until all the cascaded calls are completed and the final balance is
1000.

static class members


A class can have attributes or data as well as methods declared static. Word static
implies that a static member exists independent of the declaration of instances of a
class. For example if there is a static data member in a class, all instances of such
class will share one copy of that data member. Static member methods can only
refer to and use directly, only those class members, which are also static. That is
because no property of a static member can depend upon any instance of that class.

Static data members and their initialization


The static data members can be initialized inside the class constructors, however
unless there are good reasons to do so, it may not be a good practice. We would
explain reasons in just few moments. The static data members are generally
initialized in one of the following two ways or combining them in some manner:
• Direct assignment
• Use of a static initialization blocks. They must be marked with the
keyword static. For example following is the correct syntax for
declaring static initialization blocks.
static
{ Static initialization block.
// Code placed here
}

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 61 of 78


First we show a trivial example of declaring and initializing the static variables (also
called class variables) (Listing 4.10A).

public class StaticVar


00002 {
00003 private static int stat_var = 10;
First static
00005 static block
00006 {
00007 System.out.println ("The value of stat_var from direct assignment = "
00008 + stat_var);
00009 stat_var = 15;
00010 System.out.println ("At the end of first static initialization block:");
00011 System.out.println ("The value of stat_var = "+ stat_var);
00012 }
00013 Second
00014 static static block
00015 {
00016 stat_var = 25;
00017 System.out.println ("At the end of second static initialization block:");
00018 System.out.println ("The value of stat_var = "+ stat_var);
00019 }
00020
00021 public static int getStatic ( )
00022 {
00023 return stat_var;
00024 }
00025 }//Listing 4.10A
In this Listing line #3 declares and initializes a static int variable stat_var to a value
10. Then inside the first static block, the lines 7 & 8 print the value of stat_var set by
the direct assignment. Then on line nine its value is set to 15. Then the print
statement on lines 10 and 11 prints the value of stat_var set in the first static
initialization block. The second static block sets the value of stat_var to 25 (line 16)
and then prints this new value on lines 17 and 18. The testing of this class is done by
the class called DriverStaticVar shown in Listing 4.10B.
public class DriverStaticVar
00002 {
00003 public static void main(String[] args)
00004 {
00005 StaticVar Temp = new StaticVar ( );
00006 }
00007 }//Listing 4.10B

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 62 of 78


Java requires that whenever a class is instantiated then all of its static blocks
execute even before its instantiation. Same thing happens if any of its public static
methods are called (remember that static methods can be called with out the
instantiation of a class). Therefore all we need to do to run all static blocks and
assignments is to create an instance of class StaticVar, which we do on line five of
Listing 4.10B. The output is shown by Figure 4.23.

FIG. 4.23
The output maps with the lines 7, 8, 10, 11, and 17 & 18 of Listing 4.10A.

We mentioned that even calling any of the static method of a class will make all
static initializations and run all static blocks in it. The code snippet run in main in
Figure 4.24 does just that.
System.out.println(BankAccount.getStatic( ) + " is the final value "
+ "of static variable stat_var as printed\n in the main method");

FIG. 4.24
The first statement in the argument list to method println makes a call to the static
method getStatic of the StaticVar class. This forces to run all the static blocks of the
class, thus producing an output in the Figure 4.25 below.

FIG. 4.25
Because the static assignments and initialization blocks are run first, we see the
output from the two initialization blocks first. Then the getStatic method returns a

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 63 of 78


value of 25, which is printed followed by the literal String. Except for the last two
line the output from Figures 4.24 & 4.25 is identical as it comes from static
initialization blocks.

Using static variables or constants in initialization of instance variables


In spite of their location of declaration in the code, the static variables and constants
can be used in the expression to initialize the instance variables. For example
(Figure 4.26) the following will compile and set variable foo to 5.
public class Test
{
private int foo = foo_bar;
private static int foo_bar = 5;
}
FIG. 4.26
This class will compile because as per rule the static assignments and methods are
done first. Therefore when the statement private int foo = foo_bar; is executed,
the static variable foo_bar already has been initialized. The instance variables, no
matter where they are declared, cannot be used in the expressions initializing the
static variables. For example, the following will be a compile error:

private int foo = 55; Compile error! foo is not


private static int foo_bar = foo; created before the creation
and initialization of
foo_bar

The detailed order of construction of Java object will be discussed under title
“Advanced Object Construction” in the topic on inheritance.

Static member methods


The static member methods for a class do need an instantiation of the class to be
executed. They are therefore called class methods and are called by qualifying them
using the class name. Best example of use of the static methods is the class
java.lang.Math, which contains only static member methods. The following types of
methods must be declared static:
• Methods which return values of static variables22.
• Methods which set the value of static variables.
• Methods that must be called from with in the static initialization
blocks.
• Methods that are called to provide some special value as an
argument to this ( ) constructor (a rare need).
22
Instance methods can get and set the values of the static variables, but it is illogical to do so.

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 64 of 78


• Methods which execute special algorithms which shall work like a
stand-alone method in C/C++.
In terms of messenger receiver relationship we can say that static methods do not
have a receiver, the latter being an object of the class. We have seen some examples
of static methods in this chapter. We shall see more of them in future as we progress
in our journey to learn Java.

Example of use of static data member


We show one rather trivial example of use of static variable by adding a data
member called num_objects in class BankAccount as follows:
public class BankAccount
{
00003 private static int num_objects = 0;
00006 private String Name;
00010 private double balance;
00014 private int num_acts;
00015
00020 public BankAccount( )
00021 {
00022 this("name to be entered");
00024 }
00031 public BankAccount(String name1)
00032 {
00033 this(name1,0.0);
00035 }
00042 public BankAccount(String name1, double balance1)
00043 {
00044 this(name1,balance1, 1);
00046 }
public BankAccount(String name1, double balance1, int num_acts1)
00056 {
00057 Name = name1;
Incrementing the static variable
00058 balance = balance1;
00059 num_acts = num_acts1; num_objects in last chained
00060 ++num_objects; constructor as this one is always
00061 } called!

//Insert the code lines 62 to 70 from Listing 4.9B here


public static int getNumObjects ( )
{
return num_objects;
}
}Listing 4.11A

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 65 of 78


Our purpose here to count number of objects of type BankAccount which are
instantiated in certain execution of our program. Therefore on line #3 we declare a
static int variable num_objects and set it to zero. Knowing that the last constructor
in the chain (lines 55 to 61) is always called during the creation of an object of type
BankAccount we pre-increment the static member num_objects in its last code line
(line 60). Therefore each time when an object of class BankAccount is instantiated,
the num_objects will increment by one. Printing it by using the static method
getNumObjects would give us the number of objects of BankAccount type created.
To test this we modify the class DriverBankAccount as follows (Listing 4.11B).
public class DriverBankAccount
00002 {
00008 public static void main(String[] args) {
00009 testStatic ( );
//comment out code lines 10 to 22
00023{
//Insert code lines from 24 to 47 here
00048 public static void testStatic ( )
{
new BankAccount ();//call1
new BankAccount ();//call2
new BankAccount ();//call3
new BankAccount ();//call4
new BankAccount ();//call5
new BankAccount ();//call6
new BankAccount ();//call7
System.out.println("The number of objects of type BankAccount created "
+ " = " + BankAccount.getNumObjects( ));
}
}Listing 4.11B
The method testStatic is called in the only uncommented line in the main now (line
9). Since it makes seven calls to the constructor of class BankAccount, the output
must confirm that. The Figure 4.27 shows the output confirming our analysis.

FIG. 4.27
--------------------------------------------------------------------------------------------
Constants as class data members
Both static and instance data members can be declared as constants by using the
keyword final in the declaration. Some typical declarations may look like as follows:

private final int CONST_INT_VAR = 10;

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 66 of 78


private static double CONST_DOUBLE_STATIC = 5.5;

From above declarations we may have given an idea that direct initialization is the
only way to set the values of class level constants. This is not so. All the methods
available for initializing the class variables are also available for constant
initialization as unlike C++, Java does not require that constants be initialized in the
line in which they are declared. However they must be initialized before their use.

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 67 of 78


Java Packages
Java allows the writers of Java classes to organize them in packages. Generally the
classes in one package are related in the sense that they are usable as a software
component supplementing certain aspect of program development. Take for
example the package java.io. This package has classes which facilitate the input and
output for Java programs. Similarly the classes in package javax.swing are usable
software components to build Graphical User Interface (GUI) programs. All java
classes reside in some package, except the one’s which have an explicit package
statement on the top reside in a named package. All the classes we have written so
far in this book reside in an “un-named package”. Having your Java classes in a
named package may allow others to use them as a re-usable software component in
their programs. A Java class that must be part of a named package must
have a statement similar to below as the first uncommented line in its
source code!
Must be the first source code line
package xyz; for a class that would reside in a
package named xyz

There are three issues related to the packaged classes in Java, which deserve
discussion.
1. Placing the packaged classes.
2. Compiling the packaged classes.
3. Importing the packaged classes to other classes.
4. Compiling and running an application with imported package in
them.
Let us discuss them all one by one.

Naming and Placing the packages.


A package of classes must be named in such a way, that when package is imported
to be used in other classes, each class package ends up with a unique name. This is
equivalent to C++ namespaces. Sun Microsystems has devised a reverse domain
name system for naming the packages. For example all the packages from Sun for
the sake of simplicity are named as java.YYY or javax.YYY. The YYY is basically
the unqualified name of the package. Since Sun patented the name Java, they do not
have to use the reverse domain name scheme for their java packages. However,
their recommendation is to use the reverse domain name to ascertain that package
developed by one corporation will not have a name conflict with another.

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 68 of 78


For example I own the domain name www.gandhi.net. So packages developed by my
software company can be called as net.Gandhi.xxxx; where xxx will be different for
each package. Let us assume that I develop a package which has classes that
facilitate printing of some standard java Objects. Then I can name my package as:

net.gandhi.print Reverse domain name scheme for


naming packages

The convention is to use all lower cases in package name. A package name does not
have to have dots in it. For example one can simply use the package name Print.
However, if another company also uses the name Print for their package of Java
classes then a client would not be able to use classes from same named packages in
the same program. Therefore the reverse domain name schema makes sense, which
requires dots in the package names.

Creating the directory structure to place classes belonging to a package


Once the package name has been decided, then they must be placed in a directory
structure shown in the example of Figure 4.28.
The location
of folder net
is not
important

FIG. 4.28
If package name is net.Gandhi.print, then we must create three folder such that
folder print is located inside the folder gandhi, which in turn is located in folder net.
All the classes inside the package net.gandhi.print must be located in the folder
print. Therefore the path to the folder containing the classes in above package
would be:
…………..\net\gandhi\print In creating directory structure,
replace the dots in package name
by forward slash.

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 69 of 78


Notice that in creating the directory structure we just had to replace each dot in the
package name by a forward slash23. All the classes that must be members of the
package net.gandhi.print must be physically placed in the folder print shown in the
Figure 4.28.

Compiling the Java classes in a package


Here we only discuss the command line compile technique for compiling the classes
in a package. This is because, each Java development environment may have their
own methodology to develop packages.

While the java files in unnamed packages are compiled by being in the folder or
directory where the class is located, the packaged classes are compiled by being in a
directory or folder in which the last folder in the package is located. For example to
compile the classes in the package net.gandhi.print, the DOS command line must
look like the Figure 4.29 A.

FIG. 4.29A
If we type the following command then the output would show the print folder in
our listing, which has the classes in our package (Figure 4.29B).

……… \net\gandhi>dir Command to get directory listing

Print folder located in


PRINT <DIR> 03-17-04 2:41p print the folder gandhi
FIG. 4.29B
Now to compile all the classes in the folder print, we use the command below

……… \net\gandhi>javac print\*.java

This will create .class files inside the folder print. Usually in finished form the
packaged classes do not contain a main method as their purpose lies in being used as
a software component (example String class). However, during testing and
debugging, temporarily, a class may be provided a main method. In such case the
package statement (the first uncommented line in the java file) must be commented
out and class must be compiled and run in the usual manner. Once class is fully
debugged, the package statement is commented back in and class is recompiled

23
This scheme applies to windows. The structure in Unix would be different

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 70 of 78


using the syntax given on previous page. As an example we create two classes in the
package called net.gandhi.print. These are a class called HelloPrint, and another
one simply called p. The purpose of class p is that it has many overloaded static
methods, each called rint. Therefore, when we call make a call with the syntax

p.rint ( “Hello”);

the console must print out Hello. This saves the effort of typing the whole line such
as System.out.println to get an output. Since the source code of packaged classes is
not revealed to the client, we do not provide it here. Rather the Table 4.7 gives a
summary of just a few of them.
static void rint(char var)
Prints char var to the console without line feed.
static void rint(char[] var)
Prints char array var to the console without line feed.
static void rint(java.lang.Character var)
Prints Character var to the console without line feed.
static void rint(java.lang.Character[] var)
Prints Character var array to the console without line feed.
static void rint(double var)
Prints double var to the console without line feed.
static void rint(java.lang.Double var)
Prints Double var to the console without line feed.
static void rint(double[] var)
Prints double var to the console without line feed.
static void rint(java.lang.Double[] var)
Prints Double array var to the console without line feed.
static void rint(float var)
Prints float var to the console without line feed.
static void rint(java.lang.Float var)
Prints Float var to the console without line feed.
static void rint(float[] var)
Prints float array var to the console without line feed.
static void rint(java.lang.Float[] var)
Prints Float array var to the console without line feed.
static void rint(int var)
Prints int var to the console without line feed.
static void rint(int[] var)
Prints int array var to the console without line feed.
Table 4.7

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 71 of 78


Basically, all single variable outputs which can be done by method println of
PrintStream class, can be done with overloaded method rint of class p, but it will not
do concatenation of the arguments. On the other hand it is superior to println as it
will output arrays of primitives and wrapper classes, with out running a loop. It has
two overloaded methods – rint, which does not give a linefeed and rintln, which
does.

Using packaged classes as a software component in other classes


The class developed as a part of the package can be used, once it is installed on the
client computer using the directory structure shown in Figure 4.28. As we
mentioned before where is the parent directory of folder net is unimportant. Now
we show a simple listing which uses the two classes from package net.gandhi.print.
import net.gandhi.print.*;

public class PrintApp


{
public static void main(String [] args)
{
p.rintln("Using the rintln method of class p in package
net.gandhi.print");
HelloPrint.helloFromPrintPackage();
}
}//Listing 4.12
------------------------------------------------------------------------------------------------------------
Unless Java knows where on the client computer the package net.gandhi.print is
located, it cannot load the classes in that package during compiling and running of
the class PrintApp. Informing Java about the package location is done by using a
classpath flag. To compile the class PrintApp from command line one would need to
provide the path to the parent folder (or directory) of folder net. Therefore the
compile command line becomes:

>javac -classpath .;FULL_PATH_NAME_TO_PARENT_FOLDER_TO_NET


PrintApp.java

Needed so that
Must include the full path to the
java can locate
folder in which the folder net is
files in current
located.
directory as

For example if client installed the net folder in a directory such as C:\GandhiSoft,
then the path name to be used after the flag classpath would be C:\GandhiSoft, and
the compile command line will become

-javac –classpath .;C:\GandhiSoft PrintApp.java

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 72 of 78


Many times the class whose main method we are executing may have used classes
which lies in the same folder. Therefore, for Java to locate them as well, we must
place a .; after the classpath and before the path to the imported package. This is to
be done for compiling as well as for executing. The execution command thus
becomes:

>java –classpath .;FULL_PATH_NAME_TO_PARENT_FOLDER_TO_NET


PrintApp

If the package is located in the folder C:\GandhiSoft, then the execution command
becomes:

-javac –classpath .;C:\GandhiSoft PrintApp.java

Figure 4.30 shows the sample output from the experiment done on my computer.

FIG. 4.30
The compile statement in Figure 4.30 is:
C:\_Test1>javac –classpath .; C:\Courses\Java\LectureNotes\Topic04JavaClassesAndObjects
PrintApp.java

And the execution command is:


C:\_Test1>java –classpath .; C:\Courses\Java\LectureNotes\Topic04JavaClassesAndObjects
PrintApp

Understand that how the package developed by you is installed on client machine is
a different issue. There are many options. You may just ship the folder with your
package to the client (after removing .java files from it) along with the javadoc
documentation, or you may have an installer install it on the client machine. In
addition the client may need the instruction on how to use or set the classpath.

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 73 of 78


Questions:
1. A newbie Java programmer, thinking that Objects passed to a method are always
modifiable, writes the swap method in the class DoSwap as below, so that after the
method is executed the values of Int1 and Int2 are swapped. To their amazement the
method called from main does not swap values. Explain why it would not work?
What will be the value of Val1, and Val2 at the location marked “last line”.
------------------------------------------------------------------------------------------------------------
public class DoSwap{
public static void swap (Integer Int1, Integer Int2){
int temp = Int1.intValue( );
Int1 = new Integer (Int2.intValue( ) );
Int2 = new Integer (temp);
}
public static void main(String [] args){
Integer Val1 = new Integer (5);
Integer Val2 = new Integer (10);
swap ( Val1, Val2);
//last line
}
}
------------------------------------------------------------------------------------------------------------
2. Another newbie Java programmer mistakenly assigns a void return type to a
constructor to the class ShortObj as below:
class ShortObj{
private short num;
void ShortObj ( ){
num = 10;
}
public short getNum ( ){
return num;
}
}

public class DriverShortObj{


public static void main( String [] args)
{
ShortObj My_Short = new ShortObj ( );
System.out.println (My_Short.getNum ( ) );
}
}
What will be the output when the main method for class DriverShortObj is run?
Explain your answer.

3. Why would a compile error be issued by the following statement in a Java


program?
Math Math_Obj = new Math ( );

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 74 of 78


4. In a Java class with N chained constructor the beginning of execution order is as
follows:
Constructor (0 args) Æ Constructor (1 args) Æ…. Constructor (N args)

Write the order in which constructor calls will be completed.


5. (T/F) Constructors can be declared static.
6. (T/F) Constructors can be declared private.
7. Programmers Zack and Zelda argue whether compiling and running StaticVar
shown in Listing 4.10A will create any output? Zack says that there will be no
output as the class StaticVar has no main method. Zelda says that there will be an
output because even if there is no main method the command to execute or
command such as (after compiling):
>java StaticVar
will load the class StaticVar and then it is forced to execute all its static blocks. Who
is right? Discuss your answer.
8. (T/F) The following Java code will give a compile error.
public class Test
{
private int foo = foo_bar;
private static int foo_bar = 5;
}
9. (T/F) The following Java code will give a compile error.
public class Test
{
private int foo = 5;
private static int foo_bar =foo;
}
10. Class level instance variables can be initialized in the following manner.
A] In declaration line by direct assignment.
B] inside one or more initialization blocks’
C] inside one or more constructors
D] All of above.
11. Class level static variables can be initialized in the following manner.
A] In declaration line by direct assignment.
B] inside one or more initialization blocks (static or non-static)
C] inside one or more constructors
D] All of above.
12. Class level non-static constants can be initialized in the following manner.
A] In declaration line by direct assignment.
B] inside one or more initialization blocks
C] inside one or more constructors
D] All of above.
13. Class level static constants can be initialized in the following manner.
A] In declaration line by direct assignment.
B] inside one or more initialization blocks (static or non-static)

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 75 of 78


C] inside one or more constructors
D] All of above.
14. A Java programmer writes the following code for the class Student.
public class Student
{
private static String Name = “”;
private double gpa = 0.0;

public Student (String name, double gpa1)


{
Name = name;
gpa = gpa1;
}

public void printStudent ( )


{
System.out.println (“Name = “ + Name);
System.out.println (“GPA = “ + gpa);
}
}

Then he runs the following code in the main method:


Student St1 = new Student (“John”, 4.0);
Student St2 = new Student (“Mary”, 3.8);
Student St3 = new Student (“Zelda”, 3.5);
St1. printStudent ( );
St2. printStudent ( );
St3. printStudent ( );

What is printed by this code? Explain your answer.


15. In problem 14 what is the output if the code in the main is altered as follows:
Student St1 = new Student (“John”, 4.0);
St1. printStudent ( );
Student St2 = new Student (“Mary”, 3.8);
St2. printStudent ( );
Student St3 = new Student (“Zelda”, 3.5);
St3. printStudent ( );
Explain why is the output in problems 14 and 15 different?

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 76 of 78


Appendix 4A

class MyClass
00002 {
00003
00004 }
00005
00006 public class DriverMyClass
00007 {
00008 public static void main(String [] args)
00009 {
00010 MyClass MyObject = new MyClass( );
System.out.println("Printing the address of MyObject after constructor call in main.");
00012 System.out.println("The address of MyObject = " + MyObject.hashCode());
00013 myMethod(MyObject);
System.out.println("Printing the address of MyObject after call to myMethod.");
00015 System.out.println("The address of MyObject = " + MyObject.hashCode());
00016
00017 }
00018 public static void myMethod(MyClass MyObject)
00019 {
00020 //MyObject = new MyClass( );
System.out.println("Printing the address of MyObject locally in myMethod.");
00022 System.out.println("The address of MyObject = " + MyObject.hashCode());
00023 }
00024
00025 }//Listing 4A.1
Figure 4A.1 gives the output for the Listing A.1.

FIG. 4A.1
The Figure 4A.2 fives the output if the line 20 in Listing 4A.1 is uncommented and
the program is recompiled and run.

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 77 of 78


Different
from other
two
addresses

FIG. 4A.2
Why does the output in Figure 4A.2 show a different address for MyObject inside the
method MyMethod now? Explain.

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 78 of 78


Chapter 5 Selection Control Structures in Java

Chapter to be written ☺
Chapter 6 Looping Control Structure

This chapter is to be written ☺


Chapter 7 – Additional Control Structures And Scope Rules

This chapter is to be written ☺


CS3 – Topic 8
Author: Satish Singhal, Ph. D.
Version – 1.0
Standard Input and Output in Java

Computer software processes data. In data processing the programs in software


would accept data from user and/or output data to same or other user. The “user”
may be a human, or a machine. Many examples of data input sources known to us
are: using keyboard, data files, and databases, pointing devices, scanners, electronic
instruments or other computers. The outputted data may be directed to a console,
graphical displays, files, databases, electronic devices, or other computers. In this
chapter we only discuss the standard input and output (IO). In standard IO, the
software would accept data input either from a keyboard or from an ASCII file and
output data to the computer console and/or to ASCII file.

First let us understand the concept of standard input and output. You may not have
been aware of the fact that your computer is always in standby mode to either
accept data from keyboard or to display data on monitor console. We call the data
stream flowing from keyboard to computer memory as “standard input stream”,
and the one flowing from computer memory to monitor as “standard output
stream”. The situation is very similar to the one shown in Figure 8.1 below.

FIG. 8.1
In Figure 8.1 the keyboard may be replaced by an ASCII file and monitor by
another or same file. You may consider these data streams as “files” which are
always open as long as your program is running. You may have seen at least one
manifestation of always-open output stream, when a device error would give you
warning through “blue screen of death” (Figure 8.2).

CS3 Java – Topic 8: Standard IO (Singhal) Page 1 of 99


Data
inserted
by
operating
system
into
standard
output
stream

FIG. 8.2
In Figure 8.2 the operating system halts your program and injects the warning data
in the output stream flowing to your monitor.

Because Java knows that the inward flow of data to a program or outward flow,
written to a file may be interrupted due to the failure of devices, it takes special
precautions during IO, to prevent data corruption. This precaution is exercised
using a technology called “exception handling”, which we shall discuss in detail in
chapter 12. To handle such error conditions, Java requires that programmer
enclose the code accepting user input1 or file output, in special blocks, which upon
impending failure, activate objects to inform user of the failure that took place.
These objects are of type Java class IOException2 in java.io package. Since we need
to wait to learn more about the exception handling, until we do, we tell main and
other methods to exempt us from the requirement of enclosing data input/output
part of the code in special “java required blocks”. This exemption3 is granted if we
put the line:

throws IOException

after the header of main or any other method performing IO. The line above uses
the Java keyword throws and the phrase “throws IOException” effectively inform
compiler and JVM that IO errors (and resulting IOException) will not be handled
by the method. Thus we alter the header of this “exempted” main as:

1
Input using a JOPtionPane’s method showInputDialog is exempted from this requirement.
2
The IOExceptions are also called “checked exceptions” as they are checked by the compiler at
compile time.
3
We state emphatically that exemption from IOException which we are seeking here, only for the
ease of student learning, shall never be sought while developing enterprise software!

CS3 Java – Topic 8: Standard IO (Singhal) Page 2 of 99


Grants code in main exemption from special
requirements to handle IO errors.

public static void main (String [] args) throws IOException

Input From Keyboard/File4


In Java most activities, data IO being one of them, require use of some class objects.
One of he Java class that facilitates the data input from keyboard/file is called a
BufferedReader class, use of which requires importing the package java.io in our
programs. As the name of the class implies, its object reads the text from the
standard input stream and stores in a buffer (before passing to the program). The
buffering is done for data reading efficiency5. The default size of data reading buffer
is large enough for most purposes, though a user-defined size can be used as well.
The process of using objects of BufferedReader class may involve the following
steps:
1. Create an object of BufferedReader class and in doing so attach it
either to the input from keyboard or from a file.
2. Use one of its methods to either read data line by line or character
by character.

The step one requires instantiating an object of BufferedReader class by calling its
constructor. The constructors in Table 8.1 are provided.

Summary of Constructors for class BufferedReader


BufferedReader(Reader in)
Create a buffering character-input stream that uses a default-sized input
buffer.
BufferedReader(Reader in, int sz)
Create a buffering character-input stream that uses an input buffer of the
specified size.
Table 8.1

Notice that class BufferedReader does not have an argument-less constructor.


Rather both constructors take as an argument an object of another class called
Reader. Therefore the instantiation of an object of BufferedReader class using the
first constructor in Table 8.1 would look like something like this:

4
In this chapter by name file we would always mean an ASCII file.
5
It can be quite wasteful to read character one by one and make a trip each time to the program
memory to transport it.

CS3 Java – Topic 8: Standard IO (Singhal) Page 3 of 99


--------------------------------------------------------------------------------------------
BufferedReader Key_Board = new BufferedReader ( );

Would take an appropriate object


of type class Reader as an
argument.
FIG. 8.3
The object needed as an argument by the constructor shown in Figure 8.3 is of type
class java.io.Reader. When we learn about inheritance (chapter nine), we
shall see that Java objects may be given “similar” identities by invoking
a property called polymorphism, such that when an object of one class
is expected as an argument, an instance of a related class may be also be
passed to it instead6. One such related class is InputStreamReader, whose object
may be passed as an argument to the constructor of BufferedReader class, when the
data input from keyboard is needed. Therefore the constructor call in Figure 8.3 can
be broken down as follows (Figure 8.4).
--------------------------------------------------------------------------------------------
Needs an object, which will bind keyboard
strokes to the object Isr.

InputStreamReader Isr = new InputStreamReader( );

BufferedReader Key_Board = new BufferedReader (Isr);


FIG. 8.4
Note in Figure 8.4 that we create an object of class InputStreamReader, Isr and pass
it to the constructor of BufferedReader class. However, we still need to bind the
object Isr to the keyboard keystrokes. Passing a publicly declared static variable in
System class, called “in”, which is of type class InputStream, does this. Since this
variable is public & static we can get access to it just by using the dot operator as
System.in. Therefore the code snippet to declare Key_Board object in Figure 8.4
expands to (Figure 8.5A).

6
We are not ready to discuss as to why we cannot create an object of class java.io.Reader. This has to
do with fact that certain Java classes are created not be instantiated, but to act as a template for
other classes as their children. These “un-instantiable” parent classes are called abstract classes. We
shall discuss abstract classes in chapter nine.

CS3 Java – Topic 8: Standard IO (Singhal) Page 4 of 99


--------------------------------------------------------------------------------------------
InputStream Key_Stroke = System.in; // Line 1
InputStreamReader Isr = new InputStreamReader(Key_Stroke);//Line2
BufferedReader Key_Board = new BufferedReader (Isr);//Line 3
FIG. 8.5A
We can understand the code snippet in Figure 8.5A as follows:
• Line 1 binds the physical key strokes by the user to the object
Key_Stroke
• Line 2 binds the object Key_Stroke to the object Isr, which does
the conversion from bytes flowing from keyboard into the
character set.
• Line 3 converts Key_Stroke object into a buffered object which
can, now be used to extract user input and place it into program
variables.
You may ask several questions at this point:

Question: Why do we not use the InputStream object directly? Answer is because it
only extracts the stream in bytes and not in character sets. Therefore a conversion
from bytes to character set is needed, which is done by binding it to an object of
InputStreamReader.

Question: Then why not use the InputStreamReader class object instead of
BufferedReader class object? Answer is that InputStreamReader is not buffered,
thus it is inefficient. And due to this non-buffering it can only read character-by-
character, rather than line-by-line.

Therefore we wrap the InputStreamReader object into a BufferedReader type


object to facilitate efficiency and line-by-line reading7. One can also look at the
object bindings done in Figure 8.5A as object pipes connecting to each other (Figure
8.5B).

7
If all this explanation appears labored, then I assure that once you have learned inheritance, it
would all become crystal clear.

CS3 Java – Topic 8: Standard IO (Singhal) Page 5 of 99


FIG. 8.5B
The object pipe System.in connects to pipe InputStreamReader, which in turn
connects to pipe BufferedReader. The composite object accomplishes the objective
of buffered reading from keyboard and input data to program memory in character
form.

Listing 8.1 shows a simple example where the object bindings shown in Figure 8.5A
and B are executed.
00001 import java.io.*;
00002 public class KeyBoardInput
00003 {
00004 public static void main(String [] args)throws IOException
00005 {
00006 InputStream Key_Stroke = System.in;
00007 InputStreamReader Isr = new InputStreamReader(Key_Stroke);
00008 BufferedReader Kb_Input = new BufferedReader(Isr);
00009 System.out.print ("Please type a long string and press enter: ");
00010 String Input = "";
00011 Input = Kb_Input.readLine( );
00012 System.out.println ("You have typed : "+ Input);
00013 System.out.println ("Please type another string and press enter: ");
00014 int ch = 0;
00015 int counter = 0;
00016
00017 while((ch = Kb_Input.read( )) != (int)'\n')
00018 {

CS3 Java – Topic 8: Standard IO (Singhal) Page 6 of 99


00019 if(counter++ == 0)
00020 System.out.println ("You have typed : ");
00021 System.out.print((char)ch);
00022 }
00023 System.in.close( );
00024 }
00025 }//Listing 8.1

The lines six, seven and eight in Listing 8.1 perform the requisite object bindings
shown in Figure 8.5. The BufferedReader class methods readLine (line 11) and read
(line 17) are used to get user input (Table 8.2) from the input stream.
int read()
Read a single character.
String readLine()
Read a line of text.
Table 8.2
The method readLine reads a line of text terminated by end of line character (EOL)
(‘\n’), or line feed character (‘\r’). It returns the line read as a String. On the other
hand the method read, simply reads the inputted stream character by character, but
returns an integer value of it.

On line nine we prompt user to input a string to be terminated by pressing enter


key, thus placing the EOL character at the end of the keyboard input. Line 11
plucks the user inputted string from the input stream and it is printed on line 12.
We shall see that readLine method is the simplest technique to process user input.
At times, however, one needs to read user input (especially ASCII files) character by
character. The method read facilitates that. On line 13 we prompt user to enter
another string. Since the read method returns an integer, we declare an int variable
ch on line 14. The declaration of variable counter and its subsequent use (lines 15, &
lines 19 &20), simply prints the message “You have typed”, just once inside the loop
before the user inputted string is echo-printed. We need to now understand the
construct inside the loop pre-test condition (line 17). It is given as (Figure 8.6):
while((ch = Kb_Input.read( )) != (int)'\n')
FIG. 8.6

You may recall from DeMorgan’s rules discussed in chapter five and its application
to loops in chapter six that the loop pre-test condition must be a negation of loop
termination condition. The loop to read user input character by character using the
method read must terminate when the character ‘\n’ is read in the stream.
Therefore the loop termination condition is:

Termination Condition -> (character read) == ‘\n’


The negation of above condition gives us the loop pre-test condition, which is:

CS3 Java – Topic 8: Standard IO (Singhal) Page 7 of 99


Pre-test Condition -> !( (character read) == ‘\n’)
Pre-test Condition -> (character read )!= ‘\n’

Since the method read returns an int, we cast the character ‘\n’ into an int (Right
portion of Figure 8.6). The advantage of using the assignment:

ch = Kb_Input.read( )

inside the loop expression (line 17) is that we condense two priming reads (one
outside the loop and one inside) into one. Since the character read, ch, is an integer,
we need to cast it back into a character before we print it back to the console (Line
21). The stream is closed by using the close method of InputStream8 class (Line 23).
Figure 8.7 shows the typical output generated by the Listing 8.1.

FIG. 8.7

Notice that we used a rather expanded way of creating a BufferedReader object in


Listing 8.1 (lines six to eight). This was done to illustrate the bindings between
different objects clearly. It is customary to condense those three lines of code into
one by the statement such as:

BufferedReader Kb_Input = new BufferedReader


(new InputStreamReader (System.in));
Compiler parses the right hand expression starting from innermost parentheses and
works its way outwards, creating the same bindings as code lines six to eight in
Listing 8.1 do. The Listing A8.1 in Appendix A shows the version of Listing 8.1,
which uses the exception handling technology, to be discussed in chapter 12.

Reading from an ASCII File and End of File (EOF) Controlled loops
The BufferedReader class object can be used to read data from a file in the manner
similar to the keyboard input. Analogous to the InputStreamReader class, Java
provides us another class called FileReader, which is also of type class Reader. The

8
Recall that object System.in is of type InputStream.

CS3 Java – Topic 8: Standard IO (Singhal) Page 8 of 99


objects of class FileReader can be passed as an argument to the constructor of class
BufferedReader. Before doing this, the FileReader object must be bonded to the
ASCII file that needs to be read by the program. Figure 8.8A shows this two-step
process.
--------------------------------------------------------------------------------------------
Needs the file name string that will bind the
file to the object Freader .

FileReader Freader = new FileReader ( “Full path to Input file”);

BufferedReader Buff_Freader = new BufferedReader (Freader);


FIG. 8.8A
1. First the full path to the file name is passed as a string to the constructor of
FileReader class (First line in Figure 8.8).
2. Then the FileReader object created in step one is passed as an argument to
the constructor of BufferedReader class.
3. The methods readLine and read of BufferedReader class can then be used in
the manner similar to the one used in Listing 8.1.
As indicated earlier, another way to look at object bindings in Figure 8.8A would
be to consider them as pipes connected to each other (Figure 8.8B).

FIG. 8.8B

CS3 Java – Topic 8: Standard IO (Singhal) Page 9 of 99


The object pipe input file name binds to pipe FileReader, which in turns binds to
pipe BufferedReader, and the composite object reads from a file in the buffered
mode.
The description of constructor from FileReader class, which takes a String as an
argument is given below (Figure 8.9).
public FileReader(String fileName)
Creates a new FileReader object, given the name of the file to
read from. If file does not exist, then error condition is created and user
is informed of the non-existence of the file.
Parameters:
fileName - the name of the file to read from. Full path must be
provided. Will not recognize windows style file names with gaps in
them.
FIG. 8.9
Listing 8.2 shows an example of simple file reading and outputting its contents to the
console.
00001 import java.io.*;
00002 import javax.swing.*;
00003 public class SimpleFileReading
00004 {
00005 public static void main(String[] args) throws IOException
00006 {
00007 String Input =
JOptionPane.showInputDialog("Please enter full path to input file name.");
00009 FileReader Freader = new FileReader ( Input);
00010 //Create a bufferedReader Object
00011 BufferedReader Buff_Freader = new BufferedReader(Freader);
00012 String Line = "" ;
00013 System.out.println("printing the contents of file now.");
00014 separator( );
00015 int counter = 0;
00016 while((Line = Buff_Freader.readLine( ))!= null)
00017 {
00018 //Reads line by line and prints to output screen
00019 System.out.println(Line);
00020 if(++counter%30 == 0 )
00021 pause( );
00022 }
00023 Buff_Freader.close( );
00024 //FileReader reads character by character
00025
00026 FileReader In_File = new FileReader(Input);
00027
00028 //read method returns an int unless the EOF is reached in which

CS3 Java – Topic 8: Standard IO (Singhal) Page 10 of 99


00029 //case -1 is returned.
00030 System.out.println("printing the contents of file now.");
00031 separator( );
00032 int val = 0;
00033 counter = 0;
00034 while((val = In_File.read( )) != -1)
00035 {
00036 //Cannot print val, so must convert to char
00037 System.out.print((char)(val));
00038 if(val == (int)('\n'))
00039 {
00040 ++counter;
00041 if(counter%30 == 0 )
00042 pause( );
00043 }
00044 }
00045 In_File.close( );
00046 System.out.println("End of Program");
00047 separator( );
00048 System.exit(0);
00049 }
00050
00051 public static void pause( )
00052 {
JOptionPane.showMessageDialog(null,"Cilck on OK or press enter to continue");
00054 }
00055
00056 public static void separator( )
00057 {
00058 System.out.println("=====================================");
00059 }
00060
00061 }//Listing 8.2

On line seven & eight the user is prompted to enter the full path to file name in the
pop up dialog box. Then in line nine an object Freader of type FileReader is created.
This object is created only if a valid file is found. For example if file does not exist or
input failure occurs, then the error message similar to Figure 8.10 is issued.

CS3 Java – Topic 8: Standard IO (Singhal) Page 11 of 99


Fig. 8.10
The message in the parenthesis in the first two line states that system cannot find the
specified file. However, if file does exist then the FileReader object Freader is
bonded to the BufferedReader object Buff_Freader (Line 9). Now the readLine
method of BufferedReader class can be used to read the data file, just the way it
could read the keyboard input. A file may however, have more than one line.
Therefore we need a test that the end of file has been reached. Every ASCII file has
an EOF character embedded at the end. As the file is written into, the EOF
character keeps moving. Figure 8.11 shows this situation.

FIG. 8.11
When an input file is read (Figure 8.11 ( a)) the file reading marker is placed at the
beginning of the file. In Listing 8.2, the object Buff_Freader will read the file from
beginning, line by line. However, when the end of the file is reached, then readLine
method reads EOF character and returns a null. This forms the basis of designing
our EOF controlled loop (Lines 16 to 22). We call readLine inside the loop
expression, thus eliminating the need for priming read outside the loop. The loop
termination condition must be:

Termination Condition = (String returned == null)

The negation of above condition gives us the loop pre-test condition, which is:

Pre-test Condition = !(String returned == null)


Pre-test Condition = (String returned )!= null

CS3 Java – Topic 8: Standard IO (Singhal) Page 12 of 99


The println method prints the line read (Line 19, Listing 8.2). We add some code in
the loop (lines 20-21) such that it will pause after printing every 30 lines by calling
the method pause, which displays a message pop up box and stops the output, until
user chooses to continue. If file has any data in it, it would be printed to the console.
We calls the close method of BufferedReader class to dissociate the object
Buff_Freader from the file whose name is stored in the string called Input,
effectively closing the file.

A file can be read character by character using both, either the BufferedReader
object or directly using the FileReader object Freader. We create a new FileReader
object In_File (Line 26). The read method works exactly in the manner described
earlier, when we discussed Listing 8.1. However, when the EOF character is read
the method read returns a value of –1. Therefore or loop pre-test condition (Line 34)
ascertains that code in the loop body is iterated, until a –1 value is returned by read
method. The results of second loop (Lines 34-44) are identical to that of the first one,
except for the fact that no input buffer is used, when the object In_File reads the
file.

Comparing ASCII files for exact match


The technology we developed can be used to see if two ASCII files are identical in
their contents. The program would use two BufferedReader objects, each bound to
the respective file. Then both files are read character by character, and as soon as a
character mismatch is detected, a boolean variable that was set to true before loop is
set to false and the loop is exited. If that happens then the files are not identical. In
this case we prime read both files outside the loop. The loop invariant at the entry
point is that none of the file has reached its end. Therefore the loop pre-test
condition is:

Pre-test Condition = (Character Read in First File is not EOF) &&


(Character Read in second File is not EOF)

The algorithm for the program is given by ALG 8.1 below.

ALG 8.1
1. Open both files
2. Set the boolean variable are_same to true;
3. Prime read one character each from opened files
4. while end of file is not reached in either file
4.1 If characters read from two files are not same
4.11 Set are_same to false
4.12 break out of the loop
5. If characters read from each file are not same
5.1 Set are_same to false
6. If are_same is true then print message that files are identical
7. else print the message that files are different.

CS3 Java – Topic 8: Standard IO (Singhal) Page 13 of 99


The step five in the algorithm is crucial, because loop is exited when the end of one
of the files is reached. In a special case when up to the length of smaller file the two
files are identical, the if statement inside the loop (step 4) is not executed. Step five
checks for equality of the characters read after the loop is exited and if they are
unequal then sets the are_same to false.

Listing 8.3 shows the source code.


00002 import java.io.*;
00003 import javax.swing.*;
00004
00005 public class CompareFiles
00006 {
00007 public static void main(String[] args) throws IOException
00008 {
00009 String Input =
00010 JOptionPane.showInputDialog (null, "please enter full path to first file.");
BufferedReader Buff_Freader1 = new BufferedReader(new FileReader(Input));
00012 Input =
00013 JOptionPane.showInputDialog (null, "please enter full path to second file.");
BufferedReader Buff_Freader2 = new BufferedReader(new FileReader(Input));
00015 boolean are_same = true;
00016 int val1 = Buff_Freader1.read( );
00017 int val2 = Buff_Freader2.read( );
00018
00019 while((val1 != -1) && (val2 != -1))
00020 {
00021 if(val1 != val2)
00022 {
00023 are_same = false;
00024 break;
00025 }
00026 val1 = Buff_Freader1.read( );
00027 val2 = Buff_Freader2.read( );
00028 }
00029
00030 if(val1 != val2)
00031 are_same = false;
00032
00033 if(are_same)
00034 System.out.println("The two files tested are identical.");
00035 else
00036 System.out.println("The two files tested are not identical.");
00037
00038 Buff_Freader1.close( );
00039 Buff_Freader2.close( );

CS3 Java – Topic 8: Standard IO (Singhal) Page 14 of 99


00040 System.exit(0);
00041 }
00042 } //Listing 8.3

Following the algorithm ALG 8.1, the source code (Listing 8.3) prompts the user for
the names of files to be compared and opens them (Lines 9 to 14). The boolean
variable are_same is set to true. Then priming read is done on both files (Lines 16-
17). The read method will return –1 if either file is empty, in which case the loop
invariant is not met and program sets are_same to false (Lines 30-31) and skips to
line 37 to print that files are not identical. The loop invariant is met only when both
files are not empty, in which case the loop body compares them character-by-
character. As soon as a mismatch is found the boolean variable are_same is set to
false and loop is exited. The Lines 30 & 31 are executed only in a special case when
up to the length of smaller file, it is identical to the bigger one. Notice that we could
have made loop invariant to be:

Invariant = (Character Read in First File is not EOF) || (Character


Read in second File is not EOF)
The disadvantage of doing so is that loop will continue, even if end of one file has
reached, slowing down the whole algorithm, unless additional conditional tests are
done inside the loop, which make the algorithm unnecessarily complex.

Writing to an ASCII file


Java class PrintWriter can be used to print to standard console and to an ASCII
file. Since we can use the System.out.println quite well for printing to console, we
explore the file writing capability of PrintWriter class. The following constructor
from the PrintWriter class can be used to bind a file name with the PrintWriter
object:

public PrintWriter(Writer out, boolean autoFlush)


Create a new PrintWriter.
Parameters:
out - A character-output stream
autoFlush - A boolean; if true, the println() methods will flush the
output buffer

In above constructor the first argument is of type called Writer. We have mentioned
earlier that in Java, due to property of polymorphism when a class is expected as an
argument to a method/constructor, then an object of a related class can be passed to
it. A class related to Writer is FileWriter, one of whose constructor is given below:

public FileWriter(String fileName)


Constructs a FileWriter object given a file name.
Parameters:

CS3 Java – Topic 8: Standard IO (Singhal) Page 15 of 99


fileName - String The system-dependent filename.

Therefore the mechanism of using PrintWriter class to write an ASCII file


reduces to the following steps:
1. Create an object of type FileWriter and pass to it a string with full
path to file name into which the program must write.
2. Create an object of PrintWriter class and pass to it the FileWriter
object created in step one as the first argument and second
argument must be a boolean true value allowing the automatic
flushing of output buffer.
3. Then use the object created in step two to call methods print and
println as usual to write to the file whose name was used in step
one.

Figure 8.12A shows the schematics of code to execute the steps above.

Needs the file name string that will bind the


output file to the object FWriter.

FileWriter Fwriter = new FileWriter ( “Full path to output file”);

PrintWriter WriteToFile = new PrintWriter (Fwriter, true);


FIG. 8.12A
In terms of object pipes binding to each other, the PrintWriter object created in
Figure 8.12A can also be seen schematically as object shown in Figure 8.12B.

CS3 Java – Topic 8: Standard IO (Singhal) Page 16 of 99


FIG. 8.12B
Let us talk briefly about the second argument in the PrintWriter constructor call.
We set this boolean variable to true to cause flushing of buffer; each time method
println is called by the object WriteToFile. Normally the PrintWriter object will
write to file as soon as the output buffer is full. However, if in the end buffer is not
full, a portion of output may remain unwritten to file unless the method flush from
PrintWriter class is called explicitly. For now we avoid the complication of
remembering to call the method flush at the end, and make the object WriteToFile
as auto flushing type as it will flush the buffer, each time it writes to file when the
buffer is full or when the method println is called (whichever come first).
Understand, however that if your program uses printWriter object and it also uses
only print method, then at some point a call to flush method would be required to
print the un-flushed contents of the buffer. Listing 8.4A shows the details of reading
from a file and writing to another one.
00001 import java.io.*;
00002 import javax.swing.*;
00003
00004 public class SimpleFileWriting
00005 {
00006 public static void main(String[] args) throws IOException
00007 {
00008 String Line = JOptionPane.showInputDialog (null,
00009 "Enter the name of the input file.");
BufferedReader Buff_Freader = new BufferedReader (new FileReader (Line));
00011 Line = JOptionPane.showInputDialog (null,
00012 "Enter the name of the output file.");

CS3 Java – Topic 8: Standard IO (Singhal) Page 17 of 99


00013 FileWriter FWriter = new FileWriter(Line);
00014
00015 PrintWriter WriteToFile = new PrintWriter (FWriter, true);
00016
00017 Line = "" ;
00018
00019 while((Line = Buff_Freader.readLine( ))!= null)
00020 {
00021 //Reads line by line and prints another file
00022 WriteToFile.println (Line);
00023 }
00024
00025 Buff_Freader.close( );
00026 WriteToFile.close( );
00027 System.exit(0);
00028 }
00029 }//Listing 8.4A
We create a BufferedReader object Buff_Freader (Line 10) to read an input file
whose name is stored in String “Line”. User is prompted to provide the name of the
output file (Lines 11-12). The FileWriter object Fwriter is created and is bonded to
the output file (Line 13). Understand that if output file does not exist, then it will be
created. If file with that name already exists then it will be overwritten9! The
PrintWriter object WriteToFile is created (Line 15) by passing to it the object
Fwriter, thus effectively binding the output file to the object WriteToFile. We read
the input file line by line in an EOF loop (Line 19) and write each line to the output
file (Line 22). Finally, both input and output file streams are closed (Lines 25-26).

Example: Processing patient blood pressure data


Many applications require, that program reads certain raw data from an input file
and writes the processed data to an output file. In next Listing we use a nested loop
structure to read from a file that has the patient’s blood pressure data and output to
another file the average blood pressure of each patient and total number of patients
in the file. Figure 8.13 shows the structure of input file.

9
Be sure to not provide an existing file name, as it will be overwritten!

CS3 Java – Topic 8: Standard IO (Singhal) Page 18 of 99


FIG. 8.13

CS3 Java – Topic 8: Standard IO (Singhal) Page 19 of 99


The structure of the output file to be written is shown by Figure 8.14.

FIG. 8.14
The output file must print the patient ID, their average blood pressure and the total
number of patient’s in the file. The algorithm for the whole program is given below
by ALG8.2.

CS3 Java – Topic 8: Standard IO (Singhal) Page 20 of 99


ALG 8.2
1. Get input file name
2. Create a BufferedReader object bound to the input file name
3. Get output file name
4. Create an auto flash PrintWriter object bound to output file name.
5. Print to file the String "Patient ID \t\t BP Average"
6. Print to file the string "--------------------------------------------"
7. Set patient counter to zero
8. Outer Loop
While not end-of-input-file
8.1 Read one line from input file
8.2 Create a StringTokenizer object and bind the String read to it.
8.3 While there are more tokens in StringTokenizer
8.31 Print next token to file as the ID number
8.32 Set variable howMany equal to next token
8.33 Set sum equal to zero
8.34 for index equal to zero and index less than howMany and
incrementing index
8.341 Read and parse BP as next token
8.342 Add BP to sum
8.35 Find Average BP (= sum/howMany). Use proper rounding off
technique
8.36 Print to File Average BP
8.4 Increment the Patient counter
End of input file loop
9. Display total number of patients in the file.
10. Close the input file
11. Close the output file
12. De-allocate any system resources used.

StringTokenizer class
The new Java class used in this algorithm is java.util.StringTokenizer.
Unfortunately, Java does not have an input stream extraction operator like cin>> in
C++, which would eat and throw away the white space and just spit out the data
read in the stream. Therefore we use the class StringTokenizer that can take a
string as an argument and return the space de-limited tokens. Tokenization can be
done de-limited by other characters and on other basis. The constructor for
StringTokenizer class used in the ALG 8.2 is:
public StringTokenizer(String str)
Constructs a string tokenizer for the specified string. The
tokenizer uses the default delimiter set, which is " \t\n\r\f":

CS3 Java – Topic 8: Standard IO (Singhal) Page 21 of 99


the space character, the tab character, the newline character, the
carriage-return character, and the form-feed character. Delimiter
characters themselves will not be treated as tokens.
Parameters:
str - a string to be parsed.
The above constructor binds the StringTokenizer object to the input string str. The
tokens are produced de-limited by space, tab (‘\t’), end of line character (‘\n’), line
feed character (‘\r’), and form feed (‘\f’). Two methods from class StringTokenizer
help us get tokens from its object. First is the method hasNext which tests to see if
there are more tokens available from tokenizer's string. It returns a boolean value.
If method returns true, then a subsequent call to nextToken with no argument will
successfully return a token. The method hasNext returns a true if and only if there is
at least one token in the StringTokenizer after the current position otherwise it
returns false. The method nextToken returns the next string token from the
tokenizer object.

For example the Table 8.3 gives the sequence in which the tokens will be returned
by the method nextToken from the String: “John Doe lives in Torrance, CA.”.
Token sequence Token extracted from String “John Doe lives in
Torrance, CA.”
1 John
Output of Listing
2 Doe
8.4B (below)
3 lives
4 in
5 Torrance,
6 CA.
Table 8.3
We show a small Listing (8.4B) illustrating the use of StringTokenizer class.
-----------------------------------------------------------------------------------------------
import java.util.*;

public class Tokens Binds the string in constructor


{ argument with object St.
public static void main(String[] args)
{
StringTokenizer St =
Returns new StringTokenizer("John Doe lives in Torrance, CA.");
true if
there are while (St.hasMoreTokens ( ))
more System.out.println (St.nextToken( ));
tokens } Returns next
} //Listing8.4B
token

CS3 Java – Topic 8: Standard IO (Singhal) Page 22 of 99


The call to the constructor with the argument as the string to be tokenized creates
the object St. The method hasMoreTokens returns true only if there is at least one
more token in the object St. The method nextToken returns, as a string, the next
token in the object St. The output of Listing 8.4B is exactly shown by the right
column of Table 8.3.

We code the algorithm ALG 8.2 in Listing 8.4C below.

00001 import java.io.*;


00002 import java.util.*;
00003 import javax.swing.*;
00004
00005 public class BloodPressure
00006 {
00007 public static void main(String[] args)throws IOException
00008 {
00009 String Line = JOptionPane.showInputDialog (null,
00010 "Enter the name of the input file.");
BufferedReader Buff_Freader = new BufferedReader (new FileReader (Line));
00012 Line = JOptionPane.showInputDialog (null,
00013 "Enter the name of the output file.");
00014 FileWriter FWriter = new FileWriter (Line);
00015
00016 PrintWriter WriteToFile = new PrintWriter (FWriter, true);
00017
00018 Line = "" ;
00019 WriteToFile.println ("Patient ID" + "\t\t"+"BP Average");
00020 WriteToFile.println ("--------------------------------------------");
00021 int num_pat = 0;
00022
00023 while ((Line = Buff_Freader.readLine( ))!= null)
00024 {
00025 //Create a StringTokenizer object
00026 StringTokenizer Tokens = new StringTokenizer (Line);
00027
00028 while (Tokens.hasMoreTokens( ))
00029 {
00030 //First token is patient ID
00031 String Str = Tokens.nextToken( );
00032 WriteToFile.print (Str+"\t\t");
00033 //Next token is the number of readings
00034 int howMany = Integer.parseInt (Tokens.nextToken( ));
00035 int sum = 0;
00036 for(int index=0; index<howMany; index++)
00037 sum+=Integer.parseInt (Tokens.nextToken( ));
00038

CS3 Java – Topic 8: Standard IO (Singhal) Page 23 of 99


00039 WriteToFile.println ((int)(sum*1.0/howMany + 0.5));
00040 }
00041 num_pat++;
00042 }
00043
00044 WriteToFile.println ("--------------------------------------------");
00045 WriteToFile.println ("The total number of patients in the file were " +
00046 num_pat);
00047 Buff_Freader.close ( );
00048 WriteToFile.close ( );
00049 System.exit (0);
00050 }
00051 }//Listing 8.4C

Lines nine to 16 create BufferedReader and PrintWriter class objects, which bind to
input and output files respectively. Lines 19 & 20 print the header for the output
file. Line 23 runs an EOF controlled loop and create the string Line with containing
the line read from the file. The StringTokenizer object Token is bound to the String
Line read from the file (Line 26). The nested loop structure (lines 28 to 40) gets the
tokens from the StringTokenizer object Tokens and first token is patient ID is
printed directly to output file. The second token (see Figure 8.13 for structure of
input file) has the number of blood pressure readings for one patient. We run a for
loop (lines 36 & 37) to sum up that many blood pressures. Line 39 writes the
average blood pressure to the output file for one patient. The loop guided by method
hasMoreTokens is exited, when all tokens from the object Tokens are exhausted.
The last line in the scope of EOF control loop (line 41) increases the patient counter
by one.

Once the EOF is reached in the input file, the pretest condition in loop (Line 23) will
evaluate to false and loop is exited. Line 45 prints the total number of patients, and
Lines 47-49 close both data files and release system resources. The file shown in
Figure 8.13 creates an output similar to Figure 8.14.

Remembering the previous value


One important class of loop designs require saving the previous value when
iterating through a loop. Java program may have many binary operators. Let us
assume that we need to find out as to how many “not equal to (!=)” operators are
there in a java program file. The algorithm for such a program may be written as
follows (ALG 8.3).

CS3 Java – Topic 8: Standard IO (Singhal) Page 24 of 99


ALG 8.3
Goal: Write a program to count all occurrences of != operator
Strategy: * Read file one character at a time.
• Keep track of current and previous values read.
• If Previous value is ! and current value is = then increase the
counter by 1.
• Otherwise, keep reading.
Program variables needed:
Character/int variables to read and store current and previous values.
Counter to count the number of occurrences of !=.
Some buffered reader object to read the input data file.

Pseudo code:
Open the input data file
Read first character
Read second character
Loop Design
while not end of file
if first character is ‘!’ and second character is ‘=’
increase counter by one
set first character memory = value stored in second character
read next character into the second character memory
Exit loop
Display number stored in the counter.

We code the ALG 8.3 in Listing 8.5.


00001 import java.io.*;
00002 import javax.swing.*;
00003
00004 public class PreviousValue
00005 {
00006 public static void main(String [] args) throws IOException
00007 {
00008 BufferedReader Buff_Freader =
00009 new BufferedReader (new FileReader
00010 (JOptionPane.showInputDialog (null, “Enter the input file name")));
00011 int prev = ' ';
00012 int current = ' ';

CS3 Java – Topic 8: Standard IO (Singhal) Page 25 of 99


00013 int count = 0;
00014 prev = Buff_Freader.read( ); // != !=
00015

00016 if(prev == -1)


00017 {
00018 JOptionPane.showMessageDialog (null, "Input file is empty");
00019 System.exit (0);
00020 }
00021
00022 current = Buff_Freader.read ( ); // != !=
00023
00024 if(current == -1)
00025 {
00026 JOptionPane.showMessageDialog (null,
00027 "Input file only has one character");
00028 System.exit (0);
00029 }
00031 do
00032 {
00033 if ((char) prev == '!' && (char) current == '=')
00034 ++count;
00035
00036 prev = current;
00037 current = Buff_Freader.read ( );
00038 } while (current != -1);
00039
00040 JOptionPane.showMessageDialog (null,
00041 "Number of occurrences of != in file is = "+ count);
00042 Buff_Freader.close ( );
00043 System.exit (0);
00044 }
00045 }
00046
00047 // != != !! ==
Listing 8.5

We take user input for the name of input file and bind it to a BufferedReader object
Buff_Freader (Lines 8-10). The object Buff_Freader opens the input file and reads
the first character (Line 14). An if structure tests for input file being empty, and if
true, displays a message to that affect and exits program (Lines 16-20). For this
program to be useful, the file must have at least two characters. The program
checks if the second character is an EOF (in which case the read method will return
–1). If so then the if structure in lines 24-29 displays a message and program exits.
Inside do while loop (Lines 31-38), first test is made to see if first character is ‘!’ and
second one ‘=’. If both of those assertions are true, then the counter is incremented

CS3 Java – Topic 8: Standard IO (Singhal) Page 26 of 99


by one (Lines 33-34). Then there is the crucial step, where one needs to save the
current value as the previous value (Line 36). The object Buff_Freader reads
another character from file and saves it to the storage location current (Line 37).
The loop exits when current become –1, indicating the end of file having been
reached.

We will not understand this algorithm and source code properly, unless we see it in
action by using a code walkthrough example. The example is shown in Figure 8.15.

FIG. 8.15

The box on left shows the contents of the file. The table on right shows the states of
the three storage locations previous (declared as prev in Listing 8.5), current, and
count. When first two characters are read, the previous contains ‘(‘ and current ‘x’.
The count will be zero because the if condition on line 33 of Listing 8.5 evaluates to
false. Then contents of current storage location are saved in previous, and current is
set to next character, which is ‘ ‘. Count is still zero. In fourth iteration of the do
while loop the previous contains the character ‘!’ and current ‘=’. Only then the if
condition on line 33 evaluates to true and counter is advanced to one.

Appending to an ASCII file


Sometime user would like to append data to the end of an existing file. The
FileWriter class provides a constructor, which when invoked would allow
appending to the output file whose name is passed as first argument. The
corresponding constructor is given below.

CS3 Java – Topic 8: Standard IO (Singhal) Page 27 of 99


///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public FileWriter(String fileName, boolean append)
Constructs a FileWriter object given a file name with a boolean
indicating whether or not to append the data written.
Parameters:
fileName - String The system-dependent filename.
append - boolean variable, if set to true, then data will be written to the
end of the file rather than the beginning.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
If line 14 in Listing 8.4C is altered as follows, then the PrintWriter object
WriteToFile will always append the output to the end of the file indicated by String
Line.

FileWriter FWriter = new FileWriter (Line, true); Would allow


append writing to
the output file
whose name is in
String Line.

Appending to a file is useful when for example we are keeping data on customers in
a file, and when we need to add a new customer, we can just add the data for new
customer at the end of an already existing file. Let us use our Customer class
discussed in Chapter four and design a data entry program to input customer
information. In the event of encapsulation and data abstraction we use the form of
the customer class, where all fields are declared private and getters and setters are
provided for all private data members. Listing 8.6A shows the modified Customer
class, only in the sense that an extra method appendToFile has been added to it. We
only show this extra method.
00001 import javax.swing.*;
00002 import java.io.*;
00006 class Customer
00007 {
//Insert here Lines 11 to 217 of Listing 4.7 in chapter 4
00255 public void appendToFile (String File_Name) throws IOException
00256 {
00257 //check that object at least has a name
00258 if(name==null)
00259 {
00260 JOptionPane.showMessageDialog (null,
00261 "No entry will be done with out customer name.");
00262 return;
00263 }
00264
00265 PrintWriter Append = new PrintWriter (

CS3 Java – Topic 8: Standard IO (Singhal) Page 28 of 99


00266 new FileWriter (File_Name, true), true);
00267
00268 Append.println (name + "\t" + address + "\t"+
00269 city + "\t" + zip_code + "\t" + phone_num
00270 + "\t" + credit_card_num + "\t" + credit_rating);
00271 Append.close ( );
00272 }
00273 }//Listing 8.6A

Method appendToFile takes the output file name as a String. Generally for an
object such as Customer, the name field must be populated before it is written to the
file. We check for that and if null is stored in the name field then no data are written
to the output file (Listing 8.6A lines 258-263). If name field is populated then the
constructor for FileWriter class, which will append to file is called and is bonded to
the object Append of PrintWriter class (Lines 265-266). println method of
PrintWriter class is used to append Customer data to the output file. Finally the
output file is closed (Line 271).

Listing 8.6B shows the class DriverCustomer4 to test the upgraded Customer class.
00001 import javax.swing.*;
00002 import java.io.*;
00003 public class DriverCustomer4
00004 {
00005
00006 public static void main(String [] args) throws IOException
00007 {
00008 printSeparator();
00009 String Input = "";
00010 boolean done = false;
00011
00012 while(!done)
00013 {
00014 Input = JOptionPane.showInputDialog(
00015 "The program will do entry for Customer data to an output file "
00016 +" [Y]es or [N]o?");
00017 Input = Input.trim( );
00018 if(Input.equals("N") || Input.equals("n"))
00019 {
00020 System.out.println ("End of program");
00021 System.exit(0);
00022 }
00023 else if(!Input.equals("Y") && !Input.equals("y") )
00024 {
00025
00026 JOptionPane.showMessageDialog (null,"Invalid choice"
00027 +" click OK to proceed.");

CS3 Java – Topic 8: Standard IO (Singhal) Page 29 of 99


00028 done = false;
00029 }
00030 else
00031 {
00032 Input = JOptionPane.showInputDialog("Enter the name of "
00033 +" output file.");
00034 Input = Input.trim ( );
00035
00036 while(Input.length( ) == 0)
00037 {
Input = JOptionPane.showInputDialog("Invalid file name. “Enter the name of "
00039 +" output file.");
00040 Input = Input.trim ( );
00041 }
00042
00043 do
00044 {
00045 Customer Cust = new Customer();
00046 Cust.getCustomer();
00047 Cust.appendToFile(Input);
00048 Input = JOptionPane.showInputDialog(
00049 "The program will do entry for Customer data into an output file "
00050 +" [Y]es or [N]o?");
00051 Input = Input.trim();
00052 }while (Input.equals("Y") || Input.equals("y"));
00053 done = true;
00054 }
00055 }
00056
00057 System.exit(0);
00058 }
00062 public static void printSeparator()
00063 {
00064
System.out.println("===========================================");
00065 }
00066 }
//Listing 8.6B

Few ways in which the errors can creep up in user response are:
• Invalid user response when user is prompted about their choice to
continue program.
• Zero length String entered for the file name.
The flag control loop in Listing 8.6B (Line 12) sets the user input in motion. The
user is prompted to enter their choice to execute or exit the program (Lines 14-16).
We use the trim method of String class to ascertain that any leading or lagging

CS3 Java – Topic 8: Standard IO (Singhal) Page 30 of 99


white spaces entered by the user are trimmed to get the correct input (line 17). If
user enters characters ‘N’ or ‘n’, to indicate program end then program exits by
executing the first if block (Lines 18-22). It is possible that user unintentionally hits
invalid response, in which case the program informs user by executing the else if
block (Line 23-29). In this case the boolean flag done is set to false. Else block (Lines
30-55) is executed only when user presses either a ‘Y’ or a ‘y’ key. Program
ascertains that a zero length file name string is not entered. The loop coded in Lines
36-41 keeps user in an iteration mode until a non-zero length file name is received.
After receiving the non-zero length file name, a do while loop is used to get
Customer data and append to the output file (Lines 43-52). A new instance of
Customer is created; it is populated with user-inputted data, and appended to the
output file (Lines 45-47). The user can continue data entry or exit the data input
loop after each input (Lines 48-52). Outermost loop variable done is set to true (line
53), in case user wishes to append data to another output file.

Output Formatting
You may have noticed that in outputting the floating-point numbers, Java does not
format the fraction part to any particular significant number of figures. Special
Java class is used to manipulate the significant figures for floating point numbers. A
java package called java.text has classes, which help us format the floating-point
number output as well as outputting the currency data, and dates for a locale. Main
classes in package java.text are described below (Table 8.4).
Class name in Purpose
package java.text
DecimalFormat Assists formatting of floating-point numbers.
NumberFormat This is an abstract class10, however, it is used to
format numbers. including currency.
DateFormat Another abstract class, which assists the
formatting of time and dates depending on
locale.
Table 8.4
We show applications for the use of various output formatting classes.

Currency Formatting
Currency calculations must be exact. It is best to convert the input currency data to
smallest unit for the currency, do all calculations in smallest unit and then convert
to respective higher units. For example in USA the smallest unit of currency is one
cent, and the higher unit is dollar. Therefore it is best to convert user-inputted
currency data to cents, and then do all calculations using cents and then output
dollars and cents. NumberFormat class can be used to round off output to nearest
cent and display proper currency sign in output. Listing 8.7 shows an example of

10
An abstract class cannot be instantiated, but it may have some usable static methods, and some of
them may return an instance of this class.

CS3 Java – Topic 8: Standard IO (Singhal) Page 31 of 99


compound interest calculation; where user is asked for the principal amount of
deposit, interest rate, period of deposit, frequency of compounding. The program
outputs the total accumulation and interest earned in US and British currencies.
00001 import java.io.*;
00002 import java.text.*;
00003 import java.util.*;
00009 public class CompoundInterest
00010 {
00011 public static void main(String[] args) throws IOException
00012 {
00013 BufferedReader Keyboard = new BufferedReader(
00014 new InputStreamReader(System.in));
00015
00016 System.out.print("Enter the amount of initial deposit: ");
00017 double deposit = Double.parseDouble(Keyboard.readLine());
00018 int deposit_int = (int)(deposit*100);
System.out.println("We need the time period in years for which deposit is kept."
00020 +"Example of calculation is as follows. A deposit which is kept for "
+" One year and 55 days will be = 1 + 55/365.25 years = " +(1+ 55/365.25));

System.out.print("Enter the time period in years for which deposit is kept: ");
00023 double deposit_time = Double.parseDouble(Keyboard.readLine());

System.out.print("Enter the number of times in a year the compounding is done: ");

00025 int comp_pd = Integer.parseInt(Keyboard.readLine());


00026 System.out.print("Enter the interest rate in percent: ");
00027 double rate = Double.parseDouble(Keyboard.readLine());
00028
00029 double acuum = deposit_int*Math.pow((1+rate/(100.0*comp_pd)),
00030 deposit_time*comp_pd);
00031
00032 //format output in currency
00033 NumberFormat Currency = NumberFormat.getCurrencyInstance();
00034 System.out.println("Your total accumulation is " +
00035 Currency.format(acuum/100.0));
00036 System.out.println("Your total interest is " +
00037 Currency.format((acuum - deposit_int)/100.0));
00038 System.out.println("If you had deposit in England then following
are the results.");
00039 System.out.println("GBP = Great Britain Pound");
00040 NumberFormat Curr_UK =
NumberFormat.getCurrencyInstance(Locale.UK);
00041 System.out.println("Your total accumulation is " +
00042 Curr_UK.format(acuum/100.0));
00043 System.out.println("Your total interest is " +

CS3 Java – Topic 8: Standard IO (Singhal) Page 32 of 99


00044 Curr_UK.format((acuum - deposit_int)/100.0));
00045 }
00046 }// Listing 8.7

The program takes the user input for principal deposit in floating point numbers
but converts from double to integer by multiplying by 100 (assuming that input was
in dollars) (Lines 16-18). Then user is prompted to enter the data for deposit period,
compounding frequency per year, and the interest rate (Lines 19-27). The total
accumulation is calculated using the standard compound interest formula (Line 29-
30). The important point in this program is to understand the procedure of currency
formatting. NumberFormat class has overloaded method called
getCurrencyInstance, whose two forms are shown below (Table 8.5).
public static final NumberFormat getCurrencyInstance()
Returns a currency format for the current default locale.

public static NumberFormat getCurrencyInstance(Locale inLocale)


Returns a currency format for the specified locale.
Table 8.5
The argument-less method getCurrencyInstance returns a NumberFormat object,
which can be used to format the output data to local currency form. The default
locale is obtained by Java from the computer system settings. The second form of
method getCurrencyInstance requires passing an argument of class java.util.Locale
And then it returns a NumberFormat object specific to the Locale object passed.

In Line 33 (Listing 8.7) we get the NumberFormat object Currency using the call to
argument-less method getCurrencyInstance11. Since this Listing is compiled in USA,
the object Currency can be used to format the currency data for USA. The
overloaded method format of NumberFormat class is used to perform actual
formatting. Table 8.6 shows the details of method used in output Lines 34-35.
public final String format(double number)
Returns the String version of the number, consistent with the pattern stored
in its caller.
Table 8.6
The method format takes the total accumulation and interest earned in dollars and
rounds off to nearest cent and outputs with dollar sign (Lines 34-37). Figure 8.16
shows the example of output.

Enter the amount of initial deposit: 1000

11
In Java methods, which have names such as get…….Instance, are called factory methods. Factory
methods are static and return instance of their member class. They are used in place of constructors
to return an instance of a class. For example, the NumberFormat class is an abstract class, which
cannot be instantiated. It, however, has number of factory methods, which can return its instance.
Overloaded factory method getCurrencyInstance is one such method.

CS3 Java – Topic 8: Standard IO (Singhal) Page 33 of 99


We need the time period in years for which deposit is kept. Example of
calculation is as follows. A deposit which is kept for one year and 55 days will be =
+ 55/365.25 years = 1.1505817932922655
Enter the time period in years for which deposit is kept: 5
Enter the number of times in a year the compounding is done: 12
Enter the interest rate in percent: 5
Your total accumulation is $1,283.36
Your total interest is $283.36
If you had deposit in England then following are the results.
GBP = Great Britain Pound
Your total accumulation is GBP1,283.36
Your total interest is GBP283.36
FIG. 8.16

In Figure 8.16 the user input has been italicized and highlighted. The output
produced by Lines 34-35 without formatting would show the total accumulation to
be = 1283.3586785035118. The use of format method of NumberFormat class
instance correctly rounds off above number to 1283.36 and appends the $ sign in
front as well as adds the comma after the significant figure indicating thousand
dollar. One can perform calculations and outputs for locales other than the default.
Line 40 gets the NumberFormat object by calling the form of getCurrencyInstance
method that takes a Locale object as an argument. Locale.UK is a public static
member of class Locale. Curr_UK is the NumberFormat object which when used to
call its format method could format the argument to output form for UK currency.
Lines 41-45 output the corresponding data assuming that same deposit was made in
Britain in pounds. Table 8.7 shows the results of call to Currency.format method
where Currency is the NumberFormat object created on Line 33 of Listing 8.7.
Call made Output
System.out.println (Currency.format (13.384)); $13.38
System.out.println (Currency.format (13.385)); $13.38
System.out.println (Currency.format (13.38501)); $13.39
System.out.println (Currency.format (13.3851)); $13.39
System.out.println (Currency.format (13.3854)); $13.39
System.out.println (Currency.format (13.3855)); $13.39
System.out.println (Currency.format (13.3856)); $13.39
System.out.println (Currency.format (13.386)); $13.39
System.out.println (Currency.format (-13.386)); ($13.39)
Table 8.7
Among other things it is interesting to note (last row in Table 8.7) that when a
negative floating-point number is passed to format method, for Locale being USA it
prints a value ($13.39) as in USA it is usual to place parentheses around negative
currency number.
Half-even rounding criterion

CS3 Java – Topic 8: Standard IO (Singhal) Page 34 of 99


The format method uses the half-even12 rounding procedure to round the numbers.
This mode rounds towards the "nearest neighbor" unless both neighbors are
equidistant, in which case, it rounds towards the even neighbor. For example, if
number 1.2499 is to be rounded off to two decimal places, then two possible values
are 1.24, and 1.25. This distance of 1.2499 from 1.24 is 0.0099, but from 1.25 is
0.0001. Since the distance towards 1.25 is lower, the output of statement

System.out.println (Currency.format (1.2499));

will be $1.25. However, if we need to round off 1.245, then the distance with both
1.24 and 1.25 is equal (each is 0.005). In this case the half-even principle dictates
that rounding is to be done towards the even neighbor. Therefore the statement:

System.out.println (Currency.format(1.245));

Will create an output of $1.24. Similarly in Table 8.7 the values 13.384 and 13.385
rounds off to 13.38 because for 13.384 the distance towards 13.38 is lower, whereas
in case of 13.385, the distance towards two neighbors (13.38 & 13.39) is same, but
even neighbor 13.38 is chosen. For all other values in Table 8.7 the distance towards
13.39 is lower than towards 13.38.

Formatting of Real or Decimal numbers


Most numbers in real life are floating point types. The number of significant figures
printed for different number depends upon the utility of such figures. We saw in
example of money formatting (Listing 8.7) that rounding of to two significant
figures serves the purpose. On the other hand, when displaying physical constants,
such as Avogadro number, Planck’s constant, higher number of significant figures
may be needed. When reporting a student’s grade point average, perhaps one
significant figure could be adequate. In addition, very small or very large scientific
or engineering numbers may require display using exponent forms (such as the
velocity of light in vacuum = 2.99792458E8 meters/second). As indicated earlier,
Java class java.text.DecimalFormat helps us format the display of floating point
numbers. In using the DecimalFormat class, we first create its object using the
constructor call shown (Figure 8.17), and then call the format method to output the
number in required pattern. The overloaded method format returns a string.

12
IEEE 754 standard describes this rounding procedure in detail.

CS3 Java – Topic 8: Standard IO (Singhal) Page 35 of 99


//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Indicates the pattern to which the number outputted
by format method must conform.

DecimalFormat DF = new DecimalFormat (“Format String”);


System.out.println (DF.format (number));
Outputted number would
conform to the pattern
dictated by the Format
FIG. 8.17 String.
//////////////////////////////////////////////////////////////////////////////////////////////////
C programmers may recall as to how printf used the format string to format the
output. In similar manner the format string passed to the constructor of
DecimalFormat class dictates as to how the string representation of number passed
to it must look like. A complete list of formatting strings is provided by the
documentation for DecimalFormat class specification. Here is the summary of some
common formatting strings (Table 8.8).
Format String Meaning
"0.000" If number is less than 1.0 than zero must be shown before the
decimal point and mantissa13 will show three digits, padded with
zeros if necessary.
"0.###" If number is less than 1.0 than zero must be shown before the
decimal point and mantissa will show maximum three digits. If
lagging digits in mantissa are zero then they are not displayed.
"0.000E0" If number is less than 1.0 than zero must be shown before the
decimal point and mantissa will show three digits, padded with
zeros if necessary. The exponent E will show the powers of 10 that
need to be multiplied to the number to get its real value.
“,###” Counting from right place a comma for every three digit set (See
example output in Figure 8.19).
Table 8.8
Figure 8.18 shows the technical terms used for the parts of the format string.

13
Mantissa is a part of number after the decimal point or the fractional part of a number.

CS3 Java – Topic 8: Standard IO (Singhal) Page 36 of 99


/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

“0.0000”
Integer part Mantissa
of the part of the
number number

“0.####”
FIG. 8.18
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
The part before the decimal point is the integer part of a number. The part after the
decimal point is called “mantissa”. Inside the format string, the placement of zero
(0) means that display either the digit or zero for the lagging digits in the mantissa.
Zero in the integer part will be shown only if the number is less than one. The
placement of character # means that show the lagging digit in the mantissa only if it
is present otherwise leave the lagging digit location(s) blank.

Figure 8.19 shows code and corresponding output when the last format string in
Table 8.8 is used. In Figure 8.19, the code lines shown in Figure 8.17 are combined
into one line.

CS3 Java – Topic 8: Standard IO (Singhal) Page 37 of 99


Output on
Monitor

FIG. 8.19 In above Figure the creation of DecimalFormat object and call to format
method are combined in one step.

Table 8.9 gives the summary of the meanings of characters used in building the
format string.
Character Meaning
0 Display a digit. If no digit is present then display zero.
# Display a digit. If no digit is present then does not display
anything.
, Used only for the integer part of a number. Counting from
right, display separator comma as dictated by the pattern.
Used to format the mantissa and placement of decimal
. point accordingly. Can introduce a decimal point even if
there are no fractional parts in the number. For example
the statement System.out.println ((new
DecimalFormat("###.")).format (2L)); will output 2.
% When placed in the format string anywhere (except the
first character) multiplies the number with 100 before
displaying and appends the % sign in end. If placed as the

CS3 Java – Topic 8: Standard IO (Singhal) Page 38 of 99


first character in the format string, then still displays the
number after multiplying it by 100, but appends the %
sign in front of the number.
; When a number to be displayed can be both positive and
negative, and patterns must be provided for both, then
semicolon is used to separate the two patterns.
‘ Used to quote special characters appended as prefix or
postfix. For example ‘# will be printed as #
Other All other characters will appear literally.
Table 8.9

We show a simple example (Listing 8.8) using some of the display formats from
Table 8.8 and characters from Table 8.9.
00001 import java.text.*;
00002 public class FloatingPointFormatting
00003 {
00004 public static void main(String[] args)
00005 {
00006 System.out.println("This program will simply display various formats "+
00007 "in which normal, large and small floating point number can be displayed.");
00008 System.out.println("For example we display the value of Pi in various formats");
00009 DecimalFormat DF = new DecimalFormat("0.0");
00010 System.out.println("The value of Pi rounded to first significant figure = " +
00011 DF.format(Math.PI));
00012 DF = new DecimalFormat("0.00");
00013 System.out.println("The value of Pi rounded to two significant figures = " +
00014 DF.format(Math.PI));
00015 DF = new DecimalFormat("0.00000");
00016 System.out.println("The value of Pi rounded to five significant figures = " +
00017 DF.format(Math.PI));
00018 DF = new DecimalFormat("00.0000000");
00019 System.out.println("The value of Pi rounded to seven significant figures"+
00020 " but also showing a leading zero = " +
00021 DF.format(Math.PI));
00022 DF = new DecimalFormat("0.00");
00023 double area = Math.pow(Math.PI,3.0);
00024 System.out.println("The area of a circle of radius = " + Math.PI +
" cm " +"\n" + "Displayed in format 0dot00 is "+ DF.format(area)+ " cm square.");
00026 //radius of earth = 6378100 meters
00027 double vol =4.0*Math.PI*Math.pow(6378100,3.0);
00028 System.out.println("The approximate volume of earth in format 0dot00 = " +
00029 DF.format(vol)+ " cubic meters.");
00030
00031 DF = new DecimalFormat("##.####E0");
00032 System.out.println("Now displaying format ##.####E0");
00033 System.out.println("In scientific notation the approximate volume of earth = " +

CS3 Java – Topic 8: Standard IO (Singhal) Page 39 of 99


00034 DF.format(vol)+ " cubic meters.");
00035 DF = new DecimalFormat("#.####E0");
00036 System.out.println("Now displaying format #.####E0");
00037 System.out.println("In scientific notation the approximate volume of earth = " +
00038 DF.format(vol)+ " cubic meters.");
00039 System.out.println("Now proceeding to show formatting of small numbers.");
00040 double copper_kalpha = 1.5401E-08;
00041
00042 DF = new DecimalFormat("0.0000000000");
00043 System.out.println("Now displaying format 0.0000000000");
System.out.println("With out formatting the value of copper k alpha x-ray wavelength = " +
00045 DF.format(copper_kalpha)+ " cm.");
00046
00047 DF = new DecimalFormat("00.####E0");
00048 System.out.println("Now displaying format 00.####E0");
System.out.println("In scientific notation the value of copper k alpha x-ray wavelength = " +
00050 DF.format(copper_kalpha)+ " cm.");
00051
00052 DF = new DecimalFormat("#.####E00");
00053 System.out.println("Now displaying format 0.####E00");
System.out.println("In scientific notation the value of copper k alpha x-ray wavelength = " +
00055 DF.format(copper_kalpha)+ " cm.");
00056
00057 DF = new DecimalFormat(".####E00");
00058 System.out.println("Now displaying format .####E00");
System.out.println("In scientific notation the value of copper k alpha x-ray wavelength = " +
00060 DF.format(copper_kalpha)+ " cm.");
00061 System.out.println("In percent, using the format string\"#0.00%\""+
00062 " the number 0.086 is "+new DecimalFormat ("#0.00%").format(0.086));

00063 }
00064 }//Listing 8.8

Figure 8.20 shows the output for the code of Listing 8.8. The lines numbers are
added to the output intentionally.
01 This program will simply display various formats in which normal, large and small
floating point number can be displayed.
02 For example we display the value of Pi in various formats
03The value of Pi rounded to first significant figure = 3.1
04 The value of Pi rounded to two significant figures = 3.14
05 The value of Pi rounded to five significant figures = 3.14159
006 The value of Pi rounded to seven significant figures but also showing a leading zero =
03.1415927
07 The area of a circle of radius = 3.141592653589793 cm

Format specifies only one zero


in integer part.

CS3 Java – Topic 8: Standard IO (Singhal) Page 40 of 99


08 Displayed in format 0dot00 is 31.01 cm square.
Full integer part is displayed in
spite of format string

09 The approximate volume of earth in format 0dot00 = 3260497235812886000000.00 cubic


meters.
10 Now displaying format ##.####E0
11 In scientific notation the approximate volume of earth = 32.605E20 cubic meters.
12 Now displaying format #.####E0
13 In scientific notation the approximate volume of earth = 3.2605E21 cubic meters.
14 Now proceeding to show formatting of small numbers.
15 Now displaying format 0.0000000000
16 With out formatting the value of copper k alpha x-ray wavelength = 0.0000000154 cm.
17 Now displaying format 00.####E0
18 In scientific notation the value of copper k alpha x-ray wavelength = 15.401E-9 cm.
19 Now displaying format 0.####E00
20 In scientific notation the value of copper k alpha x-ray wavelength = 1.5401E-08 cm.
21 Now displaying format .####E00
22 In scientific notation the value of copper k alpha x-ray wavelength = .154E-07 cm.
23 In percent, using the format string"#0.00%" the number 0.086 is 8.60%
FIG. 8.20

Let us first define as to how we would refer to line numbers from Listing 8.8 and
Figure 8.20. For example, L8.8#01 will refer to line number one from Listing 8.8. Or
L8.8#01-03 would refer to lines one to three from Listing 8.8. Similarly the
abbreviation F8.20#01 or F8.20#01-03 would correspond to line number one or line
numbers one to three respectively from Figure 8.20.

In L8.8#09 we create a DecimalFormat class object, whose constructor takes the


format string “0.0” as argument. Then L8.8#10-11 print the value of Pi14 formatted
to this string (F8.20#03). As dictated by the format string (“0.0”) the mantissa of Pi
is truncated only to one decimal place, and the value of Pi is printed as 3.1
(F8.20#03). Lines L8.8#12-16 show the affect of increasing the number of possible
digits displayed in mantissa for Pi. The output lines F8.20#04-05 show that the
format strings “0.00” & “0.00000” display the value of Pi as 3.14 & 3.14159
respectively. In code lines L8.8#18 we increase the integer part of format string by
one zero and mantissa as seven significant figures as “00.0000000”. As expected by
the output from L8.8#19-20, displayed in F8.20#06 is that now the Pi is displayed as
03.1415927. Notice that adding an extra zero in the integer part of format string
forces the leading zero in Pi value to show up. The area of a circle whose radius is Pi
3
(thus the area being equal to Pi ) is displayed up to 2 significant figures by L8.8# 24-
25 and a value of 31.01 is outputted (F8.20#08). Notice that though the format string

14
The value of Pi is 3.14159265……

CS3 Java – Topic 8: Standard IO (Singhal) Page 41 of 99


provided in L8.8#22 specifies “0.00” format, the presence of single zero in the
integer part of format string the output 31.01 prints the full value of the integer part
of the number (F8.20#08).

Outputting large numbers in scientific notation


Lines L8.8#27-29 calculate and display the volume of earth (a large number) in
format 0dot00. The output line F8.20#09 shows the result. This number is more
appropriately shown in scientific notation. Therefore the code line F8.8#31 provides
the format string to be used as “##.####E0”. Apart from the usual meaning of #, and
decimal place holder (.), the placement of E indicates that the output must be in
scientific notation. The characters E0 means that even if number is less than 10, a
zero must be shown after the symbol E. In conformance with the format string
provided, the output of volume of earth (F8.20#11) shows the value 32.605E20.
However, as soon as we change the format string to “#.####E0” (Line L8.8#35), the
output follows the format string (F8.20#13) and displays the volume of earth to be
3.2605E21. Notice that even though the part of format string that formats the
exponent has only one zero (E0), Java will display the full exponent (like E20 or
E21). A general rule that is followed in formatting the integer part and exponent
is as follows: The format string is obeyed only as long as the number of
digits are equal to or less than the corresponding placeholders in the
format string. If numbers of digits are larger than the number of
placeholders in the format string, then full value of integer or exponent
part will be displayed.

Outputting small numbers in scientific notation


Listing 8.8 then proceeds to show formatting of small numbers (L8.8#42-60).
Usually small numbers are encountered in Physics, Chemistry, and Engineering,
when one is doing calculations in fields of spectroscopy, and atomic physics. For
example x-rays have very small wavelengths, yet its value is used in many
calculations. Metal copper emits a special x-ray, which is used in many scientific
measurements. Code line L8.8#40 hard codes the value of copper k-alpha x-ray as
1.5401E-08. Using the format string "0.0000000000" and with out using scientific
notation, the code lines L8.8#44-45 output the value of copper k-alpha x-ray
wavelength as 0.0000000154 (F8.20#16). This number in scientific form is outputted
using the following format strings: "00.####E0", "#.####E00", ".####E00". The
corresponding values are printed in Figure 8.20, on lines 18, 20, & 22 are 15.401E-9,
1.5401E-08, .154E-07. One can now see the mapping between the format string and
the value printed. The value printed for the format string "00.####E0" is 15.401E-9
as presence of 00 in the integer part forces one to display digits 1 & 5. Similarly the
format string "#.####E00" displays the value 1.5401E-08. Notice that in accordance
with the format string (E00), the leading zero is added in the display of exponent
(08). The format string ".####E00" totally suppresses outputting the integer part of
the number, displaying a value .154E-07. Notice that total suppression of the integer
part of a number can only be accomplished when scientific notation formatting is
used.

CS3 Java – Topic 8: Standard IO (Singhal) Page 42 of 99


A % sign placed in the format string anywhere other than first character multiplies
the number by 100 before displaying and appends the % sign at the end. This is
done by code Lines 59 to 62. The format string "#0.00%", proceeds to print the
number 0.086 as 8.60%. If the percent sign is placed as the first character in the
format string, then displayed number is still multiplied by 100, however, the % sign
is appended in the front.

Providing a pattern for prefix and suffix for negative numbers


The negative numbers are also printed using the pattern provided, except that a
negative sign is placed in the front. For example the code line

System.out.println (new DecimalFormat (“00.000”).format(-34.1009));

will print –34.101, as the half even rounding criterion is used and the output
mantissa is confined only to 3 significant figures. Notice that the minus sign is
added, even though it is not the part of format string. There are situations, however,
for example in writing financial reports, where parentheses are placed around the
negative numbers. As indicated in Table 8.9, the format string can take two
patterns, first for positive numbers, and second separated by semicolon (;) for the
negative ones. Therefore if we wished to show negative numbers inside parenthesis,
the format string of the following type can be used (Figure 8.21):

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
“00.000;(00.000)”
Positive sub
pattern Negative sub
pattern
FIG. 8.21
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
and then the code line such as below,

System.out.println (new DecimalFormat (“00.000, (00.000)”).format(-34.1009));

will print the number –34.1009 as (34.101). Understand that the only prefix and
suffix in the negative sub pattern are used in formatting the output. For example in
Figure 8.21, in the negative sub-pattern, the prefix is ‘(‘ and suffix is ‘)’. At the time
of this writing (April 2004), Sun’s API for DecimalFormat class states “If there is an
explicit negative subpattern, it serves only to specify the negative prefix and suffix;
the number of digits, minimal digits, and other characteristics are all the same as
the positive pattern. That means that "#,##0.0#;(#)" produces precisely the same
behavior as "#,##0.0#;(#,##0.0#)". Due to an unfixed bug in the DecimalFormat

CS3 Java – Topic 8: Standard IO (Singhal) Page 43 of 99


class even in the Java version15 1.4.2_03, we have found this claim to be untrue, as
the code lines:
System.out.println(new DecimalFormat("#,##0.0#;(#,##0.0#)").format(-34.1009));
System.out.println(new DecimalFormat("#,##0.0#;(#)").format(-34.1009));

results in an output: Both negative and positive sub patterns are


identical, except for the prefix and postfix
(34.1) characters in negative sub pattern.
(34.1
Loss of suffix or postfix when two sub patterns are different.

Therefore we recommend that until this bug is fixed, except for the prefix and
suffix, the sub-pattern for negative and positive numbers must be identical!
The Listing 8.9 shows a simple program to format the negative numbers.
00001 import java.text.*;
00002
00003 public class NegativeNumPattern
00004 {
00005 public static void main(String[] args)
00006 {
00007 DecimalFormat DF = new DecimalFormat("00.000");
00008 double num = -34.1009;
00009 System.out.println("The number " + num + " using the pattern\"00.000\""
00010 +" is printed as " + DF.format(num));
00011 DF = new DecimalFormat("00.000;(00.000)");
00012 System.out.println("The number " + num +
00013 " using the pattern\"00.000;(00.000)\""+" is printed as "
00014 + DF.format(num));
00015 DF = new DecimalFormat("00.000%;(00.000%)");
00016 System.out.println("The number " + num +
00017 " using the pattern\"00.000%;(00.000%)\""+" is printed as "
00018 + DF.format(num));
00019
00020 num = -34098.2004;
00021 DF = new DecimalFormat("0,000.000%;(0,000.000%)");
00022 System.out.println("The number " + num +
00023 " using the pattern\"0,000.000%;(0,000.000%)\""+" is printed as "
00024 + DF.format(num));
00025
00026 //showsBug();
00027 }

15
To find the Java version in your machine type java –version on command line. The output may
look like the following:
java version "1.4.2_03"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2_03-b02)

CS3 Java – Topic 8: Standard IO (Singhal) Page 44 of 99


00028
00029 public static void showsBug()
00030 {
System.out.println(new DecimalFormat("#,##0.0#;(#,##0.0#)").format(-34.1009));
00032 System.out.println(new DecimalFormat("#,##0.0#;(#)").format(-34.1009));
00033 }
00034 }//Listing 8.9

The Figure 8.22 shows the output for the Listing 8.9.
The number -34.1009 using the pattern"00.000" is printed as -34.101
The number -34.1009 using the pattern"00.000;(00.000)" is printed as
(34.101)
The number -34.1009 using the pattern"00.000%;(00.000%)" is printed as
(3410.090%)
The number -34098.2004 using the pattern"0,000.000%;(0,000.000%)" is
printed as (3,409,820.040%)
FIG. 8.22

The suffix and postfix parenthesis are applied around the negative numbers as per
provision by the negative sub-pattern.

Outputting into fixed width fields


Unfortunately, Java does not have a output format method like setw in C++. The
setw method included in C/C++ iomanip library would automatically print data
right justified in the width passed to it. In Java 1.5, there are plans to introduce the
versions of methods println and print from PrintStream class, which can take
format strings in the manner of C method printf. For now the column widths into
which the output must be printed must be managed by the program code. The basic
issue in printing datum into a fixed width field begs the question as how to handle
data truncation, when the data width exceeds the field width allowed for it? This in
turn relates to fact whether the loss of information in truncation process is tolerable
or not. We follow these general rules:
1. For numeric data types, such as currency, integers, and non-
currency floating-point numbers we print the datum in its
entirety, irrespective of the field width provided for it.
2. Non-numeric data such as Strings containing names, addresses,
etc., would be truncated by cutting off the lagging characters if
the number of characters in datum exceeds the allowed field
width.
We write a method called printW, which takes as an argument, the following
parameters:
• A PrintWriter object
• The String to be printed
• The width of the field into which the String is to be printed.

CS3 Java – Topic 8: Standard IO (Singhal) Page 45 of 99


• The boolean variable indicating whether to print the String left
justified or right justified and obeying the two principles described
earlier.
• A character, used to pad leading or lagging blanks.
The method printW, which we tried to make as close to setw as possible, has the
following signatures:
public static void printW (PrintWriter output, String Str, int width, boolean just,
char fill)

We describe the algorithm for the method printW (ALG 8.4).


ALG 8.4
public static void printW(PrintWriter output, String Str, int width, boolean just,
char fill)

If Str is null or has zero length, then throw an exception or exit the method.
If width is negative or zero then set width equal to the length of Str.
If length of string is equal to width, then print the string and exit method.
If character at index zero of Str is a digit or character ‘$’ or ‘-‘ or ‘(‘
If right justification print is true then
Print the leading fill characters (which is equal to difference of width
and number of characters in Str)
Print Str
Else
Print the String
Print the fill characters
Else
If length of the Str is equal to width then
Print Str
If left justification print is true then
If length of Str is less than width then
Print the Str
Print numbers of fill characters equal to the difference
between length of Str and width
Else
From Str, print only the number of characters equal to width
Else
If length of Str is less than width then
Print numbers of fill characters equal to the difference
between length of Str and width
Print the Str
Else
From Str, print only the number of characters equal to width

CS3 Java – Topic 8: Standard IO (Singhal) Page 46 of 99


Listing 8.10 shows the class FixedWidthOutPut and its driver class, former having
the method printW coded to algorithm ALG 8.4 and other utility methods, which we
shall discuss later. Table 8.10 gives the summary of methods in class
FixedWidthOutPut.
Constructor Summary for class FixedWidthOutPut
private FixedWidthOutPut()
private constructor, so that class FixedWidthOutPut is not
instantiated.

Summary of Methods for class FixedWidthOutPut


static void printCentered(java.io.PrintWriter Pwriter,
java.lang.String Str, int column, char fill)
Prints the given string centered in the column width provided
as per rules for avoiding the loss of information.
static void printCenteredln(java.io.PrintWriter Pwriter,
java.lang.String Str, int column, char fill)
Calls the method printCentered and then prints a line feed.
static void printChar(java.io.PrintWriter Pwriter,
int column, char fill)
Prints given numbers of and type of character in a row and
moves output to next line.
static void printlnW(java.io.PrintWriter output,
java.lang.String Str, int width, boolean just,
char fill)
Calls the method printW and then prints a line feed.
static void printW(java.io.PrintWriter output,
java.lang.String Str, int width, boolean just,
char fill)
static print method takes a PrintWriter
object, an int as width, and a string to be
printed. If string is non-numeric, then prints
only the characters that will fit in the width,
while ignoring the lagging characters. If string
is numeric, then prints in entirety ignoring the
width (prevents loss of information).
Table 8.10

CS3 Java – Topic 8: Standard IO (Singhal) Page 47 of 99


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
00001 import java.io.*;
00002 import java.text.*;
00003
00004 public class FixedWidthOutPut
00005 {
00006 private FixedWidthOutPut(){}
public static void printW(PrintWriter output, String Str, int width, boolean just,
00014 char fill)
00015 {
00016 if(Str == null || Str.length() == 0)
00017 {
00018 System.out.println
00019 ("Null string or zero length string will not be printed."+
00020 " Exiting the method.");
00021 return;
00022 }
00023
00024 if(width<=0)
00025 width = Str.length();
00026
00027 if(Str.length() == width)
00028 {
00029 output.print(Str);
00030 output.flush();
00031 return;
00032 }
00033
00034 boolean condition = Character.isDigit(Str.charAt(0)) || Str.charAt(0) == '$' ||
00035 Str.charAt(0) == '-' || Str.charAt(0) == '(';
00036
00037 if(condition)
00038 {
00039 //print right justified if just is true. Pad with fill in front.
00040 //decimals will be aligned if numeric is properly formatted
00041 //using the DecimalFormat class
00042 if(just)
00043 {
00044 for(int index = Str.length(); index<width; index++)
00045 output.print(fill);
00046 output.print(Str);
00047 output.flush();
00048 }
00049 else //print left justified
00050 {
00051 output.print(Str);

CS3 Java – Topic 8: Standard IO (Singhal) Page 48 of 99


00052 for(int index = Str.length(); index<width; index++)
00053 output.print(fill);
00054 output.flush();
00055 }
00056
57 }

00058 else
00059 {
00060 if(!just)
00061 {
00062 if(Str.length()<width)
00063 {
00064 //print left justified and pad up to width with fill
00065 output.print(Str);
00066 for(int index = 0; index<(width - Str.length());index++)
00067 output.print(fill);
00068 output.flush();
00069
00070 }
00071 else // Str is non-numeric and greater than width
00072 {
00073 //only print the substring up to the width
00074 output.print(Str.substring (0,width));
00075 output.flush();
00076 }
00077 }
00078 else
00079 {
00080 if(Str.length()<width)
00081 {
00082 //print right justified and pad up to width with fill
00083 for(int index = Str.length(); index<width; index++)
00084 output.print(fill);
00085 output.print(Str);
00086 output.flush();
00087
00088 }
00089 else // Str is non-numeric and greater than width
00090 {
00091 //only print the substring up to the width
00092 output.print(Str.substring(0,width));
00093 output.flush();
00094 }
00095 }
00096

CS3 Java – Topic 8: Standard IO (Singhal) Page 49 of 99


00097 }
00098 }
00101 public static void printlnW(PrintWriter output, String Str, int width,
00102 boolean just, char fill )
00103 {
00104 printW(output,Str,width, just, fill);
00105 output.println();
00106 }
00111 public static void printChar(PrintWriter Pwriter, int column, char fill)
00112 {
00113 for(int index=0; index<column; index++)
00114 Pwriter.print(fill);
00115 Pwriter.println();
00116 }
00120 public static void printCentered(PrintWriter Pwriter, String Str, int column,
00121 char fill)
00122 {
00123 if(Str == null || Str.length() == 0)
00124 {
00125 System.out.println
00126 ("Null string or zero length string will not be printed."+
00127 " Exiting the method.");
00128 return;
00129 }
00130
00131 if(column<=0)
00132 column = Str.length();
00133
00134 if(Str.length() == column)
00135 {
00136 Pwriter.print(Str);
00137 Pwriter.flush();
00138 }
00139 else if(Str.length()<column)
00140 {
00141 int remainder = (column - Str.length())%2;
00142 int to_pad = (column - Str.length())/2;
00143 for(int index=0; index<to_pad; index++)
00144 Pwriter.print(fill);
00145 Pwriter.print(Str);
00146 for(int index=0; index<(to_pad + remainder); index++)
00147 Pwriter.print(fill);
00148 Pwriter.flush();
00149 }
00150 else
00151 {

CS3 Java – Topic 8: Standard IO (Singhal) Page 50 of 99


00152 boolean condition = Character.isDigit(Str.charAt(0)) || Str.charAt(0) == '$' ||
00153 Str.charAt(0) == '-' || Str.charAt(0) == '(';
00154
00155 if(condition)
00156 {
00157 Pwriter.print(Str);
00158 Pwriter.flush();
00159 }
00160 else
00161 {
00162 Pwriter.print(Str.substring(0,column));
00163 Pwriter.flush();
00164 }
00165 }
00166 }
public static void printCenteredln(PrintWriter Pwriter, String Str, int column,
00171 char fill)
00172 {
00173 printCentered( Pwriter, Str, column, fill);
00174 Pwriter.println();
00175 }
00176
00177
00178 }//Listing 8.10A

First we discuss obvious “house-keeping” details of class FixedWidthOutput.


• If the string to be passed to print methods is zero length or null, then
program exits (L8.10A#16-22 & #123-129).
• If width parameter passed to print methods is negative or zero, then width is
set equal to the length of the string to be printed (L8.10A#24-25 & #131-132).
• If the length of the string to be printed is equal to the width of field to be
printed into, then just print the string (L8.10A#27-32 & #134-138).
• flush method of PrintWriter object is called after making the call to method
print, as the buffer is not flushed16 each time when print method is called
(L8.10A#30, #47, #54, #68, #75, #93, #137, #148, #158, & #163). Understand
that when PrintWriter and PrintStream objects call method println, then
buffer is flushed automatically (provided that proper constructor was used
for PrintWriter object). However, when they call print method then buffer is
flushed automatically only for PrintStream objects, and not for PrintWriter
objects, the latter needing an explicit call to flush method!

16
The use of constructor PrintWriter (OutputStream out, boolean autoflush) automatically flushes
the buffer during the call to println method when autoflush is set to true.

CS3 Java – Topic 8: Standard IO (Singhal) Page 51 of 99


Methods printW and printCentered
As discussed in ALG 8.4, the method printW takes a String, the field width,
PrintWriter object, and fill character as argument. It and method printCentered
sub-specialize in printing of numeric and non-numeric strings as follows.

Printing numeric string larger than the field width


Whether the input string is numeric is tested by setting a boolean value condition to
true if the first character in the string is a digit, ‘-‘, ‘$’ or ‘(‘ (L8.10A# 34-35, &
#152-152). The last two conditions are needed for a positive or negative currency
numeric string for the Locale USA. Obviously the code would need modification for
other Locale. If the String is numeric, and its length is larger than the width to be
printed into, then it is printed in its entirety (L8.10A#51 & #155-159).

Printing any string smaller than the field width


When the string to be printed is smaller than the width to be printed into, then it
may be printed in three different ways:
1. Left Justified
2. Right Justified
3. Center Justified.
The method printW covers the first two cases, whereas the third one is covered by
method printCentered. For left justified printing, first the string is printed
(L8.10A#51 &#65) and then the leftover spaces are filled with the fill character
passed to the method printW (L8.10A#52-53 & #66-67). Reverse process is followed
when the string is to be printed right justified (L8.10A#44-46) & #83-85).

For centered printing, the number of fill characters would be field width minus the
length of the string to be printed. This number may be odd or even. If this number
were even, then the number of fill character on each side of the string to be printed
would be even. Otherwise we need to make an arbitrary choice as to which side of
the string (left or right) must have the extra character. We choose that right side of
the string has the extra fill character if the number of fill characters needed in
centered printing are odd. L8.10A#139-147 show as to how the above algorithm is
executed. The remainder of the difference of width and the string length when
divided by two is found (L8.10A#141). This value would either be zero or one. The
number of pad characters is given by the value half of the difference width minus
the string length (L8.10A#142). The numbers of pad characters are first printed
((L8.10A#143-144). Then the string is printed (L8.10A#145). Finally the right side
pad characters are printed (L8.10A#146-147).

Printing non-numeric string larger than the field width


For non-numeric strings, that are larger than the field width, we choose only to
print the number of characters that would fit in the field width and discard the
lagging characters. Code lines L8.10A#92 enforces that for the method printW,
where a substring of length equal to the filed width is printed. Similar algorithm is
executed by the method printCentered in code line L8.10A#162.

CS3 Java – Topic 8: Standard IO (Singhal) Page 52 of 99


The methods printlnW and printCenteredln first simply call printW and
printCentered respectively, and then output a new line by calling println using the
PrintWriter object passed to them.

The class DriverFixedWidthOutput tests the class FixedWidthOutput (Listing


8.10B).
00002 import java.io.*;
00003 import java.text.*;
00005 public class DriverFixedWidthOutput
00006 {
00007 public static void main(String[] args) throws IOException
00008 {
00009 String Longer = "A really really really long String of length = 49";
00010 int len = Longer.length();
System.out.println("Outputting string \"" + Longer + "\" in column width = "+
00012 len);
00013
00014 PrintWriter PW = new PrintWriter(System.out,true);
00015 FixedWidthOutPut.printlnW(PW,Longer,len,true,'*');
System.out.println("Outputting string \"" + Longer + "\" in column width = "+
00017 (len-9));
00018 FixedWidthOutPut.printlnW(PW,Longer,len-9,true,'*');
00019
System.out.println("Outputting string \"" + Longer + "\" in column width = "+
00021 (len+10) + " left justified padded with character *.");
00022 FixedWidthOutPut.printlnW(PW,Longer,len+10,false,'*');
00023
System.out.println("Outputting string \"" + Longer + "\" in column width = "+
00025 (len+10) + " right justified padded with character *.");
00026 FixedWidthOutPut.printlnW(PW,Longer,len+10,true,'*');
00027 System.out.println("Proceeding to demonstrate numeric outputs.");
00028
00029 double val = -90009.90009;
00030
00031 Longer = new DecimalFormat("00000.00000").format(val);
00032 len = Longer.length();
00033 System.out.println("Printing the numeric String " + Longer+
00034 " of length = " + len + " in column width " + len);
00035 FixedWidthOutPut.printlnW(PW,Longer,len,true,'*');
00036
00037 System.out.println("Printing the numeric String " + Longer+
00038 " of length = " + len + " in column width " + (len-5));
00039 FixedWidthOutPut.printlnW(PW,Longer,len-5,true,'*');
00040
00041 System.out.println("Printing the numeric String " + Longer+
00042 " of length = " + len + " in column width " + (len+10) + "\n"

CS3 Java – Topic 8: Standard IO (Singhal) Page 53 of 99


00043 + "right justified, padded with character *.");
00044 FixedWidthOutPut.printlnW(PW,Longer,len+10,true,'*');
00045
00046 System.out.println("Printing the numeric String " + Longer+
00047 " of length = " + len + " in column width " + (len+10) + "\n"
00048 + "left justified, padded with character *.");
00049 FixedWidthOutPut.printlnW(PW,Longer,len+10,false,'*');
00050
00051 Longer = new
DecimalFormat("00000.00000;(00000.00000)").format(val);
00052 len = Longer.length();
00053 System.out.println("Printing the numeric String " + val+
00054 " of length (after formatting) = " + len + " in column width " + len);
00055 FixedWidthOutPut.printlnW(PW,Longer,len,true,'*');
00056
00057 System.out.println("Printing the numeric String " + val+
00058 " of length (after formatting) = " + len + " in column width " + (len-5));
00059 FixedWidthOutPut.printlnW(PW,Longer,len-5,true,'*');
00060
00061 System.out.println("Printing the numeric String " + val+
" of length (after formatting) = " + len + " in column width " + (len+10) + "\n"
00063 + "right justified, padded with character *.");
00064 FixedWidthOutPut.printlnW(PW,Longer,len+10,true,'*');
00065

00066 System.out.println("Printing the numeric String " + val+


" of length (after formatting) = " + len + " in column width " + (len+10) + "\n"
00068 + "left justified, padded with character *.");
00069 FixedWidthOutPut.printlnW(PW,Longer,len+10,false,'*');
00070 System.out.println("Now testing centered printing. For numeric values "
00071 + " we use negative currency.");
00072
00073 val = -9999.98456;
00074 Longer = NumberFormat.getCurrencyInstance().format(val);
00075 len = Longer.length();
00076 System.out.println("Printing the currency String " +
" of length (after formatting) = " + len + " in column width " + (len+11) + "\n"
00078 + "center justified, padded with character *.");
00079 FixedWidthOutPut.printCenteredln(PW,Longer,(len+11),'*');
00080 System.out.println("Printing the currency String " +
" of length (after formatting) = " + len + " in column width " + (len-5) + "\n"
00082 + "center justified, padded with character *.");
00083 FixedWidthOutPut.printCenteredln(PW,Longer,(len-5),'*');
00084 Longer = "A short String";
00085 len = Longer.length();
00086 System.out.println("Printing the non-numeric String " +

CS3 Java – Topic 8: Standard IO (Singhal) Page 54 of 99


00087 " of length = " + len + " in column width " + (len+11) + "\n"
00088 + "center justified, padded with character *.");
00089 FixedWidthOutPut.printCenteredln(PW,Longer,(len+11),'*');
00090 System.out.println("Printing the non-numeric String " +
00091 " of length = " + len + " in column width " + (len-5) + "\n"
00092 + "center justified, padded with character *.");
00093 FixedWidthOutPut.printCenteredln (PW,Longer,(len-5),'*');
00094
00095 }
00096 }//Listing 8.10B

The testing strategy for the class FixedWidthOutput includes printing the numeric
and non-numeric strings of length equal to, greater than, and lesser than the print
field width. Print formats include left justified, right justified and center justified.
Figure 8.23 shows the results. (The first three characters in Figure 8.23 are line
numbers, which are not the part of output).

001 Outputting string "A really really really long String of length = 49" in column width = 49
002 A really really really long String of length = 49
003 Outputting string "A really really really long String of length = 49" in column width = 40
004 A really really really long String of le
005 Outputting string "A really really really long String of length = 49" in column width = 59 left
justified padded with character *.
006 A really really really long String of length = 49**********
007 Outputting string "A really really really long String of length = 49" in column width = 59 right
justified padded with character *.
008 **********A really really really long String of length = 49
009 Proceeding to demonstrate numeric outputs.
010 Printing the numeric String -90009.90009 of length = 12 in column width 12
011 -90009.90009
012 Printing the numeric String -90009.90009 of length = 12 in column width 7
013 -90009.90009
014 Printing the numeric String -90009.90009 of length = 12 in column width 22
0015 right justified, padded with character *.
0016 **********-90009.90009
017 Printing the numeric String -90009.90009 of length = 12 in column width 22
018 left justified, padded with character *.
019 -90009.90009**********
020 Printing the numeric String -90009.90009 of length (after formatting) = 13 in column width 13
021 (90009.90009)
022 Printing the numeric String -90009.90009 of length (after formatting) = 13 in column width 8
023 (90009.90009)
024 Printing the numeric String -90009.90009 of length (after formatting) = 13 in column width 23
025 right justified, padded with character *.
026 **********(90009.90009)
027 Printing the numeric String -90009.90009 of length (after formatting) = 13 in column width 23
028 left justified, padded with character *.
029 (90009.90009)**********
030 Now testing centered printing. For numeric values we use negative currency.
031 Printing the currency String of length (after formatting) = 11 in column width 22
032 center justified, padded with character *.

CS3 Java – Topic 8: Standard IO (Singhal) Page 55 of 99


033 *****($9,999.98)******
034 Printing the currency String of length (after formatting) = 11 in column width 6
035 center justified, padded with character *.
036 ($9,999.98)
037 Printing the non-numeric String of length = 14 in column width 25
038 center justified, padded with character *.
039 *****A short String******
040 Printing the non-numeric String of length = 14 in column width 9
041 center justified, padded with character *.
042 A short S
FIG. 8.23

The string Longer of length 49 is declared (L8.10B#9). A PrintWriter object is


created (L8.10B# 14), which will automatically flush the buffer when the method
println is called. String Longer is printed in column width equal to its length
(L8.10B#15). Figure 8.23 Lines F8.23#1-2, show the literal display of the string as
expected. The string is then printed right justified in a column width that is nine
characters less than the string length (L8.10B#18). F8.23#4 shows that nine
characters have been chopped off right side of the string. L8.10#22 prints the string
Longer left justified in column width = 59 and fill character ‘*’. F8.23#6 shows that
ten stars have been printed to the right of the string. L8.10#26 prints the same string
again, except that this time it is printed right justified. F8.23#8 shows that this time
ten stars are printed to the right of the string. The floating-point number
val = -90009.9000 is then printed in format "00000.00000" , first in the column
width equal to its length L8.10#33-35. F8.23#11 shows that the numeric val is
printed properly. Then val is printed in column width of five columns less than its
width (L8.10#37-39). We see that in spite of the reduced output width the numeric
val is printed in its entirety (F8.23#13). Then we print the numeric val, right
justified, in field width that is 10 columns larger than width of val (L8.10#41-44).
We see that numeric is printed in its entirety with 10 leading stars as fill characters
(F8.23#16). The left justification printing of val in larger field width (L8.10#46-49),
creates similar results, except that now fill stars are printed as lagging characters
(F8.23#19).

Java allows one to provide a separate pattern for the negative numbers, which
includes a prefix and/or a suffix. The format string "00000.00000;(00000.00000)"
provides a left and right parenthesis for the negative number as is customary in
Locale USA (L8.10#51). Using this new format string val is printed in field width
less than and equal to its width (L8.10#53-59). In both cases the full numeric
encased in a pair of parentheses is printed (F8.23#21 & #23). The results from right
justified and left justified printing (L8.10##61-69) in larger field widths are similar
(F8.23##26 & #29), as the leading and lagging fill stars are printed.

Centered printing is tested next using a negative currency, where the initial value of
the currency is set to val = -9999.98456 (L8.10#73). The format string for val is then
created using the getCurrencyInstance method of NumberFormat class (L8.10#74).
This currency string is then center justified printed in field widths that are 11

CS3 Java – Topic 8: Standard IO (Singhal) Page 56 of 99


column larger and five columns shorter respectively (L8.10#76-83). When column
width larger by 11 characters is used, then val is center printed as:

*****($9,999.98)******

printing five stars before the number and six after it (F8.23#33). You may recall that
it was coded into the algorithm that if in center printing, the number of extra
columns is an odd number, then extra fill character is printed to the right side of the
printed string. The numeric currency string prints in entirety even when field width
is lower than its length (F8.23#36).

Finally center printing of non-currency string tested. The significant result in this
test is that if output field width is smaller than the string length than lagging
characters are chopped off. Code line L8.10#90-93 output the result (F8.23#42)
where the string “A short String” is printed shortened by five columns as
“A short S”. The decision to chop off the lagging characters is arbitrary, but logical,
as the printing of leading characters gives a fair idea about the contents of the whole
string.

Miscellaneous File Manipulations


In reading from a file or writing to a file, we have assumed so far, that a file or drive
for file exists, and user has provided their names with out any error. There are
situations, however that by mistake user may provide the name of an existing file to
write into, resulting in file being overwritten (unless, append method is used). It is
also possible that by mistake the name of an input file that does not have read
permission is given. Java class java.io.File is file authentication and manipulations
to avoid errors similar to above. A File class constructor that takes the path to file
name as a String is described below.
public File(String pathname)
Creates a new File instance by converting the given pathname string into an
abstract pathname. If the given string is the empty string, then the result is the
empty abstract pathname.

Parameters:
pathname - A pathname string
We should become clear about the terms pathname and abstract pathname. The
abstract pathname for a file/folder is the full path name, which starts with the drive
letter (in Windows) and terminates with the file/folder name. The abstract
pathname has two components:

1. An optional system dependent prefix string. It can be one of the followings:


A] A disk drive specifier.
B] The string “/” for Unix root directory.
C] The string “\\” for a Microsoft Windows UNC (Universal Naming
Convention) pathname.

CS3 Java – Topic 8: Standard IO (Singhal) Page 57 of 99


2. A sequence of zero or more strings as the names for folders or file.

Every name in the abstract pathname, except for the last one is a
directory or folder. The last one could be a directory or a file. For example the
Figure 8.24 shows the directory structure to get to the folder
Topic02IntroductionToJava. If we were to use the file HelloWorld.java from this
folder, then the abstract pathname for

FIG. 8.24
DOS style abstract pathname
this file would be:

C:\_Courses\_Java\Topic02IntroductionToJava\HelloWorld.java

On a Unix system, the corresponding abstract pathname may look like as follows:

Unix style abstract pathname

/_Courses/_Java/Topic02IntroductionToJava/HelloWorld.java

The UNC pathname system is used for computers that are networked together on a
Windows 9x, NT, 2000, or XP network. In such network, each computer is given a
name, and there may be a shared folder, which is accessible to all network members.
Assume that the name of the computer, which contains the shared folder _Courses,
is ComPC. Then the abstract pathname string (assuming the file structure similar to
the one shown in Figure 8.24) would be:

CS3 Java – Topic 8: Standard IO (Singhal) Page 58 of 99


Windows networked computers style abstract pathname

\\ComPc\_Courses\_Java\Topic02IntroductionToJava\HelloWorld.java

However if a file and a class using it reside in the same folder, then one can simply
pass the file name to the constructor of File class. The constructor then converts that
file name into an abstract pathname by getting additional information from the
operating system.

Notice that we state of two components for abstract pathname, the first one is
optional. Therefore the abstract pathname can have two forms, which are:
1. Absolute pathname: which requires the part one of the two components,
and which ascertains that no additional information is required by JVM to
locate the file.
2. Relative pathname: If absolute pathname is not given then JVM needs
additional information to locate the file. JVM attempts to locate the file
“relative” to the directory in which it was invoked. For example when we
only provide the name of a file that resides in the folder, in which JVM was
invoked, it is found because JVM first looks for it in the current directory.
Any pathname that is not absolute will be interpreted as a relative pathname.
It appears that on Windows system, either file name provided must be absolute, or
the file must be in the folder in which JVM is invoked.

Table 8.11 gives the summary of important methods from class java.io.File. The
important point in understanding the description of File class methods is, that once
a File object is created by passing a pathname string to the File class constructor,
then the File object thus created represents that directory or file.

Method name ( all Return Description


instance methods) Type
canRead ( ) boolean Returns true if the file specified by the abstract
pathname stored in this File object exists and is
readable by the application; otherwise returns
false.
canWrite ( ) boolean Returns true if the file specified by the abstract
pathname stored in this File object can be written
into and has the write permission; otherwise
returns false.
createNewFile ( ) boolean Returns true if the file specified by the abstract
pathname stored in this File object does not exist
and is successfully created; otherwise returns
false.

CS3 Java – Topic 8: Standard IO (Singhal) Page 59 of 99


delete ( ) boolean Returns true if the file/directory specified by the
abstract pathname stored in this File is
successfully deleted; otherwise returns false. The
directory can only be deleted if it is empty!
deleteOnExit ( ) void Requests to JVM to delete the file/directory
stored in this File object upon “normal”
termination of JVM operation17. Deletion, once
requested, cannot be cancelled.
exists ( ) boolean Returns true if the file/directory specified by the
abstract pathname stored in this File object
exists; otherwise returns false.
getAbsolutePath ( ) String Returns the absolute pathname for the abstract
pathname stored in this File object.
getName ( ) String Returns the name of the file/directory stored in
this File object. Only the last portion of the
abstract pathname string is returned.
getParent ( ) String Returns the name of the parent directory of the
directory/file for this File object. Returns a null if
there is no parent directory.
getParentFile ( ) File Gets the File object form of the parent directory
of directory/file for this File object.
getPath ( ) String Converts the abstract pathname string stored in
this File object to absolute pathname and returns
it. Uses the system dependent separator strings as
needed.
isAbsolute ( ) boolean Returns true if the abstract pathname stored in
this File object is absolute; otherwise returns
false.
isDirectory boolean Returns true if the abstract pathname stored in
this File object is a directory; otherwise returns
false.
isFile ( ) boolean Returns true if the abstract pathname stored in
this File object is a file; otherwise returns false.
isHidden ( ) boolean Returns true if the abstract pathname stored in
this File object is a hidden file; otherwise returns
false.
lastModified long Returns the time at which the file with abstract
pathname stored in this File object was last
modified.
length ( ) long Returns in bytes the length of the file whose
abstract pathname is stored in this File object.

17
Deletion will not be done if an abnormal program termination, for example invoking of an
exception took place.

CS3 Java – Topic 8: Standard IO (Singhal) Page 60 of 99


reNameTo(File dest ) boolean Returns true if able to successfully rename this
File object into the File object dest; otherwise
returns false. Renaming is system dependent.
Table 8.11

Class IOManagement
We design a class IOManagement, whose member methods would create the objects
of File class, and use its methods to facilitate input/output in Java programs. Clients
of class IOManagement would only be able to access some of its static methods and
would not be able to instantiate it. The class would have the methods that would
fulfill the following goals:
1. Return a BufferedReader object to read from keyboard.
2. Return a BufferedReader object to read from a file.
3. Return an object to write to a newly created output file in the buffered mode.
4. Return an object to append to a new or existing file in buffered mode.
5. Return a String, which has the description of main properties of a File object
passed to the method.

Table 8.12 gives a summary description of the member methods for class
IOManagement. Notice that method getFileName and constructor are private
members. The method getFileName is only used internally by other class methods.
All methods are static.

CS3 Java – Topic 8: Standard IO (Singhal) Page 61 of 99


Details of the Member Methods for IOManagement Class
private IOManagement()
private constructor to prevent the instantiation of class IOManagement.

getFileName
private String getFileName(String Name)
throws java.io.IOException
Gets the String for the name of input file that exists and is not empty, not
hidden, can be read, and output file which either does not exist or is intended
to be re-written or appended by the user and has write permission.
Parameters:
Name - is the name of the file to be opened for reading or writing.
Returns:
The valid String with the filename.

getFileReader
public static BufferedReader getFileReader()
throws java.io.IOException
Gets the BufferedReader object bonded to an existing input file.
Returns:
The BufferedReader object for an existing input file.

getFileWriter
public static PrintWriter getFileWriter()
throws java.io.IOException
Gets the PrintWriter object bonded to an existing output file to write in
buffered mode.
Returns:
The PrintWriter object to a existing output file.

getFileWriterAppend
public static PrintWriter getFileWriterAppend()
throws java.io.IOException
Gets the PrintWriter object that will append to an existing file, in buffered
writing mode.
Returns:
The PrintWriter object to a existing output file to append to it.

getKeyboardReader
public static BufferedReader getKeyboardReader()
throws java.io.IOException
Gets the BufferedReader object to read from keyboard
Returns:
The BufferedReader object to read from keyboard.

getProperties
public static String getProperties(File My_File)

CS3 Java – Topic 8: Standard IO (Singhal) Page 62 of 99


Determines the properties of the File object passed and returns a String
object with its properties description.
Parameters:
My_File - is the File object whose properties are to be determined.
Returns:
The String with the description of properties of My_File.
Table 8.12

Most important method in class IOManagement is the private method getFileName,


whose purpose is to get from the user a “valid” name for an input or output file. The
method would prompt the user to enter the name for an input or output file to be
used. For all file types the method must make sure that name entered is not a null or
zero length string. For an input file the method getFileName must check for the
followings:
1. The name given is not a directory or folder.
2. The file with given name exists.
3. The file with the given name is not empty.
4. The file is not hidden.
5. The file has the permission to be read.
For an output file the method must check for the followings:
1. If the name given is an existing file then confirm with the user that they wish
to overwrite it or to append to it.
2. The file has the write permission.
3. The file is not hidden.

The ALG 8.5 gives the algorithm for the method getFileName.

CS3 Java – Topic 8: Standard IO (Singhal) Page 63 of 99


ALG 8.5
private static String getFileName (String Name) throws IOException
1. Set the boolean variable done to false
2. Set the String variable File_Name to zero length string
3. Do the followings while done is false
Prompt user to enter the file name and store input into File_Name
If the object File_Name is null or a zero length string
3.21 Then display message that no file name has been entered.
3.22 Set done to false.
Else
Create File object FR from string File_Name.
Determine if the FR refers to an existing object and set boolean variable existing
to true if it exists or set to false otherwise.
If string Name equals to “input” and file does not exists then
3.331 Display the message that file doe not exist
3.332 Set done to false
Else If the Name equals to “input and file exists then
3.341 If FR does not have read permission then
3.3411 Display the message that the file cannot be read
3.3412 Set done to false
3.342Else If FR is not a file then
3.3421 Display the message that the FR is not a file
3.3422 Set done to false
3.343 Else if FR is a hidden file or directory then
3.3431 Display the message that FR is a hidden object
3.3432 Set done to false.
3.344 Else If the length of object FR is zero then
3.3441 Display the message that input file is empty
3.3442 Set done to false
3.345 Else
3.3451 Set done to true
Else if Name equals to “output” and File exists then
3.351 If Object FR is a File then
3.3511 If FR is not hidden and has write permission then
3.35111 Inform user that file already exists, and would
they like to overwrite it or append to it?
3.35112 Store user response in character response
3.35113 If response is ‘Y’ or ‘y’ then
3.351131 Set done to true
3.35114 Else if response is “’N’ or ‘n’ then
3.351141 Set done to false
3.35115 Else
3.351151 Display message “invalid response”
3.351152 Set done to false
3.3512 Else
3.35121 Display the message that either FR is a hidden

CS3 Java – Topic 8: Standard IO (Singhal) Page 64 of 99


file or it does not have write permission
3.35122 Set done to false
3.352 Else
3.3521 Display the message that given name is not a file
3.3522 Set done to false
Else
3.361 Set done to true
4. Return File_Name

In ALG 8.5 Section 3.34 ascertains that the input file is actually a file, is not hidden,
has read permission, and has data in it; otherwise the user is iterated through to
enter the input file name again. Section 3.35 ascertains that if output file exists then
it has write permission, it is a file, it is not hidden and user wishes to overwrite or
append to it; otherwise user is iterated through to enter the output file name again.
Listing 8.11 shows the source code for the class IOManagement.
00001 import java.io.*;
00002 import java.util.*;
00003 public class IOManagement
00004 {
00009 private IOManagement(){}
00017 private static String getFileName(String Name)throws IOException
00018 {
00019 boolean done = false;
00020 String File_Name = "";
00021 BufferedReader KB = getKeyboardReader();
00022 do
00023 {
00024 System.out.println("Type the " + Name + " file name and press enter key.");
00025 File_Name = KB.readLine();
00026
00027 if(File_Name == null || File_Name.length() == 0)
00028 {
00029 System.out.println("No file name entered.");
00030 done = false;
00031 }
00032 else
00033 {
00034 File FR = new File(File_Name.trim());
00035 boolean isExisting = FR.exists();
00036 if(Name.equals("input")&& (!isExisting))
00037 {
00038 System.out.println("The input file does not exist.");
00039 done = false;
00040 }
00041 else if(Name.equals("input")&& isExisting)

CS3 Java – Topic 8: Standard IO (Singhal) Page 65 of 99


00042 {
00043 if(!FR.canRead())
00044 {
00045 System.out.println("File does not have the read permission.");
00046 done = false;
00047 }
00048 else if(!FR.isFile())
00049 {
00050 System.out.println("The name " + File_Name +" is not a file.");
00051 done = false;
00052 }
00053 else if(FR.isHidden())
00054 {
00056 System.out.println("The name " + File_Name +" is a hidden file.");
00057 done = false;
00058 }
00059 else if(FR.length() == 0)
00060 {
00061 System.out.println("The name " + File_Name +" is an empty file.");
00062 done = false;
00063 }
00064 else
00065 done = true;
00066 }
00067 else if(Name.equals("output")&& isExisting)
00068 {
00069 if(FR.isFile())
00070 {
00071 if(FR.canWrite() && !FR.isHidden())
00072 {
00073 System.out.println("The output file with name " + File_Name +
00074 " already exists. Would you like to overwrite or append to the " + "\n" +
00075 "existing file? [Y]es or [N]o?");
00076 char response = KB.readLine().trim().charAt(0);
00077
00078 if(response == 'Y'||response == 'y')
00079 done = true;
00080 else if(response == 'N' || response == 'n')
00081 done = false;
00082 else
00083 {
00084 System.out.println("Invalid response.");
00085 done = false;
00086 }
00087 }
00088 else

CS3 Java – Topic 8: Standard IO (Singhal) Page 66 of 99


00089 {
00090 System.out.println("The file " + File_Name +
00091 " either does not have write permission or is a hidden file.");
00092 done = false;
00093 }
00094 }
00095 else
00096 {
00097 System.out.println("The given name " + File_Name +" is not a file.");
00098 done = false;
00099 }
00100 }
00101 else
00102 done = true;
00103 }
00104 }while(!done);
00105
00106 return File_Name;
00107 }
00112 public static BufferedReader getFileReader()throws IOException
00113 {
00114 String In_File = getFileName("input");
00115 return new BufferedReader(new FileReader(In_File));
00116 }
00122 public static PrintWriter getFileWriter()throws IOException
00123 {
00124 String Out_File = getFileName("output");
00125 FileWriter FW = new FileWriter(Out_File);
00126 return new PrintWriter(new BufferedWriter(FW),true);
00127 }
00134 public static PrintWriter getFileWriterAppend()throws IOException
00135 {
00136 System.out.println("Stand by to provide the name of file to append to.");
00137 String Out_File = getFileName("output");
00138 FileWriter FW = new FileWriter(Out_File,true);
00139 return new PrintWriter(new BufferedWriter(FW),true);
00140 }
00145 public static BufferedReader getKeyboardReader() throws IOException
00146 {
00147 return new BufferedReader(new InputStreamReader(System.in));
00148 }
00156 public static String getProperties(File My_File)
00157 {
00158 String Str = "";
00159
00160 if(My_File.exists())

CS3 Java – Topic 8: Standard IO (Singhal) Page 67 of 99


00161 {
00162 Str = "The absolute path to this file/directory = " +
00163 My_File.getAbsolutePath()+"\n";
00164 Str+="The path to this file/directory = "
00165 +My_File.getPath()+"\n";
00166
00167 if(My_File.isFile())
00168 {
00169 Str+= "The file was last modified on: " +
00170 new Date(My_File.lastModified()).toString() + "\n";
00171 Str+= "The size of the file = " + My_File.length()+" bytes." +"\n";
00172
00173 if(My_File.canRead())
00174 Str+= "This file can be read\n";
00175 else
00176 Str+="This file does not have read permission.\n";
00177
00178 if(My_File.canWrite())
00179 Str+="This file has write permission.\n";
00180 else
00181 Str+="This file does not have write permission.\n";
00182
00183 if(My_File.isHidden())
00184 Str+="This File is a hidden file.\n";
00185 else
00186 Str+="This File is not a hidden file.\n";
00187 }
00188 else if(My_File.isDirectory())
00189 {
00190 Str+= "The directory was last modified on: " +
00191 new Date(My_File.lastModified()).toString() + "\n";
00192 Str+= "The size of the directory = " + My_File.length()+" bytes." +"\n";
00193
00194 if(My_File.canRead())
00195 Str+= "This directory can be read\n";
00196 else
00197 Str+="This directory does not have read permission.\n";
00198
00199 if(My_File.canWrite())
00200 Str+="This directory has write permission.\n";
00201 else
00202 Str+="This directory does not have write permission.\n";
00203
00204 if(My_File.isHidden())
00205 Str+="This directory is a hidden directory.\n";
00206 else

CS3 Java – Topic 8: Standard IO (Singhal) Page 68 of 99


00207 Str+="This directory is not a hidden directory.\n";
00208 }
00209 if(My_File.isAbsolute())
00210 Str+="The parent of this file/directory = " +
00211 My_File.getParent()+"\n";
00212 }
00213 else
00214 Str = "The object does not refer to an existing file or directory.";
00215
00216
00217 return Str;
00218 }
00219
00220 }
//Listing 8.11

Other Member methods of class IOManagement


Three public member methods of class IOManagement, getFileReader,
getFileWriter, and getFileWriterAppend, call the private method getFileName to
receive a valid file name string. The method getFileReader returns a
BufferedReader object bonded to the input file. The method getFileWriter returns a
PrintWriter object, which is bonded to a BufferedWriter object, which in turn is
bonded to a FileWriter object for the given output file name. The multiple bindings
performed by these methods are displayed by Figures 8.25A-B.

FIG. 8.25 A

CS3 Java – Topic 8: Standard IO (Singhal) Page 69 of 99


The method getFileReader binds the input file name string to a FileReader object,
which in turns binds to a BufferedReader object, and the composite object is
returned to the caller of the method.

Can choose the buffer


size by calling proper
constructor

FIG. 8.25B
The method getFileWriter binds the output file name to a FileWriter object, which
in turns binds to a BufferedWriter object, which finally binds to a PrintWriter
object, and method returns this composite object to the caller. The method
getFileWriterAppend works in a manner similar to the method getFileWriter, with
one difference, that the object FileWriter is built to append to the output file. This is
done by calling a FileWriter constructor, where the second argument (a boolean) is
set to true to indicate that output file must be written in the append mode
(L8.11#138).

Method getProperties
The method getProperties gets a File object and returns a string, which displays the
properties of the file object passed to it provided that the object is bonded to a file or
directory. The code first checks whether the object passed is an existing file or
directory or not (L8.11#160). If object exists then its absolute path and abstract path
is concatenated to the string to be returned (Str). Inside the first if block, the
method has two if/else-if blocks. The first block executes if the File object is a file
(L8.11#168-187). Following tests are done on the file object and the relevant
information is added to the string Str.
1. Date on which the file was modified last (L8.11#169-170). Understand that
the method lastModified returns the time as a long number. To convert it to
an actual date format, we pass it to the constructor of class java.uti.Date and
then call toString method for Date class to convert to regular date format.
For example the code line such as:

CS3 Java – Topic 8: Standard IO (Singhal) Page 70 of 99


new Date (num).toString( ); will change the number num to the
date format provided num refers to actual date returned from method
lastModified.
2. The size of the file in bytes (L8.11#171).
3. Program tests whether file has read permission or not and relevant
information is added to Str (L8.11#173-176).
4. The program tests if the file has the write permission or not and the relevant
information is concatenated to Str (L8.11#178-181).
5. Finally if the file is hidden then information pertaining to that is added to the
string Str (L8.11#183-186).

The else-if block (L8.11#188-208) performs the above tests (1 to 5) if the File object
is a directory, and concatenates the results to string Str. The abstract pathname
stored in the object File may be an absolute pathname or a relative one. The
program can find the parent of the file object only if the pathname stored is absolute
one. Therefore the method performs a test whether the File object has an absolute
path stored in it (L8.11#209). If that is true then the name of the parent is added to
the information string Str (L8.11#211-212). If the File object does not exist then the
string returned indicates that the file/directory does not exist.

Testing class IOManagement


To test various member methods of class IOManagement, we need the following
types of files:
1. An input file that has no data in it.
2. A file that is hidden.
3. A file that has no write access.
4. A file that has no read access (It is impossible to have a file with no read
permission in Windows 98).
5. Directories having similar properties as above.
The code to test the class IOManagement is simple (Listing 8.12).
00001 import java.io.*;
00002
00003 public class TestIOManagement
00004 {
00005 public static void main(String[] args) throws IOException
00006 {
00007 BufferedReader KB = IOManagement.getKeyboardReader();
00008 BufferedReader FReader = IOManagement.getFileReader();
00009 PrintWriter PWriter = IOManagement.getFileWriter();
00010 PrintWriter PWriter_Append = IOManagement.getFileWriterAppend();
00011 System.out.println("Enter the name of File/directory to get properties.");
00012 File My_File = new File(KB.readLine().trim());
00013 System.out.println(IOManagement.getProperties(My_File));
00014 }
00015 }//Listing 8.12

CS3 Java – Topic 8: Standard IO (Singhal) Page 71 of 99


The results of running the code in Listing 8.12 under various conditions is shown in
Figure 8.26.
User either presses the
Results from executing all lines in Listing 8.12
enter key or presses
00003 Type the input file name and press enter key.
00004 Control + Z
00005 No file name entered.
00006 Type the input file name and press enter key.
00007 Type the input file name and press enter key.
00008 DoesNotExist
00009 The input file does not exist.
00010 Type the input file name and press enter key.
00011 hidden
00012 The name hidden is a hidden file.
00013 Type the input file name and press enter key.
00014 html
00015 The name html is not a file.
00016 Type the input file name and press enter key.
00017 empty
00018 The name empty is an empty file.
00019 Type the input file name and press enter key.
00020 inventory.txt
00021 Type the output file name and press enter key.
00022 html
00023 The given name html is not a file.
00024 Type the output file name and press enter key.
00025 no_write
00026 The file no_write either does not have write permission or is a hidden file.
00027 Type the output file name and press enter key.
00028 hidden
00029 The file hidden either does not have write permission or is a hidden file.
00030 Type the output file name and press enter key.
00031 sys
00032 The output file with name sys already exists. Would you like to overwrite or
00033 append to the existing file? [Y]es or [N]o?
00034 dddddddddd
00035 Invalid response.
00036 Type the output file name and press enter key.
00037 sys
00038 The output file with name sys already exists. Would you like to overwrite or
00039 append to the existing file? [Y]es or [N]o?
00040 N
00041 Type the output file name and press enter key.

CS3 Java – Topic 8: Standard IO (Singhal) Page 72 of 99


00042 sys
00043 The output file with name sys already exists. Would you like to overwrite or
append to the existing file? [Y]es or [N]o?
00046 Y
00047 Stand by to provide the name of file to append to.
00048 Type the output file name and press enter key.
00049 sys
00050 The output file with name sys already exists. Would you like to overwrite or
append to the existing file? [Y]es or [N]o?
00053 Y
00054 Enter the name of File/directory to get properties.
00055 html
00056 The absolute path to this file/directory =
C:\_Courses\_Java\_LectureNotes\_Topi
00057 c08StandardInputAndOutputInJava\FixedWidthOut\html
00058 The path to this file/directory = html
00059 The directory was last modified on: Sun Apr 11 19:55:14 PDT 2004
00060 The size of the directory = 0 bytes.
00061 This directory can be read
00062 This directory has write permission.
00063 This directory is not a hidden directory.
00065 Results from executing only line 7 and 9 in Listing 8.12
00066 Type the output file name and press enter key.
00067
00068 No file name entered.
00069 Type the output file name and press enter key.
00070 Type the output file name and press enter key.
00071 createIt
00073 Results from executing only lines 7 and 11-13 in Listing 8.12
00075 Run#1
00076 -----------------------------------------------------------------------------------
00077 DoesNotExist
00078 The object does not refer to an existing file or directory.
00079 ---------------------------------------------------------------------------------
00080 Run #2
00081 -----------------------------------------------------------------------------------
00082 Enter the name of File/directory to get properties.
00083 HiddenDirectory
00084 The absolute path to this file/directory =
C:\_Courses\_Java\_LectureNotes\_Topi
00085 c08StandardInputAndOutputInJava\FixedWidthOut\HiddenDirectory
00086 The path to this file/directory = HiddenDirectory
00087 The directory was last modified on: Sun Apr 18 13:46:06 PDT 2004

CS3 Java – Topic 8: Standard IO (Singhal) Page 73 of 99


00088 The size of the directory = 0 bytes.
00089 This directory can be read
00090 This directory has write permission.
00091 This directory is a hidden directory.
00092 ---------------------------------------------------------------------------------------------------
00093 Run #3
00094 ---------------------------------------------------------------------------------------------
00095 Enter the name of File/directory to get properties.
00096 NoWriteDirectory
00097 The absolute path to this file/directory = C:\_Courses\_Java\_LectureNotes\
00098 _Topic08StandardInputAndOutputInJava\FixedWidthOut\NoWriteDirectory
00099 The path to this file/directory = NoWriteDirectory
00100 The directory was last modified on: Sun Apr 18 13:46:48 PDT 2004
00101 The size of the directory = 0 bytes.
00102 This directory can be read
00103 This directory does not have write permission.
00104 This directory is not a hidden directory.
00105 ---------------------------------------------------------------------------------------------------
00106 Run #4
00107 ---------------------------------------------------------------------------------------------------
00108 Enter the name of File/directory to get properties.
00109
C:\_Courses\_Java\_LectureNotes\_Topic08StandardInputAndOutputInJava\
FixedWidthOut\IOManagement.java
00111 The absolute path to this file/directory = C:\_Courses\_Java\_LectureNotes
00112
\_Topic08StandardInputAndOutputInJava\FixedWidthOut\IOManagement.java
00113 The path to this file/directory = C:\_Courses\_Java\_LectureNotes\
00114 _Topic08StandardInputAndOutputInJava\FixedWidthOut\IOManagement.java
00115 The file was last modified on: Sun Apr 18 13:11:04 PDT 2004
00116 The size of the file = 6654 bytes.
00117 This file can be read
00118 This file has write permission.
00119 This File is not a hidden file.
00120 The parent of this file/directory = C:\_Courses\_Java\_LectureNotes\
00121 _Topic08StandardInputAndOutputInJava\FixedWidthOut
00122 ---------------------------------------------------------------------------------------------------
00123 Run #5
00124 ---------------------------------------------------------------------------------------------------
00125 Enter the name of File/directory to get properties.
00126
C:\_Courses\_Java\_LectureNotes\_Topic08StandardInputAndOutputInJava\
FixedWidthOut\html
00128 The absolute path to this file/directory = C:\_Courses\_Java\_LectureNotes\
00129 _Topic08StandardInputAndOutputInJava\FixedWidthOut\html

CS3 Java – Topic 8: Standard IO (Singhal) Page 74 of 99


00130 The path to this file/directory = C:\_Courses\_Java\_LectureNotes\
00131 _Topic08StandardInputAndOutputInJava\FixedWidthOut\html
00132 The directory was last modified on: Sun Apr 11 19:55:14 PDT 2004
00133 The size of the directory = 0 bytes.
00134 This directory can be read
00135 This directory has write permission.
00136 This directory is not a hidden directory.
00137 The parent of this file/directory = C:\_Courses\_Java\_LectureNotes\
00138 _Topic08StandardInputAndOutputInJava\FixedWidthOut
00139 -----------------------------------------------------------------------
FIG. 8.26 : All user input is in italics and is highlighted.
All user input on console is italicized and highlighted in the Figure 8.26. In Listing
8.12, first a BufferedReader object is created (L8.12#7). Then call is made to method
getFileReader (L8.12#8). The getFileReader calls the method getFileName
(L8.11#114). If user simply presses an enter key, that amounts to entering a zero
length string, and it executes the L8.11#27-31. Therefore the do-while loop in
getFileName method in Listing 8.12 is executed again. Similar result is obtained if
user presses Control + Z keys on Windows 98, which amounts to reaching an end of
file and entering a null string. Consequently program asks for the file name again
(F#8.26-01-07). When user enters the name of a file that does not exist,
DoesNotExist (F8.26#8), then isExisting (L8.11#35) is set to false, and L8.11#36-
37 inform user that no such file exists F8.26#9. As program continues the user enters
the name of a hidden file hidden (F8.26#11), name of a directory html (F8.26#14),
and name of a file empty, which has no data in it (F8.26#17). In each case a
respective block in Listing 8.12 is executed and user is iterated back to provide an
input file name. Finally the user provides the name of file, inventory.txt, which
meets the criterion of a readable input file F8.26#20, and the method getFileName
executes the code line (L8.11#65) exiting from do-while loop and returning a valid
input file name string to method getFileReader. The method then returns the object
BufferedReader to the call made in Listing 8.12 line (L8.12#8).

Line (L8.12#9) calls the method getFileWriter from IOManagement class. This
method also calls the getFileName method (L8.11#124), which prompts the user to
enter an output file name. When user enters the file names html, a directory
(F8.26# 22), no_write, a file with read only access (F8.26#25), and a hidden file
hidden (F8.26#28), the user is iterated through the do-while loop in method
getFileName (Listing 8.12) each time with appropriate message printed for the user.
Then user enters a filename sys (F8.26#31), which exists. Since this is a pre-existing
file the program asks user if they would like to overwrite this file or append to it
(F8.26#32-33). If user response is not ‘Y’ or ‘y’, then they are iterated through
again, until a valid yes response is received (F8.26#34, F8.26#37, F8.26#40, F8.26#42,
and F8.26#46). If user provides the name of an existing output file then loop
iteration stops only under two conditions. Either user wishes to overwrite or append

CS3 Java – Topic 8: Standard IO (Singhal) Page 75 of 99


to this file or user provides the name of an output file that does not exist. Finally the
method getFileWriter returns (L8.11#126) a PrintWriter object to its caller
(L8.12#9).

Method getFileWriterAppend works very similar to the method getFileWriter.


Therefore we do not discuss it here and the mapping of output lines F8.26#47-56
with the code in Listing 8.12 would clarify the method functioning.

Finally in Listing 8.12 we test the method getProperties from class IOManagement
(L8.12#11-13). User is prompted to provide the name of a file or directory whose
properties are needed. A File object is created, and the last line in Listing 8.12 print
the string returned from method getProperties. The user is prompted to provide the
file/directory, whose properties are needed (F8.26#54). The user provides the
directory html (F8.26#55). This directory has some html file in it. Program lists its
properties (F8.26#56-63). It is important to note that length method in File class
gives a size only for files, and it will always show a size of zero for anything that is
not a file or for an empty file. Lines F8.26#70-71 show that if method getFileReader
is called and a name of non-existing file is given, then such file (CreateIt) is simply
created.

Five more tests are done on method getProperties (Run #1 to Run #5, Figure 8.26).
In Run #1 the name of a non-existing object DoesNotExist is provided, and as
expected by executing the line L8.11#213-214, the program prints that such object
does not exist (F8.26#78). In Run #2 a hidden directory HiddenDirectory is
provided and passed as File object to method getProperties. Its properties are
printed in Figure 8.26, (F8.26#84-91). The line F8.26#91 confirms the hidden status
of this directory.

Understand that the parent of a file or directory is printed only when the path
provided to the program is absolute path. For example in Run #4 the absolute path
to file IOManagement.java is provided (F8.26#109-110). This path is:

C:\_Courses\_Java\_LectureNotes\_Topic08StandardInputAndOutputInJava\
FixedWidthOut\IOManagement.java

The program correctly prints out its parent (F8.26#120-121) as:

The parent of this file/directory = C:\_Courses\_Java\_LectureNotes\


_Topic08StandardInputAndOutputInJava\FixedWidthOut

Run #5 shows that when the full path to a directory is given (F8.26#126-127), then
its parent directory is also printed (F8.26#137-138). As long as the abstract path
stored in the File object is absolute path, its parent can be determined and
displayed.

CS3 Java – Topic 8: Standard IO (Singhal) Page 76 of 99


Case Study: Inventory Report for Jane Doe Hardware International
It is common for retail businesses to create reports on their stock inventory. Such
inventory reports give summary and details of items, their unit prices, and total cost
of the inventory. This combined information may give a snap shot of the status of
sales and re-orders facilitating business decisions. Let us assume that Jane Dow
International Hardware asked you to write a program, so that each of their location
can create an inventory report to see the status of their stock. They keep their
inventory data in a text file, which may look like Figure 8.27 below.

FIG. 8.27
The file shown in Figure 8.27 is an ASCII file, where data are stored in the following
order: Part Name (either one word or many words joined by underscore), number
of units, and unit price. For example in above figure, the first set of data lists Chisel,
whose 50 units are in store and unit price is $9.99. The report is required in the
format shown in Figure 8.28.

Inventory
Table

Inventory
summary

FIG. 8.28
Notice that in inventory summary in the lower part of the report, the total cost of
inventory would be the sum of TOTAL VALUE column in the main report above it.

CS3 Java – Topic 8: Standard IO (Singhal) Page 77 of 99


Design of necessary classes:
Looking at the inventory report in Figure 8.28 it appears that we may need at least
two classes in writing overall software to create inventory reports. One class
manages the portion inventory table while other manages the inventory summary.
We therefore design the classes with the names InventorySummary, and
InventoryTable. Notice this software has other requirements such as:
• Data are read from and written to files.
• Creation of tables and summary format require printing data into some fixed
column widths.
To fulfill these requirements we use our previously developed classes
IOManagement, and FixedWidthOutPut. Therefore the software to be developed
includes the following five classes and their status in our software project (Table
8.13).

Class Status
IOManagement Written and tested
FixedWidthOutPut Written and tested
InventorySummary To be Written and tested
InventoryTable To be Written and tested
DriverInventory To be Written and tested
Table 8.13
One must know that several designs are possible to satisfy a certain set of user
requirements. In a sophisticated design one would produce three design alternatives,
which would include high end, middle end, and low-end solutions. The detail of
overall design methodology is discussed in chapter one of this book. Here we jump
first directly to designing the attributes and constants each of our un-designed
classes would need and then we decide on “intelligence” (which comes in forms of
class methods) to be imparted to each class.

Design of class InventorySummary


Examining the requirements from the summary part of the inventory report, an
object of class InventorySummary would need the following attributes or instance
fields:
1. Total cost of inventory
2. Cost of lowest priced item
3. Cost of highest priced item
4. Average cost of the items in inventory
5. Standard deviation of the price of items in inventory
6. Number of goods (items) in the inventory
The above six instance fields or data members design the numbers on the right hand
side of the inventory summary in Figure 8.28. However, the class uses some strings
as well, which are printed on left hand side of the inventory summary report. We
can store them as class constants. Therefore at least six string constants; each
forming the print heading for one of the above instance fields is needed. The Table
8.14 gives the instance fields and constants needed by the class InventorySummary.

CS3 Java – Topic 8: Standard IO (Singhal) Page 78 of 99


Summary of instance variable For class InventorySummary
private double cost_of_inv
Stores the total cost of inventory.

private double lowest_cost


Stores the cost of lowest priced item

private double highest_cost


Stores the cost of highest priced item.

private double ave_cost


Stores the average cost of the items in inventory

private double std_dev


Stores the standard deviation of the price of items in inventory

private int num_items


Stores the number of goods (items) in the inventory

private String Title


Title of Inventory Summary report

Summary of instance constants For class InventorySummary


Access
level/field Name Value
type/data type
private final int col 80
private final char fill_char1 ‘ ‘
private final char fill_char2 ‘*’
private final String Head1 "The total cost of inventory = "
private final String Head2 "The lowest cost item = "
private final String Head3 "The highest cost item = "
private final String Head4 "The average cost of inventory item = "

private final String Head5 "The cost standard deviation = "


private final String Head6 "Total number of units in inventory = "

private final boolean left false


private final String Message "Not Calculated"
private final boolean right true
Table 8.14

CS3 Java – Topic 8: Standard IO (Singhal) Page 79 of 99


Design of constructors and methods
Now we get to designing the “intelligence” the class InventorySummary must
possess. This relates to the following issues:
• Maintaining the invariants for the class
• Performing the operations needed on class data members or providing
services to other client classes.
The intelligence of a class is embedded in its constructors and methods18. We need to
maintain the following invariants for the class InventorySummary.
1. All numeric instance data members must not be negative.
2. The string instance data member must be non-null and non-zero in
length.
3. Data member lowest_cost must be lower than or equal to data
member highest_cost.
4. Data member ave_cost must be higher than or equal to lowest_cost
and also lower than or equal to member highest_cost.
5. Data member cost_of_inv must be equal to or greater than both
lowest_cost and highest_cost.
6. If num_items is zero then cost_of_inv19 must be zero.

All constructors and methods must maintain the above invariants. For the sake of
simplicity we do not, for now, write our code to maintain the above invariants. Later
on, when we have learned the technology of exception handling, we would revisit
this topic and introduce the technology for maintaining the above invariants.

In class InventorySummary we initialize the constant data members by technique


direct initialization. For example the constant data member col would be declared
and initialized as follows:

private final int col = 80;

All other constant data members would be initialized to values given in the last
column of lower table in Table 8.14. Table 8.15 summarizes the two constructors
provided. Additional constructors may be provided for testing purposes.

Summary of Constructors For Class InventorySummary


public InventorySummary()
No argument constructor.

public InventorySummary(double ci, double lc, double hc, double ac,


double sd, int ni, String Title1)
Initializes each class instance fields to the values passed to the constructor.
Initializes the Title field to "Summary Of" + the value passed to the

18
A class can have inner classes, in which such data member also add to the “intelligence” of
enclosing class. We discuss inner classes later.
19
In an improved design we may not need the instance variable cost_of_inv. Rather it can be derived
from the multiplication num_items*ave_cost.

CS3 Java – Topic 8: Standard IO (Singhal) Page 80 of 99


constructor.
Parameters:
ci - sets the cost_of_inv
lc - sets the lowest_cost
hc - sets the highest_cost
ac - sets the ave_cost
sd - sets the std_dev
ni - sets the num_items
Title1 - provides a portion of Title

Table 8.15
In addition to two constructors the class InventorySummary has only one method,
which is used to print the summary report. Table 8.16 gives the design summary of
method printInvSummary.

Summary of Methods For Class InventorySummary


public void printInvSummary(PrintWriter Pwriter)
Prints the InventorySummary to either the console or to a file.
Parameters:
Pwriter - is the object passed to print the InventorySummary to either a file or console.
Table 8.16

Algorithms
The algorithm for the constructor is straightforward. Therefore we only discuss the
algorithm for method printInvSummary (ALG 8.6).

CS3 Java – Topic 8: Standard IO (Singhal) Page 81 of 99


ALG 8.6
public void printInvSummary(PrintWriter Pwriter)
Note: All class constants are in bold italicized letters.
1. Print a line of asterisks (*) col columns left justified
2. Print Title of summary report left justified in col columns, with fill
character ‘ ‘.
3. Repeat step one once
4. Format and get the string for instance variable cost_of_inv in currency
format for the default Locale.
5. Repeat step four for instance variable lowest_cost
6. Repeat step four for instance variable highest_cost
7. Repeat step four for instance variable ave_cost
8. Set string SD to zero length string.
9. If instance variable std_dev is less than zero then
Set SD = constant string Message
Else repeat step four for std_dev and store resulting string in SD
10. Get the length of constant string Head1 and store in column
11. Get the length of constant string Message and store in column2
12. If column2 is less than the length of string found in step four then
Set column2 equal to the length of string in step four.
13. Print constant string Head1 in width equal to column left justified with fill
character ‘ ‘.
14. Print the string from step four in width column2 right justified with fill
character ‘ ‘ and print line feed after that.
15. Print constant string Head2 in width equal to column left justified with fill
character ‘ ‘.
16. Print the string from step five in width column2 right justified with fill
character ‘ ‘ and print line feed after that.
17. Print constant string Head3 in width equal to column left justified with fill
character ‘ ‘.
18. Print the string from step six in width column2 right justified with fill
character ‘ ‘ and print line feed after that.
19. Print constant string Head4 in width equal to column left justified with fill
character ‘ ‘.
20. Print the string from step seven in width column2 right justified with fill
character ‘ ‘ and print line feed after that.
21. Print constant string Head5 in width equal to column left justified with fill
character ‘ ‘.
22. Print the string SD in width column2 right justified with fill character ‘ ‘ and
print line feed after that.
23. Print constant string Head6 in width equal to column left justified with fill

CS3 Java – Topic 8: Standard IO (Singhal) Page 82 of 99


character ‘ ‘.
24. Print the string form of instance variable num_items in width column2 right
justified with fill character ‘ ‘ and print line feed after that.
25. Repeat step one once.

Listing 8.13A gives the source code for class InventorySummary, which conforms to
above design specifications.
00001 import java.io.*;
00002 import java.text.*;
00007 public class InventorySummary
00008 {
00011 private final int col = 80;
00015 private final boolean right = true;
00019 private final boolean left = false;
00023 private final char fill_char1 = ' ';
00027 private final char fill_char2 = '*';
00031 private final String Head1 = "The total cost of inventory = ";
00035 private final String Head2 = "The lowest cost item = ";
00039 private final String Head3 = "The highest cost item = ";
00043 private final String Head4 = "The average cost of inventory item = ";
00047 private final String Head5 = "The cost standard deviation = ";
00051 private final String Head6 = "Total number of units in inventory = ";
00056 private final String Message = "Not Calculated";
00060 private double cost_of_inv;
00064 private double lowest_cost;
00068 private double highest_cost;
00072 private double ave_cost;
00076 private double std_dev;
00080 private int num_items;
00087 private String Title;
00091 public InventorySummary()
00092 {
00093 Title = "Summary of";
00094 }
00107 public InventorySummary(double ci, double lc, double hc, double ac,
00108 double sd, int ni, String Title1)
00109 {
00110 cost_of_inv = ci;
00111 lowest_cost = lc;
00112 highest_cost = hc;
00113 ave_cost = ac;
00114 std_dev = sd;
00115 num_items = ni;
00116 Title = "Summary of " + Title1;
00117 }

CS3 Java – Topic 8: Standard IO (Singhal) Page 83 of 99


00124 public void printInvSummary(PrintWriter Pwriter)
00125 {
00126 FixedWidthOutPut.printlnW(Pwriter,"*",col,left,fill_char2);
00127 FixedWidthOutPut.printlnW(Pwriter,Title,col,left,fill_char1);
00128 FixedWidthOutPut.printlnW(Pwriter,"*",col,left,fill_char2);
00129 NumberFormat DF = DecimalFormat.getCurrencyInstance();
00130 String CI = DF.format(cost_of_inv);
00131 String LC = DF.format(lowest_cost);
00132 String HC = DF.format(highest_cost);
00133 String AC = DF.format(ave_cost);
00134 String SD = "";
00135 if(std_dev <0.0)
00136 SD = this.Message;
00137 else
00138 SD = DF.format(std_dev);
00139 int column = Head1.length();
00140 int column2 = Message.length();;
00141 if(Message.length()<CI.length())
00142 column2 = CI.length();
00143
00144 FixedWidthOutPut.printW(Pwriter,Head1,column,left,fill_char1);
00145 FixedWidthOutPut.printlnW(Pwriter,CI,column2,right,fill_char1);
00146 FixedWidthOutPut.printW(Pwriter, Head2,column,left, fill_char1);
00147 FixedWidthOutPut.printlnW(Pwriter,LC,column2,right,fill_char1);
00148 FixedWidthOutPut.printW(Pwriter, Head3,column,left, fill_char1);
00149 FixedWidthOutPut.printlnW(Pwriter,HC,column2,right,fill_char1);
00150 FixedWidthOutPut.printW(Pwriter, Head4,column,left, fill_char1);
00151 FixedWidthOutPut.printlnW(Pwriter,AC,column2,right,fill_char1);
00152 FixedWidthOutPut.printW(Pwriter, Head5,column,left, fill_char1);
00153 FixedWidthOutPut.printlnW(Pwriter,SD,column2,right,fill_char1);
00154 FixedWidthOutPut.printW(Pwriter, Head6,column,left, fill_char1);
00155 FixedWidthOutPut.printlnW(Pwriter,
00156 new Integer(num_items).toString(),column2,right,fill_char1);
00157 FixedWidthOutPut.printlnW(Pwriter,"*",col,left,fill_char2);
00158 }
00159 }// Listing 8.13A

Design of class InventoryTable


The class InventoryTable is responsible for printing the top portion of the Figure
8.28 as well as printing the Inventory summary, which is the lower portion of the
same figure. This brings us to an important design concept that binds user-defined
classes into a relationship called “composition”. When a class is a member of
another class, then two classes are related by a composition relationship. In
developing class InventoryTable we use class InventorySummary as one of its data
member. Therefore the structure of an object of class InventoryTable would look
similar to Figure 8.29.

CS3 Java – Topic 8: Standard IO (Singhal) Page 84 of 99


2000
InventoryTable

private:
InventorySummary
InventorySummary Summary 2000
private:
//Other data members Data members

Constructors
Constructors

printInvSummary
Member methods

FIG. 8.29: Composition relationship between classes InventoryTable &


InventorySummary

Let us review the responsibilities of class InventoryTable.


1. It prints the inventory report header.
2. It prints the inventory table
3. It prints the inventory summary.
The last task is simplified by including the class InventorySummary as a data
member of class InventoryTable, thus allowing the member object to fulfill the third
responsibility by itself. Since the inventory table has certain number of columns, it is
imperative that we have an integer data member, which defines the number of
columns. The column headings may be stored as constant strings. The Design of
instance variable and constant members for class InventoryTable is given by Table
8.17.
Summary of instance variable For class InventoryTable
private String Title
Title for the overall report

private InventorySummary Summary


Stores the Summary of overall inventory report.

private int column


Stores the number of Columns in the report

CS3 Java – Topic 8: Standard IO (Singhal) Page 85 of 99


Summary of instance constants For class InventoryTable
private final int col 80
private final char fill_char1 ‘‘
private final char fill_char2 ‘*’
private final char fill_char3 ‘-‘
private final int gap 5
private final String Item "ITEM"
private final boolean left false
private final String Num_Units "NUMBER OF UNITS"
private final boolean right true
private final String Tot_Val "TOTAL VALUE($)"
private final String Unit_Cost "UNIT COST($)"
Table 8.17

The class InventoryTable has three instance variables: Title, Summary and column.
Title is a String data type, which forms the overall title for the report. Summary is
the InventorySummary object, which when filled and printed fulfills the
responsibility for printing the summary part of the inventory report. Generally
most inventory tables have fixed number of columns, but here for the sake of
flexibility, we use an integer variable for number of columns.

The class InventoryTable has 11 instance constants, of which six are unique to this
class, while other five have the same values and names as they do in Class
InventorySummary. In an upgraded design we could cut down on this duplication,
by designing a separate class, to just store all the constants. The constant strings
simply indicate the headings of columns in the inventory table (Figure 8.28).

Design of Constructors and methods


The “intelligence” imparted to class InventoryTable is embedded in member
methods, whose names, responsibilities, and call relationships are shown by Figure
8.30. All methods in Figure 8.30 are members of InventoryTable, except the
printInvSummary, which is member of class InventorySummary, and whose
algorithm is described in ALG 8.6.

CS3 Java – Topic 8: Standard IO (Singhal) Page 86 of 99


FIG. 8.30
Client of class InventoryTable would create objects of InventoryTable,
BufferedReader, and PrintWriter; among which the later two are bonded to input
and output files respectively. Then client would simply call the printReport method
via the InventoryTable object created by them and pass the BufferedReader and
PrintWriter objects to it. That call to printReport method would trigger a chain of
method calls shown in Figure 8.30 to read data from input file and write the
inventory report to output file in the format shown in Figure 8.28. Use of the static
member methods of class FixedWidthOutPut does the column formatting.

Table 8.18 provides summary of constructor and methods for class InventoryTable.

CS3 Java – Topic 8: Standard IO (Singhal) Page 87 of 99


Summary of Constructors For Class InventoryTable
public InventoryTable() throws IOException
Argument less constructor
Summary of Methods For Class InventoryTable
private void printTableHeader (PrintWriter Pwriter, int col_width)
throws IOException
Prints the header of inventory table.

Parameters:
Pwriter - is the object passed to print the header of the inventory table to either a file
or console.
col_width - is the width in number of columns in which the table header is to be
printed.

private void printReportHeader(PrintWriter Pwriter) throws IOException


Prints the header of inventory report.

Parameters:
Pwriter - is the object passed to print the header of the inventory report to either a
file or console.

public void printReport(PrintWriter Pwriter, BufferedReader Buff_Freader)


throws IOException
Reads the data from input file and prints entire inventory report to an output file.

Parameters:
Pwriter - is object bonded to an output file or console.
Buff_Freader - is an object bonded to an input file.

private void printInvTable(PrintWriter Pwriter,


BufferedReader Buff_Freader2) throws IOException
Prints the Inventory table column headings and inventory data in it.

Parameters:
Pwriter - is object bonded to an output file or console.
Buff_Freader2 - is an object bonded to an input file.

private String getDataString(BufferedReader Buff_Freader2)


throws IOException
Gets one line of data from an input file and returns that as a string to caller method.

Parameters:
Buff_Freader2 - is an object bonded to an input file.

CS3 Java – Topic 8: Standard IO (Singhal) Page 88 of 99


private void printGap(PrintWriter PWriter, int val)
Prints val number of ' ' characters to a file or console.
Parameters:
PWriter - is object bonded to an output file or console.
Table 8.18
Notice that in this class all but one of member method is declared private. This is
done to modularize the class as much as possible. Only method available to the
client of class InventoryTable is the public method printReport.

Algorithms
Most of the work in class InventoryTable is done by the private method
printInvTable, whose algorithm is described in ALG 8.7. The method has the
following purposes:
1. Print header for the inventory table.
2. Read input data file to get raw data.
3. Print inventory table
4. Get the necessary data for the instance data member Summary and fill it.

private void printInvTable(PrintWriter Pwriter, BufferedReader Buff_Freader2)


All class instance constants are shown italicized and highlighted.

1. Declare and initialize the variable for cost of inventory cost_inv


2. Print the line of header of inventory table as a line of character ‘-‘ for
column width equal to col
3. Set integer variable col_width equal to the value calculated from the
following formula: col_width = (col - gap*(column-1))/column; The column
is the class instance variable, which is set equal to the number of columns the
table should have. In most cases column = 4.
4. Call method printTableHeader to print the column headings passing to it the
parameter col_width.
5. Repeat step two once.
6. Get the StringTokenizer object St by calling the method getDataString to get
the entire input file read and stored in St.
7. Get NumberFormat object DF, to format a currency number as per default
Locale.
8. Declare and initialize the following local variables lowest for storing the
price of lowest costing item, highest for storing the price of most expensive
item, count for counting the total number of units in inventory, item_type to
store the number of types of items in the inventory.
9. while object St (from step six) has more tokens
Print the first token left justified in column width col_width with fill character
fill_char1
Print the gap by calling method printGap passing the parameter gap to it.
Get next token and parse it as an integer into local variable units.

CS3 Java – Topic 8: Standard IO (Singhal) Page 89 of 99


Set count equal to count plus units.
Set local variable width1 equal to half of the length of string Num_Units plus
two.
Print the units (from step 9.3) in string form in column width width1, right
justified with fill character fill_char1
Repeat step 9.2 once with the second parameter to the method printGap equal to
gap+(col_width-width1)
Get the next token and parse it as a double value into local variable cost
If highest is less than cost, then
9.91 set highest equal to cost
Set lowest equal to cost.
If lowest is larger than cost then
9.111 Set lowest equal to cost
Format the cost into a currency string DBL by using the NumberFormat object
DF created in step seven.
Set variable width1 equal to length of string Unit_Cost/2+2
Repeat step 9.6 once with string DBL as the string to be printed.
Repeat step 9.7 once
Set variable part_total equal to product of units and cost
Repeat step 9.12 once to format part_total into a currency string and store result
into DBL.
Set width1 equal to length of string Tot_Val( )/2 + 2
Repeat step 9.14 once
Set cost_inv equal to part_total plus cost_inv
Print a blank line feed
Pre-increment item_type by one.
10. Repeat step two once
11. Set the class instance variable Summary equal to the value created by the call
to sex argument constructor for class InventorySummary with the following
argument list (in this order): cost_inv, lowest, highest, cost_inv/count,
-1, count, Title (Recall the Title is a class instant variable).

Listing 8.13B shows the source code for class InventoryTable.


00001 import java.io.*;
00002 import java.util.*;
00003 import java.text.*;
00009 public class InventoryTable
00010 {
00013 private final int col = 80;
00017 private final boolean right = true;
00021 private final boolean left = false;
00025 private final char fill_char1 = ' ';
00029 private final char fill_char2 = '*';
00033 private final char fill_char3 = '-';

CS3 Java – Topic 8: Standard IO (Singhal) Page 90 of 99


00037 private final int gap = 5;
00041 private final String Item = "ITEM";
00045 private final String Num_Units = "NUMBER OF UNITS";
00049 private final String Unit_Cost = "UNIT COST($)";
00053 private final String Tot_Val = "TOTAL VALUE($)";
00057 private String Title = "";
00061 private InventorySummary Summary = new InventorySummary();
00065 private int column;
00069 public InventoryTable( ) throws IOException
00070 {
00071 column = 4;
System.out.println("Enter the name of company whose inventory report is needed.");
00073 Title =IOManagement.getKeyboardReader().readLine().trim();
00074 }
00082 private void printTableHeader(PrintWriter Pwriter,int col_width)
00083 throws IOException
00084 {
00085 FixedWidthOutPut.printW(Pwriter,Item,col_width,left,fill_char1);
00086 printGap(Pwriter,gap);
00087
FixedWidthOutPut.printW(Pwriter,Num_Units,col_width,left,fill_char1);
00088 printGap(Pwriter,gap);
00089
FixedWidthOutPut.printW(Pwriter,Unit_Cost,col_width,left,fill_char1);
00090 printGap(Pwriter,gap);
00091
FixedWidthOutPut.printW(Pwriter,Tot_Val,col_width,left,fill_char1);
00092 Pwriter.println();
00093 }
00099 private void printReportHeader(PrintWriter Pwriter) throws
IOException
00100 {
00101 Title = "Inventory Report For " + Title;
00102 FixedWidthOutPut.printCenteredln(Pwriter, Title, col, fill_char1);
00103 Pwriter.println();
00104 }
00111 public void printReport(PrintWriter Pwriter,BufferedReader
Buff_Freader)
00112 throws IOException
00113 {
00114 printReportHeader(Pwriter);
00115 printInvTable(Pwriter,Buff_Freader);
00116 Pwriter.println();
00117 Pwriter.println();
00118 Summary.printInvSummary(Pwriter);
00119 }

CS3 Java – Topic 8: Standard IO (Singhal) Page 91 of 99


00120
00126 private void printInvTable(PrintWriter Pwriter,BufferedReader
Buff_Freader2)
00127 throws IOException
00128 {
00129 double cost_inv = 0.0;
00130 FixedWidthOutPut.printlnW(Pwriter,"-",col,left,fill_char3);
00131
00132 //print columns. column width = ((col-gap(column -1))/column
00133 int col_width = (col - gap*(column-1))/column;
00134
00135 printTableHeader(Pwriter,col_width);
00136
00137 FixedWidthOutPut.printlnW(Pwriter,"-",col,left,fill_char3);
00138 //Read entire file into one string and create Tokenizer object
00139 StringTokenizer St = new
StringTokenizer(getDataString(Buff_Freader2));
00140 NumberFormat DF = DecimalFormat.getCurrencyInstance();
00141
00142 double lowest = 0.0;
00143 double highest = 0.0;
00144 int count = 0;
00145 int item_type = 0;
00146 while(St.hasMoreTokens())
00147 {
00148
FixedWidthOutPut.printW(Pwriter,St.nextToken(),col_width,left,fill_char1);
00149 printGap(Pwriter,gap);
00150 int units = Integer.parseInt(St.nextToken());
00151 count = count + units;
00152 int width1 =Num_Units.length()/2+2;
00153 FixedWidthOutPut.printW(Pwriter,new
Integer(units).toString(),
00154 width1,right,fill_char1);
00155 printGap(Pwriter,gap+(col_width-width1));
00156 double cost = Double.parseDouble(St.nextToken());
00157 if(highest<cost)
00158 highest = cost;
00159
00160 lowest = cost;
00161 if(lowest>cost)
00162 lowest = cost;
00163 String DBL = DF.format(cost);
00164 width1 = Unit_Cost.length()/2+2;
00165
FixedWidthOutPut.printW(Pwriter,DBL,width1,right,fill_char1);

CS3 Java – Topic 8: Standard IO (Singhal) Page 92 of 99


00166 printGap(Pwriter,gap+(col_width-width1));
00167 double part_total = units*cost;
00168 DBL = DF.format(part_total);
00169 width1 = Tot_Val.length()/2 + 2;
00170
FixedWidthOutPut.printW(Pwriter,DBL,width1,right,fill_char1);
00171 cost_inv = cost_inv+part_total;
00172 Pwriter.println();
00173 ++item_type;
00174 }
00175
00176 FixedWidthOutPut.printlnW(Pwriter,"-",col,left,fill_char3);
00177 Summary = new InventorySummary(cost_inv,lowest,
00178 highest,cost_inv/count,-1,count,Title);
00179 }
00185 private String getDataString(BufferedReader Buff_Freader2)throws
IOException
00186 {
00187 String Data = "";
00188 String Data2 = "";
00189
00190 while((Data = Buff_Freader2.readLine()) != null)
00191 Data2+=Data;
00192
00193 return Data2;
00194 }
00199 private void printGap(PrintWriter PWriter, int val)
00200 {
00201 for(int index=0; index<val; index++)
00202 PWriter.print(fill_char1);
00203 PWriter.flush();
00204
00205 }
00222 }
//Listing 8.13B

Creating the Inventory Report


Creating an inventory report similar to format shown in Figure 8.28 becomes
somewhat easier by using the classes, FixedWidthOutPut, IOManagement,
InventorySummary, InventoryTable, all developed in this chapter. Listing 8.13C
shows a simple client program to create an inventory report.
00001 import java.io.*;
00002
00003 public class DriverInventory
00004 {

CS3 Java – Topic 8: Standard IO (Singhal) Page 93 of 99


00005 public static void main(String[] args) throws IOException
00006 {
00007 InventoryTable Table = new InventoryTable();
00008 BufferedReader Read = IOManagement.getFileReader();
00009 PrintWriter PW = IOManagement.getFileWriter();
00010
00011 Table.printReport(PW,Read);
00012 Read.close();
00013 PW.close();
00014 System.out.println("Processed data from input file and wrote to "
00015 + " output file");
00016 System.exit(0);
00017 }
00018 }
//Listing 8.13C

The client program (Listing 8.13C) creates an object Table of type InventoryTable
(L8.13C#7). It uses IOManagement class methods getFileReader and getFileWriter
to get the user input for the input and output file names (L8.13C#8-9). The Table
object calls member method printReport (L8.13C#11) and passes to it the
BufferedReader and PrintWriter objects created earlier. The printReport method
triggers the chain of method calls depicted in Figure 8.30 and prints the inventory
report to the user specified output file. Figure 8.31A shows the console output from
the Listing 8.13C, whereas Figures 8.31B and 8.31C show the input and output files
respectively.

FIG 8.31A

CS3 Java – Topic 8: Standard IO (Singhal) Page 94 of 99


FIG 8.31B

FIG 8.31C

Notice the following properties of the inventory report print out.


1. All numbers are right justified.
2. All strings are left justified
3. Decimal points of all currency numbers are aligned vertically in same
column.
4. The decimal point lies in the middle of each column heading
5. Heading of the report is centered.
6. All currency numbers are formatted as per half even rounding criterion.
Since this criterion is applied after the calculations yield a final number, it is

CS3 Java – Topic 8: Standard IO (Singhal) Page 95 of 99


expected to produce results accepted by commonly agreed accounting
principles.

Questions (Multiple choice questions may have more than one correct answer)

1. Which of the followings can be used for standard input in a java program:
A] keyboard
B] ASCII input file
C] Mouse
D] All of above
2. Which of the followings can be used for standard output in a java program:
A] Console
B] ASCII output file
C] Computer Speakers
D] All of above
3. Which Java package is needed to be imported in order to write to a file?
4. Which of the BufferedReader class constructor allow one to specify a size for the
input buffer?
5. Which of the member method from BufferedReader class reads the input
character by character?
6. Which of the member method from BufferedReader class reads input line by
line?
7. Write the headers for the following member methods from BufferedReader
class: read, readLine, close. Which of these method(s) is/are overloaded?
8. (T/F) The BufferedReader class has an argument-less constructor.
9. When reading from the keyboard what is the function of InputStreamReader
object that is passed as an argument to the BufferedReader constructor?
A] It converts characters flowing from keyboard into bytes
B] It converts bytes flowing from keyboard into characters
C] It buffers the input
D] It corrects any user errors during data input
E] It acts as a pipe between objects InputStream and BufferedReader.
10. The object InputStream used during reading from keyboard is:
A] System.in B] System.out C] Of type PrintStream
D] Of Type PrintWriter E] Of type InputStreamReader
11. What is returned by read method when the end of file is reached?
A] null B] ‘\n’ C] 32 d] –1 E] 65
12. What is returned by readLine method when the end of file is reached?
A] null B] “\n” C] 32 d] –1 E] 65
13. (T/F) For character-by-character non-buffered reading from an ASCII file,
one can simply use a FileReader object bonded to that ASCII file.
14. What is true about FileReader class?
A] It does not have a method with name read
B] It does not have a method named readLine
C] It does not have a constructor that can take the input file name as
a String

CS3 Java – Topic 8: Standard IO (Singhal) Page 96 of 99


D] It only has one constructor
E] With out wrapping an object of FileReader, by itself it cannot write
to an ASCII file.
F] It does not have a method with name close.
15. (T/F) BufferedReader class has overloaded constructor.
16. (T/F)In PrintWriter class calling method println will always flush the buffer.
17. (T/F) In PrintWriter class call to method print will never flush the buffer.
18. Which method from PrintWriter class must be called to flush the buffer?
19. Which constructor from class PrintWriter allows automatic buffer flushing
when method println is used?
20. Which constructor in BufferedWriter class allows you to choose a user-
defined buffer size?
21. Which constructor from BufferedReader class allows you to choose a user
defined buffer size.
22. (T/F) In making a call to print in System.out.print ( ), the buffer is not
flushed automatically.

Appendix
00001 import java.io.*;
00002
00003 public class KeyBoardInputUsingIOException
00004 {
00005 public static void main(String [] args)
00006 {
00007 InputStream Key_Stroke = System.in;
00008 InputStreamReader Isr = new InputStreamReader(Key_Stroke);
00009 BufferedReader Kb_Input = new BufferedReader(Isr);
00010 System.out.print ("Please type a long string and press enter: ");
00011 System.out.flush( );

CS3 Java – Topic 8: Standard IO (Singhal) Page 97 of 99


00012 String Input = "";
00013
00014 try
00015 {
00016 Input = Kb_Input.readLine( );
00017 System.out.println ("You have typed : "+ Input);
00018 System.out.flush( );
00019 }
00020 catch(IOException ex)
00021 {
00022 System.out.println("From First IOException block");
00023 ex.printStackTrace( );
00024 System.out.flush( );
00025 }
00026 finally
00027 {
00028 System.in.close( );
00029 }
00030
00031 System.out.println ("Please type another string and press enter: ");
00032 System.out.flush( );
00033 try
00034 {
00035 int ch = 0;
00036 int counter = 0;
00037
00038 while((ch = Kb_Input.read( )) != (int)'\n')
00039 {
00040 if(counter++ == 0)
00041 System.out.println ("You have typed : ");
00042 System.out.print((char)ch);
00043 }
00044 System.out.flush( );
00045 }
00046 catch(IOException ex)
00047 {
00048 System.out.println("From Second IOException block");
00049 ex.printStackTrace( );
00050 System.out.flush( );
00051 }
00052 finally
00053 {
00054 System.in.close( );
00055 System.exit(0);
00056 }
00057 }

CS3 Java – Topic 8: Standard IO (Singhal) Page 98 of 99


00058 } //Listing A8.1

http://www.horstmann.com/

CS3 Java – Topic 8: Standard IO (Singhal) Page 99 of 99


CS3 – Topic 9
Author: Satish Singhal, Ph. D.
Version – 1.0
One Dimensional Array

Some of our analyses in early chapters showed that as the computer program
accepts data from the user (human or other machines), they need to be stored, and
programmer needs to specify program variables to hold the user data. Naming the
individual memory locations for data persistence during the life of the program
works when the amounts of user data are small. However, if user had large amount
of data that needed processing, then method of naming individual memory locations
to store data becomes tedious. We discuss with some examples.

Example of Large Amount of Data To Be Processed


One example of large amount of data to be processed is if we need to write a
program to collect student scores in the final examination of a large class and plot a
histogram of such scores and do some sort of frequency and sampling analysis on
them. Such data processing requires that all score, be it 100 students, or 300, be
internally stored for the life of the program. It would be awfully tiring for the
programmers to type again and again the names of 300 variables as well as
processing such huge amounts of data. Java allows a construct to help programmer
to store and process large amounts of data. This construct is called declaring an
array of data. As the name implies, the data structure called array allows
programmer to define essentially one name for the group of data to be stored and
processed and the memory would be allocated for them in an array – meaning one
after another. A group of data whose data type are homogeneous (all data having
the same type) can be stored in an array, whose length will be equal to the
maximum possible number of data items.

We further enlighten the concept of arrays by taking two examples; let us say
storing the blood pressure data on patients in a Doctor’s office by declaring one
variable for each patient’s blood pressure. This method is shown in Figure 9.1
below.

Lecture10_3Var.ppt

CS3 Java – Topic 9: Arrays (Singhal) Page 1 of 134


Memory address

5000 7000
Variable
names

FIG. 9.1

Obviously if it was a matter of just storing the blood pressure of three patients, then
construct shown in Figure 9.1 will suffice, but what if 1000 patients blood pressure
data were required to be stored? In that case, the Java data structure called arrays
is very useful and a graphical representation of it to store blood pressure of large
number of patients is shown in Figure 9.2 below. We also show the process in the
power point presentation below.
Error! Not a valid link.

CS3 Java – Topic 9: Arrays (Singhal) Page 2 of 134


FIG. 9.2

As seen in Figure 9.2, Java allows us to declare a large number of variables, whose
data type is same, by a simple declaration like

int [ ] bp = new int[1000];


The above statement would create 1000 int variables, which can be used to store
integer data. The names of these variables will be tied to their subscript number.
For example first data in this array group be would called bp[0], second bp[1], third
bp[2], and so on. The value in the square bracket is called an array index or
subscript, which in Java always starts with the 0 (unlike Fortran, where it starts at
1). Thus, the array variable bp would have indices from 0 to 999. Upon declaration,
the values stored in all array cells would be the fundamental initializer value for its
data type (for example zero for an int & null for reference types1). The array
elements are located in the heap memory contiguously. The memory address of the
first element is called the base address. In the Figure 9.2, the base address is
assumed 5000. Since int data type is four byte in size the second array element has

1
See Table 4.2 in chapter four for other types.

CS3 Java – Topic 9: Arrays (Singhal) Page 3 of 134


an address of 5004, the third 5008 and so on. Notice that the index of an array
element is always one less than its number in the order.

Largest index of in array of size N will be (N-1)!

An array like the one in Figure 9.2 is called a one-dimensional array, whose
characteristics are summarized in the Figure 9.3.

ArrayName [index]

FIG. 9.3
Figure 9.4 gives syntax for single line general declaration of arrays in Java as
follows.
DataType [ ] Array_Name = new DataType [IntExpression];
OR
DataType Array_Name [ ] = new DataType [IntExpression];

FIG. 9.4

Note that in array declaration the length expression in square bracket can be any
integer type expression except long data type. The array length expression must
evaluate to a specific positive value at run time. For example all array declarations
below are legal.

CS3 Java – Topic 9: Arrays (Singhal) Page 4 of 134


int [ ] my_int = new int[100];
int [ ] my_int = new int [‘A’];
int [ ] your_int = new int [“Hello Dad”.charAt(0)*2];
int [ ] their_int = new int [“Hi Mom”.length( )];
In second case the array length will be 65 since compiler will take the ASCII value
of the character A, which is 65.In third the method charAt will return a character
‘H’, whose ASCII value is 72, therefore your_int array would have a length of 144.

Q. What would be the length of array their_int?


The meaning of IntExpression in the array declaration syntax in Figure 9.4 is that
the maximum number of elements specified in the array declaration must compute
to a concrete positive number at run time. Note that the IntExpression should not
evaluate to negative. Attempt to specify an array of negative length is not a compile
error, but the program will crash when it is run. Figure 9.4 shows two alternate
ways to declare Java arrays, and Java programmers have accepted the first form
almost universally. The Figure 9.5 summarizes the rules related to array length.

• Array length expression must evaluate to a concrete


positive integer at run time.
• It cannot be a long data type.
• The array length expression should not evaluate to a
negative value. Zero length array will have no
elements in it
• The parameters
Question: What is wrong
in thewith this
array manner
length of assigning
expressions can be
named or literal constants, initialized variables, or
values returned from method calls.
FIG. 9.5

Table 9.1 shows few examples of array declarations that would cause compile error.
Array declaration which would cause Reason for compile error
compile error
DataType [ ] Arr = new DataType [ 9.5 ]; Array length cannot be floating point
type expression.
DataType [ ] Arr = new DataType [ 10L ]; Array length cannot be long type
expression.
DataType [ ] Arr = new DataType [ true ]; Array length cannot be a boolean
value.

CS3 Java – Topic 9: Arrays (Singhal) Page 5 of 134


DataType [ ] Arr = new DataType [ null ]; Array length cannot be a null, as null
has no numeric value.
Table 9.1

Some of you may be surprised to note that array length cannot be a long type
expression, even though long data is an integer type. You may recall that the
maximum allowed value for long type variable is 9.22…E18. You would also recall
that byte data type takes one byte for each of its variable (the smallest data type in
Java). Imagine that if long data type were allowed to be the length expression for an
array, then under some accidental programming condition, one may end up
declaring an array, which, even for byte data type, would require 9.22…E18 bytes
of memory, which is equivalent to 9.22 exabytes. Needless to say that such memory
requirement will crash the program instantly.

Array of Java Objects


When the java object array is created then all of its members are the object
references that are set to null values. Example is shown in Figure 9.6

FIG. 9.6
But if we make the following assignments,

CS3 Java – Topic 9: Arrays (Singhal) Page 6 of 134


groceryItems [0] = “cat food”;
groceryItems [1] = “rice”;
groceryItems [8] = “spinach”;
groceryItems [9] = “butter”;

FIG. 9.7
then the state of array changes to the one in Figure 9.8

Unassigned
components
are still null.

FIG. 9.8

A Common Mistake
A common mistake in using Java arrays is to declare an array of objects, but then
forget to make a constructor calls for the array components to allocate memory for
them, and then try to use them in some form. Because in absence of constructor call,
only a null object is stored, the attempt to use a null object causes Java Virtual
Machine to throw a null pointer exception. The compiler will not save you, because
having a null stored in an object reference is not a compile error. Listing 9.1 below
shows the error, its results and Listing 9.2 shows the solution.

CS3 Java – Topic 9: Arrays (Singhal) Page 7 of 134


Attempt to use an un-constructed null
object.

Program will compile, but will crash at run time,


throwing NullPointerException!

>javac CommonMistake_Array.java

>java CommonMistake_Array
Exception in thread "main" java.lang.NullPointerException
at CommonMistake_Array.main(CommonMistake_Array.java:11)

Listing 9.1

In 9.1, the program will compile, but it will crash when executed because the
reference Arr[0] stores a null as there was no constructor call made to allocate
memory on the heap. Thus when we try to set the field of null object Arr[0] to value
five the program crashes. Solution to this problem is shown in Listing 9.2.

CS3 Java – Topic 9: Arrays (Singhal) Page 8 of 134


Constructor call
is made and
memory is
allocated on
heap.

>javac CommonMistake_Array.java
Value 5 as
>java CommonMistake_Array expected is
5 printed.

Listing 9.2
Of course the ideal solution is to make a constructor call soon after the array is
declared (Listing 9.3).

CS3 Java – Topic 9: Arrays (Singhal) Page 9 of 134


ALL ARRAY
COMPONENTS
CONSTRUCTED
NOW!

Listing 9.3

Array operator [ ] is a Reference Type


Figure 9.9 shows the Java data types broken down into primitive and reference
types.

FIG. 9.9

Three reference types in Java are array operator [ ], interface, and class. We have
already discussed the class reference types. It is important to recall that all reference
types only hold the address of no-name objects on the heap. Figure 9.10 shows the

CS3 Java – Topic 9: Arrays (Singhal) Page 10 of 134


structure of stack and heap memories for the Java declarations made in lines above
it.
///////////////////////////////////////////////////////////////////////////////////////////////////////////
int val = 6;
int [ ] num = new int [5];
String Name = “John”;
double data = 5.005;
String City = null;

FIG. 9.10
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Notice that array reference num only stores the address of the first element in the
array located on heap. In that sense the array name is no different than the String
reference Name, which also stores the address of object with “John” in it.

Alternate ways for array declarations


Arrays can be declared using two-line declaration methods such as:

String [ ] Str_Arr1; No memory assigned here. Str_Arr1


stores undefined value.

Str_Arr1 = new String [10]; Array created on heap, Str_Arr1


stores the address of the first array
cell.

CS3 Java – Topic 9: Arrays (Singhal) Page 11 of 134


String [ ] Str_Arr2 = null; No memory assigned here. Str_Arr2
stores null.

Str_Arr2 = new String [12];

When the array declaration has no value on right hand side, then the array
reference contains an undefined value, which must be initialized to a definable value
prior to its use. Multiple arrays of same data types can be declared on the single
line. For example the statement below declares five different arrays of int data type.

int [ ] foo_one, foo_two, foo_three, foo_four, foo_five;

However, the following will not declare five arrays

int foo_one [ ], foo_two, foo_three [ ], foo_four[ ], foo_five;


as in above declaration, only foo_one, foo_three and foo_four are arrays, and rest
are simple int declarations. Using comma operator, it is also possible to initialize all
or some of the array references in a single line. For example one could do the
following type of initializations.

int [ ] foo_one = new int [5], foo_two = new int [10], foo_three;
foo_three = new int [40];

The first statement creates and initializes the array references foo_one and foo_two,
whereas the second statement initializes foo_three.

Providing an initialization list and implicit array sizing


Java allows one to define an array and provide the values for its elements in one
declaration line, using the following syntax.

DataType [ ] Arr = { value1, value2, value3, value4};

For an int type array the above syntax could boil down to the following statement
type:

int [ ] Arr = { -4, 2, 5, Math.abs (-99)};

Figure 9.11 shows the schematic picture of int array Arr in the program heap
memory.

CS3 Java – Topic 9: Arrays (Singhal) Page 12 of 134


FIG. 9.11
The JVM in this case counts the number of data members in the initialization list on
right hand side, and assigns the memory spaces for that many variables
contiguously as well as fills the spaces with values provided. Since in such
declaration, the size is not provided, it is also called implicit array sizing, as JVM
implicitly deduces the size of array from the number of values provided in the
initialization list. The initialization list may contain values returned by method calls
as well. For example the following declaration is also legal.

int [ ] Arr = { -“Hello Mom and Dad”.length ( ), 2, 5, 99};

There is an alternate form available for implicit array sizing, which is more
appropriate when an un-named array is to be passed to a method as an actual
argument. This alternate declaration has the following type of syntax.
No length is specified when followed by initialization list.

int [ ] Arr2 = new int [ ] { 8, -22, “Yo Mom”.charAt (1), 31};

Question: What will be the value stored in the third element of array
Arr2 in above declaration?

The alternate syntax for implicit array sizing declarations given below are legal but
these forms are not encouraged for usage.

int Arr3[ ] = {1,2,3,4};


int Arr4 [ ]= new int [ ] { 7, -2, Math.min (8, 12), 1};

Question: What will be the value stored in the third element of array
Arr4 in above declaration?

Due to efficiency concerns one must use the implicit array sizing technique only
when the number of array elements involved is small. The reason for this would be
discussed after we have discussed the read and write access to array elements in the
next section.

CS3 Java – Topic 9: Arrays (Singhal) Page 13 of 134


Read and write access to array elements
Arrays have random read and write access. What that means is that each array
element is available to use as if it is a stand alone variable to read its value or write a
new value in it. We show this mechanism by the following power point presentation.

Microsoft PowerPoint
Presentation

Figure 9.12A shows the initial state of an int array of five elements.

FIG. 9.12A
Figure 9.12B shows the state of the array, when a value of –5 is stored in the third
array cell.

CS3 Java – Topic 9: Arrays (Singhal) Page 14 of 134


FIG. 9.12B
Figure 9.12B also shows the access mechanism for any member of the array. The
array name followed by the square bracket with an index specified in acts like a
stand-alone variable. Thus the individual elements of an array have same write
access, as do the stand-alone Java variables. Figure 9.12C shows the state of the
array, when all of its elements are filled with the preceding program statements.

FIG. 9.12C

CS3 Java – Topic 9: Arrays (Singhal) Page 15 of 134


One obvious conclusion from the Figure 9.12 is that array elements have
random write access!

Since stand-alone variables have read access, it is true of array elements as well
(Figure 9.13A).

FIG. 9.13A
An array of five elements is created and populated in Figure 9.13A. The second code
line prints the value stored in the second array element, which is eight. Figure 9.13B
shows the console output, when statements to print the contents of randomly chosen
array cells are executed.

FIG. 9.13B

CS3 Java – Topic 9: Arrays (Singhal) Page 16 of 134


The conclusion from Figure 9.13 is that the array cells have random read access.
Therefore one can say that in Java the array elements have random read
and write access.

Now we discuss as to why for large arrays the implicit array sizing or direct array
assignment must be avoided. Take for example the declaration:

int [ ] arr = { 5, -8, 11, 22, 89};

Compiler, in order to make above assignment would need to break down the above
code as follows and create its byte code.

int [ ] arr = new int [5];


arr [0] = 5;
arr [1] = -8;
arr [2] = 11;
arr [3] = 22;
arr [4] = 89;

Not only this, but the JVM will have to interpret the above byte code one line at a
time. Needless to say that for large direct assignment arrays, whole process would
be very slow. Therefore it is best to use direct assignment only for small size arrays.

Data and method members for Java array reference types


All reference types have some member methods given to them by Java by default.
This will become clearer when we discuss the topic of inheritance in next chapter.
Java array reference type, in addition to methods, by default carries a public length
member with it, which stores the length of the array. Listing 9.4 shows the use of
length data member of Java array reference Type.
public class LengthDemo
{
public static void main (String [] args)
{
int [ ] arr = new int [ 22 ];
System.out.println (arr.length);
}
}//Listing 9.4

The listing 9.4 will print 22, the length of array arr. Notice the syntax to access the
length of a Java array:
length data member
Array name arr.length storing the array length

CS3 Java – Topic 9: Arrays (Singhal) Page 17 of 134


The array name dotted with data member length gives access to the length of an
array, which is an int parameter. It is clear that the length data member is a
publicly accessible; therefore one can access it by using the familiar dot operator.
Conclusion: In Java arrays carry their length in the publicly accessible
member parameter called length.

Cloning (copying) of Java arrays


Among others, Java also provides a method for array reference types, which allows
client to make a copy of the given array. The process of copying is more commonly
referred to as “cloning”. Listing 9.5 shows a simple procedure for cloning a given
Java array using the clone method provided as a member of array reference type.
00001 import java.io.*;
00002 public class CloningArray
00003 {
00004 private static PrintStream Console = System.out;
00005 public static void main(String[] args)
00006 {
00007 int [ ] int_arr = {(int)(10*Math.random()), (int)(10*Math.random()),
00008
(int)(10*Math.random()),(int)(10*Math.random()), (int)(10*Math.random())};
00009 Console.println("Printing the original array.");
00010
00011 for(int index = 0; index<int_arr.length; index++)
00012 Console.print(int_arr[index] + " ");
00013 Console.println();
00014
00015 Console.println("Proceeding to clone the above array.");
00016 int [ ] clone_arr = (int [ ])int_arr.clone( );
00017 Console.println("Printing the cloned array.");
00018
00019 for(int index = 0; index<clone_arr.length; index++)
00020 Console.print(clone_arr[index] + " ");
00021 Console.println( );
00022
00023 }
00024 }//Listing 9.5
Lines 7 & 8 create int_arr; an array of randomly generated integers, of size five.
Lines 11& 12 print the original array. Line 16 clones the int_arr by calling its
member method clone using the following syntax.
public member
Array object int_arr.clone( ) method clone.
int_arr

CS3 Java – Topic 9: Arrays (Singhal) Page 18 of 134


Remembering the messenger-receiver relationship, in this method call, the
messenger clone calls its receiver int_arr and asks it to return a clone of itself. The
object int_arr obliges. However the reference returned by the call int_arr.clone ( )
does not have an identity of int [ ]. Rather it is of type java.lang.Object, which is the
Java class from which all other Java reference types derive2. Therefore the
reference returned by method clone must be cast into an int [ ] type. Thus the cast
operator (int [ ] ) in Line 16 performs proper casting before the returned array
reference can be copied to a new array reference clone_arr. Figure 9.14 provides
further explanation of process of array cloning.
int [ ] clone_arr = (int [ ])int_arr.clone( );

Clones the array int_arr and


returns a reference to it as a
Casts the reference reference of type
Must be same types! java.lang.Object to java.lang.Object
int array as int [ ].

FIG. 9.14
In above Figure, on the right hand side, first the array int_arr calls its member
method clone to clone itself. However, the value returned by clone method is not
type int [ ]. Rather it is of type java.lang.Object, which is a Java class. Therefore the
cast operator (int [ ] ) is needed to be applied on the return value before it can be
copied to the clone_arr, which is of type int [ ]. Lines 19-20 print the cloned array.
Figure 9.15 shows the typical output from Listing 9.5.

FIG. 9.15
Figure 9.16 shows the schematic structure of object referred to by reference Arr and
created by the following program statement.

int [ ] Arr = {-4,2,5,9};

2
Once again, this issue will become clearer after discussion of inheritance in next chapter.

CS3 Java – Topic 9: Arrays (Singhal) Page 19 of 134


FIG. 9.16
The data member length stores a value of four as the array pointed to by reference
Arr has four elements in it. The values stored are –4, 2, 5, and 9. In addition the
object pointed to by Arr contains member methods clone and other methods. The
object itself is on the heap, whereas the reference Arr is on stack.

Other technique for copying Java array


The class java.lang.System has a static member method arraycopy, which can copy
a source array (src) to a destination array (dest) partially or fully. The method
arraycopy has the following description (Figure 9.17):
public static void arraycopy(Object src, int srcPos, Object dest,
int destPos, int length)

Parameters:
src - the source array.
srcPos - starting position in the source array.
dest - the destination array.
destPos - starting position in the destination data.
length - the number of array elements to be copied.
FIG. 9.17
The method arraycopy takes two non-null arrays src, and dest as arguments. The
method copies length number of elements from src into the array dest. The copy

CS3 Java – Topic 9: Arrays (Singhal) Page 20 of 134


process starts by copying the element at position srcPos in source array into the
index destPos in the destination. It copies length number of elements sequentially
from src to dest. We shall discuss polymorphism and polymorphic methods in next
chapter. However, it is sufficient to know at this point that when a method takes an
object of type java.lang.Object as a formal argument, one can pass to it any java
reference type as an actual argument, which is an important property of
polymorphic methods. The method arraycopy is polymorphic in the sense that
parameters src and dest could be taking identity of any array type and still it would
work fine. For example src and dest could be reference to int arrays in one case,
whereas references to String array in another. Listing 9.6 shows the technique to use
the arraycopy method.
00001 import java.io.*;
00002 public class CopyArray
00003 {
00004 private static PrintStream Console = System.out;
00008 private static final int MAX = 10;
00012 private static final int srcPos = 2;
00016 private static final int destPos = 5;
00017
00018 public static void main (String[] args)
00019 {
Console.println("Printing source array of randomly created int of size = " +MAX);
00021 int [ ] Source = new int[MAX];
00022
00023 for(int index=0; index<Source.length; index++)
00024 {
00025 Source[index] = (int)(10*Math.random( ));
00026 Console.print(Source[index]+ " ");
00027 }
00028
00029 Console.println();
00030
00031 int [ ] Destination = new int [MAX+MAX];
00032
Console.println ("Now copying " + MAX/2 + " elements from Source array "+
00034 "starting at index " + srcPos+" to Destination array starting at position "
00035 + destPos);
00036
00037 System.arraycopy (Source,srcPos,Destination,destPos,MAX/2);
00038
00039 Console.println("Printing the copied elements from source array.");
00040
00041 for(int index=srcPos; index<(srcPos+MAX/2); ++index)
00042 Console.print(Source[index]+ " ");
00043 Console.println();
00044

CS3 Java – Topic 9: Arrays (Singhal) Page 21 of 134


00045 Console.println("Printing the portion of Destination array that has "
00046 +" the copied elements only.");
00047
00048 for(int index=destPos; index<(destPos+MAX/2); ++index)
00049 Console.print(Destination[index]+ " ");
00050 Console.println();
00051
00052 Console.println("Printing entire Destination array.");
00053
00054 for(int index=0; index<Destination.length; ++index)
00055 Console.print(Destination[index]+ " ");
00056 Console.println();
00057
00058 }
00059 }//Listing 9.6
Figure 9.18 shows the output for Listing 9.6.

FIG. 9.18
Line 21 declares an int array called Source of size MAX. Source is filled with
random numbers and printed (L9.18#23-27). A Destination array of type int is
created whose size is 2*MAX (L9.18#31). The method arraycopy from System class
is called to copy MAX/2 elements from Source to Destination (L9.18#37). The copy
starts at index srcPos in Source array and corresponding copy location in
Destination array is destPos. The values of MAX (=10), srcPos (=2), and destPos
(=5) are given as class constants (L9.18 #8, 12, and 16).
Second line of Figure 9.18 shows the entire Source array created by Math.random
generated values. Since srcPos is set to a value of two and length to be copied to
MAX/2 = 5, the values to be copied from source array are: 5, 9, 9, 6, and 4. Last line
of output shows that exactly same elements are present starting index destPos = 5 to
index nine in Destination array. L9.18# 41-42 and L9.18#48-49 print the copied
elements from Source and Destination arrays respectively, which are identical.

Using Loops to assign values to Array elements sequentially


Loops can be used to fill array elements sequentially. User may enter the data for
array, from a keyboard, or data may be read from a file. We show several examples
of filling an array with data. Listing 9.7 shows the conventional methodology for
populating arrays.

CS3 Java – Topic 9: Arrays (Singhal) Page 22 of 134


import java.io.*;
public class ConvetionalArrayFilling
{
public static void main (String [] args)
{
//declare array
int [ ] arr = new int [ 10 ];
//populate with random numbers
for(int ind = 0; ind<arr.length; ++ind)
arr[ind] = (int)(10*Math.random( ) );
//Print array to console
for(int ind = 0; ind<arr.length; ++ind)
System.out.print (arr[ind] + “ “);
System.out.println( );
}
}//Listing 9.7

An integer array of size ten is declared and filled with random numbers using the
for loop. The array is subsequently printed. Depending upon the numbers generated
by method Math.random ( ) different set of values would be stored in the ten array
elements. Listing 9.7 gives us a “bare bone” technique to populate and print arrays.
However realizing the fact that any real array would be entered into the program
memory from user input (file, database, or keyboard); we can develop an advanced
version of this technique. We design a class called ManageArray, which has the
following goals:
• Take user input for an integer array3 either from the keyboard or from an
input file.
• Display the array read from keyboard or file on the console.
• If array was read from the keyboard, then give user an option to write or
append it to an output file.
• Handle all input errors in user response during menu choices.

Design of Class ManageArray


The class ManageArray would only have static methods. Since we do not wish the
client to create an instance of this class, we prevent that by writing a private
constructor for the class. When user is prompted to make choices such as whether to
enter data from keyboard or file, errors may occur. We write a method called
getUserResponse, which keeps user in the loop, until a valid response is achieved.
Other three key methods are fillFromKeyboard, fillFromFile, and print. The
method fillFromKeyboard allows user to enter an array from keyboard and
fillFromFile method reads the array from an input file in which the integers are
space de-limited. The method print, displays the array read by either of the fill

3
The limitation of data type of the array restricted to int type can be removed in the more advanced
versions of ManageArray or one can use methods in class java.lang.reflect.Array class (to be
discussed later).

CS3 Java – Topic 9: Arrays (Singhal) Page 23 of 134


methods on the console and if the array was read from keyboard, then the method
gives user an option to write or append that array to an output file.

Obviously, the member methods of class ManageArray would need to read data
from keyboard and files as well as write to files. For all file authentication purposes
the methods of class ManageArray use our previously developed class
IOManagement (developed in chapter 8). Table 9.2 gives the summary of the design
of class ManageArray.

Constructor Summary for class ManageArray


private ManageArray()
Private constructor to stop instantiation of class ManageArray
Method Summary for class ManageArray
public static char getUserResponse(int flag)
throws java.io.IOException
Method keeps user in a loop unless characters 1 or 2 or y, y, n or N is entered
and then valid character is returned.
Parameters:
flag - is the integer that controls the kind of response user would be asked to
provide.
Returns:
a valid character from user inputs.

public static void fillFromKeyboard()


throws java.io.IOException
Creates the StringTokenizer object from the keyboard input and calls the
print method for further processing.

public static void fillFromFile()


throws java.io.IOException
Creates the StringTokenizer object from the file input and calls the print
method for further processing.

public static void print(StringTokenizer St,


boolean flag)
throws java.io.IOException
Creates an int array from the space delimited tokens in the StringTokenizer
object, and displays the array on the console. Depending upon the value of
boolean variable flag writes or appends the array to an output file.
Parameters:
St - is a StringTokenizer object containing array tokens.
flag - if true, then writes or appends the array to an output file.

public static void greeting()


Greets the user and explains as to what the program does.

CS3 Java – Topic 9: Arrays (Singhal) Page 24 of 134


public static void goodBye()
Displays a goodbye message and exits the program.

Table 9.2
The methods of class ManageArray tested by the class DriverManageArray work as
follows. Inside a do while loop the method getUserResponse is called that asks user’s
choice to populate array either from a keyboard or from an input file. In first user
choice the method fillFromKeyboard is called, whereas the method fillFromFile is
called for other user choice. Both fill methods create a StringTokenizer object,
which stores the array tokens. This StringTokenizer object is passed to the print
method, where the array is created and printed. Listings 9.8A and 9.8B show the
classes ManageArray and DriverManageArray.
00001 import java.io.*;
00002 import java.util.*;
00003
00009 public class ManageArray
00010 {
00014 private static PrintStream Console = System.out;
00015
00020 private ManageArray(){}
00021
00029 public static char getUserResponse(int flag) throws IOException
00030 {
00031 BufferedReader KB = IOManagement.getKeyboardReader();
00032 char choice = ' ';
00033 boolean done = false;
00034 String Input = "";
00035
00036 do
00037 {
00038 if(flag == 1)
00039 Console.println("Enter 1 to provide data from keyboard or 2 from a file.");
00040 else if (flag == 2)
00041 Console.println("More data? [Y]es or [N]o?");
00042 else
00043 Console.println("Append your array to an output file ? [Y]es or [N]o?");
00044
00045 Input = KB.readLine();
00046 if(!(Input == null)&&!Input.equals(""))
00047 {
00048 Input = Input.trim();
00049 if(flag == 1)
00050 {
00051 if(Input.equals("1")|| Input.equals("2"))
00052 done = true;
00053 else

CS3 Java – Topic 9: Arrays (Singhal) Page 25 of 134


00054 {
00055 Console.println("Invalid choice");
00056 done = false;
00057 }
00058 }
00059 else
00060 {
00061 if(Input.equals("Y")|| Input.equals("y")||
00062 Input.equals("N")|| Input.equals("n"))
00063 done = true;
00064 else
00065 {
00066 Console.println("Invalid choice");
00067 done = false;
00068 }
00069 }
00070 }
00071 else
00072 {
00073 Console.println("Invalid operation");
00074 done = false;
00075 }
00076 }while(!done);
00077
00078 return choice = Input.charAt(0);
00079 }
00084 public static void fillFromKeyboard() throws IOException
00085 {
00086 BufferedReader KB = IOManagement.getKeyboardReader();
00087 Console.print(" Enter all int data with space between numbers. Press"
00088 +" enter key when done: ");
00089 String Input = KB.readLine();
00090
00091 if(!(Input == null)&&!Input.equals(""))
00092 {
00093 StringTokenizer St = new StringTokenizer(Input.trim());
00094 print(St, true);
00095 }
00096 else
00097 Console.println("Invalid keyboard input.");
00098
00099 }
00104 public static void fillFromFile()throws IOException
00105 {
00106 Console.println("Please enter the name of the file with int data.");
00107 BufferedReader Fl = IOManagement.getFileReader();

CS3 Java – Topic 9: Arrays (Singhal) Page 26 of 134


00108
00109 String Data_File = "";
00110 String Line = "";
00111
00112 while((Line = Fl.readLine()) != null)
00113 Data_File+=Line;
00114 StringTokenizer St = new StringTokenizer(Data_File);
00115 print(St, false);
00116 }
00125 public static void print(StringTokenizer St, boolean flag) throws
IOException
00126 {
00127 int len = St.countTokens();
00128
00129 if(len == 0)
00130 {
00131 Console.println("No data inputted.");
00132 return;
00133 }
00134
00135 int [ ] arr = new int[len];
00136
00137 int index = 0;
00138 while(St.hasMoreTokens())
00139 arr[index++] = Integer.parseInt(St.nextToken());
00140 Console.println("Printing your array to console.");
00141
00142 for(int ind = 0; ind<arr.length;++ind)
00143 Console.print(arr[ind] + " ");
00144 Console.println();
00145
00146 if(flag)
00147 {
00148 char ch = getUserResponse(3);
00149
00150 if(ch == 'Y' || ch == 'y')
00151 {
00152 PrintWriter Pw = IOManagement.getFileWriterAppend();
00153 for(int ind = 0; ind<arr.length;++ind)
00154 Pw.print(arr[ind] + " ");
00155 Pw.println();
00156 Pw.flush();
00157 Pw.close();
00158 }
00159 }
00160 }

CS3 Java – Topic 9: Arrays (Singhal) Page 27 of 134


00161
00165 public static void greeting()
00166 {
00167 Console.println("This program will get integer data either from keyboard "
00168 +" or from an ASCII file and store them in an
array and print.");
00169 }
00173 public static void goodBye()
00174 {
00175 Console.println("Thank you for using El Camino array Program.");
00176 System.exit(0);
00177 }
00178 }//Listing 9.8A

Sidebar 9.1
The design of class ManageArray shows an element of functioning of Software
Engineering. The lines 31, 86, 107, and 152 use the static member methods of class
IOManagement to get a keyboard reader, file reader, and file writer objects. Many
user errors can occur in getting the file related objects. For example the path of the
file may be wrong, the path given may not be a file, the file may be hidden. The
input file may not exist, may not have the read permission, or may be empty. The
output file may not have write permission. Since the designer and producer of the
class IOManagement already took care of all those error conditions, its client
ManageArray class does not have to worry about any of those details and can safely
use its methods to get requisite file reader and writer objects. Thus in this manner,
the IOManagement class is used as a “pre-tested” and qualified software component
by the software component class ManageArray. This is not too different from the
“assembly line” concept used in automobile manufacturing, where pre-
manufactured and tested components are assembled together to form the final
product - an automobile.

00002 import java.io.*;


00006 public class DriverManageArray
00007 {
00008 public static void main (String [] args) throws IOException
00009 {
00010 ManageArray.greeting();
00011
00012 boolean done = false;
00013 do
00014 {
00015 char choice = ManageArray.getUserResponse(1);
00016

CS3 Java – Topic 9: Arrays (Singhal) Page 28 of 134


00017 if(choice=='1')
00018 ManageArray.fillFromKeyboard();
00019 else
00020 ManageArray.fillFromFile();
00021
00022 choice = ManageArray.getUserResponse(2);
00023 if(choice == 'Y' || choice == 'y')
00024 done = false;
00025 else
00026 done = true;
00027
00028 }while(!done);
00029
00030 ManageArray.goodBye();
00031 }
00032
00033
00034 }//Listing 9.8B
Figure 9.19 shows the output from Listing 9.8B where all user inputs are shown in
bold italics.
0001 This program will get integer data either from keyboard or from an ASCII file
0002 and store them in an array and print.
00003 Enter 1 to provide data from keyboard or 2 from a file.
00004 1
00005 Enter all int data with space between numbers. Press enter key when done: 9 87
654210
00007 Printing your array to console.
00008 9 8 7 6 5 4 2 1 0
00009 Append your array to an output file ? [Y]es or [N]o?
00010 y
00011 Stand by to provide the name of file to append to.
00012 Type the output file name and press enter key.
00013 somefile
00014 More data? [Y]es or [N]o?
00015 y
00016 Enter 1 to provide data from keyboard or 2 from a file.
2
00018 Please enter the name of the file with int data.
00019 Type the input file name and press enter key.
00020 somefile
00021 Printing your array to console.
987654210
00023 More data? [Y]es or [N]o?
00024 y

CS3 Java – Topic 9: Arrays (Singhal) Page 29 of 134


00025 Enter 1 to provide data from keyboard or 2 from a file.
1
00027 Enter all int data with space between numbers. Press enter key when done: 1 23
456789
00029 Printing your array to console.
123456789
00031 Append your array to an output file ? [Y]es or [N]o?
00032 y
00033 Stand by to provide the name of file to append to.
00034 Type the output file name and press enter key.
00035 somefile
00036 The output file with name somefile already exists. Would you like to overwrite
00037 or append to the
00038 existing file? [Y]es or [N]o?
00039 y
00040 More data? [Y]es or [N]o?
00041 y
00042 Enter 1 to provide data from keyboard or 2 from a file.
2
00044 Please enter the name of the file with int data.
00045 Type the input file name and press enter key.
00046 somefile
00047 Printing your array to console.
987654210123456789
00049 More data? [Y]es or [N]o?
00050 n
00051 Thank you for using El Camino array Program.
FIG. 9.19
Testing of class ManageArray
Line 10 of Listing 9.8B calls the greeting method of class ManageArray, which is
displayed on line one and two of Figure 9.19. Local boolean variable done is set to
false (L9.8B#12). Then inside a do while loop, the method getUserResponse of
class ManageArray is called with the argument value of one (L9.8B#15) and results
stored in local character variable choice. The method getUserResponse (Listing
9.8B) gets a BufferedReader object KB, to read from the keyboard (L9.8A#31). It
also declares the local variables choice, done and input, which are character,
boolean and String respectively (L9.8A#32-34). If the value of the integer flag passed
to the method getUserResponse is one then the first if block inside the do while loop
executes (L9.8A#38-39), in which the user is prompted to enter either a value 1 or 2
to read the data either from a file or from a keyboard. Line four of Figure 9.19
shows that user chooses to enter data from keyboard by typing a value of 1. The
method getUserResponse reads the user input (L9.8A#45) into the local String
variable Input. Understand that there is no guarantee that this user input is valid as
the user may enter a tab of press control Z (on Windows 9X) as end of file

CS3 Java – Topic 9: Arrays (Singhal) Page 30 of 134


character. Therefore the first if block (L9.8A#46) checks to ascertain that String
read are neither a null nor an empty character set. Input string is then trimmed to
remove leading and lagging white spaces (L9.8A#48). If the value of int argument
flag passed to method getUserResponse is one, then user is expected to enter a value
of 1 or 2. If string Input stores either of those values (L9.8A#51-52), then there is no
error in user input and the do while loop control variable done is set to true
(L9.8A#52) and loop is exited. If user response is invalid then the else block is
executed (L9.8A#71-75), and loop control variable done is set to false. If the int
argument passed to getUserResponse is other than 1, then the else block in lines
L9.8A#59-69 is executed, which ascertains that user only enters choices Y, y, N, or
N.

Line 4 of Figure 9.19 shows that user enters 1, in order to supply data from
keyboard. Since the value returned by method getUserResponse would also be 1, the
line 18 of Listing 9.8B executes and user is routed to method
fillFromKeyboard of class ManageArray. This method calls the method
getKeyboardReader from class IOManagement to get a BufferedReader object KB
(L9.8A#86). The method prompts user to enter the integer data to be stored in the
array as space de-limited tokens (L9.8A#87-88). User input is stored in the local
String Input. Understand that user may again errantly enter a null or an empty
string. The method fillFromKeyboard checks for those conditions (L9.8A#91) and if
indeed the string Input is anything other than null or empty character set, it is
passed to the StringTokenizer constructor, and its object St is created (L9.8A#93).
The object St is passed to the method print with boolean flag value equal to true
(L9.8A#94).

The purpose of print method is to create the array from the tokens stored in
StringTokenizer object passed to it, and display such an array to console and write
to file as needed. Method print first checks the array length by counting the tokens
stored in the StringTokenizer object St passed to it (L9.8A#127). If length is zero
then user is informed that no data were inputted and method print exits
(L9.8A#129-133). Otherwise an int array of length len, which is equal to the number
of tokens stored in the incoming object St, is created (L9.8A#135). The methods
hasMoreTokens, and nextToken of StringTokenizer class manage to fill the tokens
parsed as integers into the array arr (L9.8A#137-139). The array arr is then printed
using the technique similar to the one shown in Listing 9.7. Since user enters the
array from keyboard (F9.19#5-6) and the flag value passed to method print is true
(L9.8A#94), the if block starting at line 146 of print method is executed. This block
calls the method getUserResponse with an argument value 3, so that user is
prompted to indicate their choice whether they would like to write or append this
array to an output file (L9.8A#42-43)4 (see line 9 in Figure 9.19). The user chooses to
append the array entered to an output file (F9.19#10). In Listing 9.8A a PrintWriter
object is created by calling the getFileWriterAppend method from class

4
Technically the user is only prompted to append to a file. However if a file does not exist, then the
append mode will create it.

CS3 Java – Topic 9: Arrays (Singhal) Page 31 of 134


IOManagement (L9.8A#152). The PrintWriter object Pw appends (L9.8A#153-157)
the array to the input file somefile (F9.19#13) provided by the user. The Figure 9.19
provides the proof that this was indeed accomplished. The user inputs a choice to
read the array from a file (F9.19#17), and they provide the file name somefile
(F9.19#20), into which the array was written earlier (F9.19#13). The array read
from the file somefile is printed to console (F9.19#22), which is the same array as
entered (F9.19#5-6) and displayed (F9.19#8) earlier. The Figure 9.19 shows further
results confirming that reading from file where the method fillFromFile of class
ManageArray is called, works just as well.

Passing Arrays to methods ( As non-constant and constant references)


One can pass an entire array or only one of its members, from one method to
another to process them. If the selected elements of the array are passed to a
method, they behave just like atomic data being passed to it. Figure 9.20 below
shows as how to pass each individual element of an array to a method called
printSquare to print square of each element.

public class SomeClass{


public static void main(String[] args){

int [ ] base = {3,7,2,4,5};

for(int ind=0; ind<base.length, ++ind)


printSquare (base[ind]);
}

public static void printSquare (int val)


{
System.out.println (val*val + “ “);
}
}

val

Prints val*val
to console
FIG. 9.20
In this example, using a loop, we pass each individual element of array called base
from main to a method called PrintSquare, which prints the square of each element
it receives. The method PrintSquare does not differentiate between an array element
and a single atomic data as long as the data type is same. Notice for example that in
first loop iteration in main, the value base[0] (=3) is passed to the method

CS3 Java – Topic 9: Arrays (Singhal) Page 32 of 134


printSquare, it is copied into the local variable val, whose square 9, is displayed on
the console. Similar process is followed for rest of the array elements, producing an
output of 9 49 4 16 25 on the console. Therefore an array element can be passed to a
method, in the same manner in which an atomic variable or object can be.

Passing entire array as an argument to a method


When an array is passed as an argument to a method, the following things are
required (Figure 9.21).

Using Arrays as Arguments


to methods
methods

Array reference storing the memory address


of first element.

FIG. 9.21
The arguments sent to the method to process array are the name of the array and its
logical processing length. The length parameter can be omitted if entire array need
to be processed. Figure 9.21 shows the example of finding an average of the numbers
in an array, when the array called base is passed to the method average.

CS3 Java – Topic 9: Arrays (Singhal) Page 33 of 134


import java.text.*;
public class MyClass{
public static void main(String[] args){

int [ ] base = {3,7,2,4,5};

double ave = average(base);


DecimalFormat DF = new DecimalFormat (“0.00”);

System.out.println (DF.format (ave));


}

public static double average (int [ ] x)


{
int sum = 0;
for(int i=0; i<x.length; ++i)
sum+=x[i];
return (sum*1.0)/x.length; Output to console
}
}
4.20

FIG. 9.22
Pay attention to the syntax as to how the array name is used as formal argument to
the method average, compared to when the method is called from main.
The argument to average method contains the array data type, a square bracket,
and array name. In Figure 9.22 the header for method average can be written as:

public static double average( int x [ ] ) or


public static double average (int [ ] x)

The actual call to the method in the main is different as it just has the array name in
it. For example the call statement is:

double ave = average(base);

A compile error will be caused if square brackets were to be included in the method
call. For example:

double ave = average(base [ ] ); //Compile Error because of square brackets

When an array is passed to a method, then the copy of the address of its base
element or its first element is passed as a parameter. For example in Figure 9.22 in

CS3 Java – Topic 9: Arrays (Singhal) Page 34 of 134


method average the address stored in x is same as the one stored in base in the main
method. Therefore x[0] accesses the value base[0], x[1] the value base[1] and so on.
The method to which the array reference is passed can access all elements of an
array because it has the address of the base element. This gives the method
capability to change the values of the array elements. This is shown in Figure 9.22.

public class YourClass{


public static void main(String[] args)
{

int [ ] base = {3,7,2,4,5};

multiply2(base);
for(int i=0; i<base.length; ++i)
System.out.print(base[i] + “ “);
System.out.println( );
}

public static void multiply2 (int [ ] x)


{
for(int i=0; i<x.length; ++i)
x[i] = x[i]*2;
}
}
Output to console

6 14 4 8 10

FIG. 9.22
In Listing shown in Figure 9.22, the array called base is passed to the method
multiply2. There each element is multiplied by a factor of two. Effectively then the
array base has changed in the main method as well. The console output in Figure
9.22 shows the changed state of the array as modified by method multiply2. So in
process of passing an array, since the address of base element is passed, effectively,
entire array is available to the calling method to modify it. Understand that the
method to which the array is passed can also assign that array reference to another
array. Java allows its array reference types to print the address stored in the array
name by using a method called hashCode (which is available to all Java reference
types). Output from Listing 9.9 proves that when the arrays are passed to methods,
the copy of the address stored in the array name is passed.

CS3 Java – Topic 9: Arrays (Singhal) Page 35 of 134


public class ArrayPassing
{
public static void main(String[] args)
{
String [ ] base = {"John","Mary","Dave","Tim","Jill"};
System.out.println ("The address stored in array name in main = "
+base.hashCode ( ));
processArray(base);
}

public static void processArray(String [ ] nums)


{
System.out.println ("The address stored in array name in processArray = "
+nums.hashCode ( ));
}
}

Listing 9.9 and its output


We declare and print the address of array called base in main. Then we pass the
base to the method ProcessArray and print its address again using the method
hashCode5. The output of Listing 9.9 shows that two addresses printed are identical,
proving that in passing the array called base from the main, the copy of the address
stored in the reference called base was passed. As we also saw in method multiply2,
the method, which gets an array as an argument, can change the values of array
elements. This affects can be used to design a method that would fill an empty array
sent to it. We discuss an example of such code shortly.

Use of Keyword final, if array reference is not to be re-assigned


When a method receives an array as an argument, it has read/write access to the
array elements. Additionally, however, the method can reassign a new array to the
array name in its method argument. Consider for example the method processArray
below:

public static void processArray ( int [ ] nums)


{
//code
}

5
One must exercise caution is using the method hashCode in printing the address of a reference type.
It will not work if the object is immutable. In Java identical immutable objects print the same
hashCode, even if they are stored in two different memory locations.

CS3 Java – Topic 9: Arrays (Singhal) Page 36 of 134


The method processArray can alter the values stored in nums through a code
exercising random write access. One example is given below:

for(int ind=0; ind<nums.lengh; ++nums)


nums [ind] = (int)(10*Math.random ( ));

Other possible action that method processArray can take is to reassign name nums
to another int array on heap as shown in the code snippet below.

nums = new int [ 10 ]; Now nums stores a new address,


different from the one stored in
the caller method!

There may be situations in which we wish that the method to which we pass the
array to couldn’t re-assign that array name. This can be accomplished by passing
the array to the method as a final reference. If the header of method processArray is
changed as follows:

public static void processArray (final int [ ] nums)

then inside the body of processArray, the following code will cause compile error.

nums = new int [ 10 ];


Compile error because nums
is passed as a final
(unchangeable) parameter!!!

Listing 9.10 shows three methods processArrayOne, processArrayTwo, and


processArrayThree, exercising the degrees of freedoms available to the methods on
arrays passed to them. We use the example of a String array. However same
principle applies to arrays of other data types.
00001 public class ArrayAsArguments
00002 {
00003 public static void main(String[] args)
00004 {
00005 System.out.println("**************************************");
00006 System.out.println("Output from main.");
00007 String [ ] base = {"John","Mary","Dave","Tim","Jill"};
00008 System.out.println("The address stored in array called base in main = "
00009 +base.hashCode());
00010 System.out.println("Printing the array base in main method "
00011 +" before the call to method ProcessArrayOne.");

CS3 Java – Topic 9: Arrays (Singhal) Page 37 of 134


00012 for(int ind=0; ind<base.length; ++ind)
00013 System.out.print(base[ind] + " ");
00014 System.out.println();
00015
System.out.println("Passing the array called base to method ProcessArrayOne.");
00017 processArrayOne(base);
00018 System.out.println("**************************************");
00019 System.out.println("Output from main.");
00020 System.out.println("Printing the array base in main method "
00021 +" after the call to method ProcessArrayOne.");
00022
00023 for(int ind=0; ind<base.length; ++ind)
00024 System.out.print(base[ind] + " ");
00025 System.out.println();
00026
System.out.println("Passing the array called base to method ProcessArrayTwo.");
00028 processArrayTwo(base);
00029 System.out.println("**************************************");
00030 System.out.println("Output from main.");
00031 System.out.println("Printing the array base in main method "
00032 +" after the call to method ProcessArrayTwo.");
00033
00034 for(int ind=0; ind<base.length; ++ind)
00035 System.out.print(base[ind] + " ");
00036 System.out.println();
00037
System.out.println("Passing the array called base to method ProcessArrayThree.");
00039 processArrayThree(base);
00040 System.out.println("**************************************");
00041 System.out.println("Output from main.");
00042 System.out.println("Printing the contents of array base in main method "
00043 +" after the call to\n method ProcessArrayThree.");
00044
00045 for(int ind=0; ind<base.length; ++ind)
00046 System.out.print(base[ind] + " ");
00047 System.out.println();
00048 }
00049
00050 public static void processArrayOne(String [ ] Names)
00051 {
00052 System.out.println("**************************************");
00053 System.out.println("Output from method processArrayOne.");
System.out.println("The address stored in array Names (passed from main)\n in processArrayOne = "
00055 +Names.hashCode());
00056 Names[0] = "Tonny";

CS3 Java – Topic 9: Arrays (Singhal) Page 38 of 134


00057 Names[1] = "Morine";
00058 Names[2] = "Nancy";
00059 Names[3] = "Mister M";
00060
00061 System.out.println("Printing the array Names in method ProcessArrayOne "
00062 +" after changing some elements.");
00063 for(int ind=0; ind<Names.length; ++ind)
00064 System.out.print(Names[ind] + " ");
00065 System.out.println();
00066 }
00067
00068 public static void processArrayTwo(String [ ] Names)
00069 {
00070 System.out.println("**************************************");
00071 System.out.println("Output from method processArrayTwo.");
00072 System.out.println("The address stored in array Names " +
00073 " (passed from main) in processArrayTwo\n"
00074 +" before reassigning to new array on heap = "+Names.hashCode());
System.out.println("Now re-assigning the array reference Names to a new array.");
00076 Names = new String[ ] { "Bertha", "Hagrid", "Harry Potter", "Gargoyle"};
System.out.println("After assigning the array reference Names\n to a new array"
00078 + " the address stored in Names now is = " + Names.hashCode());
00079
00080 System.out.println("The names stored in Names array are : ");
00081
00082 for(int ind=0; ind<Names.length; ++ind)
00083 System.out.print(Names[ind] + " ");
00084 System.out.println();
00085 }
00086
00087 public static void processArrayThree(final String [ ] Names)
00088 {
00089 System.out.println("**************************************");
00090 System.out.println("Output from method processArrayThree.");
00091 Names[0] = "James";
00092 Names[1] = "Mathew";
00093 Names[2] = "Norine";
00094 Names[3] = "Ralph";
System.out.println("Printing the array Names in method ProcessArrayThree "
00096 +" after changing some elements.");
00097 for(int ind=0; ind<Names.length; ++ind)
00098 System.out.print(Names[ind] + " ");
00099 System.out.println();
00100 //uncommenting below will cause a compile error
00101 //Names = new String [ 10];
00102 }

CS3 Java – Topic 9: Arrays (Singhal) Page 39 of 134


00103 }//Listing 9.10
main method creates an array called base with five names stored in it (L9.10#7) and
displayed by Figure 9.23 line #5. The address of the array base in main is printed
by program (L9.10#8-9) and is displayed in output (F9.23#3).
00001 **************************************
00002 Output from main.
00003 The address stored in array called base in main = 18508170
00004 Printing the array base in main method before the call to method
ProcessArrayOne.
00005 John Mary Dave Tim Jill
00006 Passing the array called base to method ProcessArrayOne.
00007 **************************************
00008 Output from method processArrayOne.
00009 The address stored in array Names (passed from main)
00010 in processArrayOne = 18508170
00011 Printing the array Names in method processArrayOne after changing some
elements.
00012 Tonny Morine Nancy Mister M Jill
00013 **************************************
00014 Output from main.
00015 Printing the array base in main method after the call to method
processArrayOne.
00016 Tonny Morine Nancy Mister M Jill
00017 Passing the array called base to method processArrayTwo.
00018 **************************************
00019 Output from method processArrayTwo.
00020 The address stored in array Names (passed from main) in processArrayTwo
00021 before reassigning to new array on heap = 18508170
00022 Now re-assigning the array reference Names to a new array.
00023 After assigning the array reference Names
00024 to a new array the address stored in Names now is = 17237886
00025 The names stored in Names array are :
00026 Bertha Hagrid Harry Potter Gargoyle
00027 **************************************
00028 Output from main.
00029 Printing the array base in main method after the call to method
ProcessArrayTwo.
00030 Tonny Morine Nancy Mister M Jill
00031 Passing the array called base to method ProcessArrayThree.
00032 **************************************
00033 Output from method processArrayThree.
00034 Printing the array Names in method ProcessArrayThree after changing some
elements.
00035 James Mathew Norine Ralph Jill
00036 **************************************
00037 Output from main.

CS3 Java – Topic 9: Arrays (Singhal) Page 40 of 134


00038 Printing the contents of array base in main method after the call to
00039 method ProcessArrayThree.
00040 James Mathew Norine Ralph Jill
//FIG. 9.23
The array base is printed in the main method (L9.10#12-14) and then it is passed to
method processArrayOne (L9.10#17). Figure 23.3 shows the values stored in array
base before it is passed to method processArrayOne (Line #5). Since at that point
the program control is transferred to the method processArrayOne, the method
prints out the address stored in the array name “Names” passed to it (L9.10#53-54).
The output shows that this address (F23.3#10) is identical to the one printed in main
method (F23.3#3) proving that a copy of the same address is passed to the method
processArrayOne. The Figure 9.24 shows the situation during the call to
ProcessArrayOne.

FIG. 9.24
Since the reference Names in the method processArrayOne points to the same array
as in main, the method has the random read/write access to the array. The method
changes the names stored in first four array elements (L9.10#56-59), changing the
state of the array as shown in Figure 9.25.

CS3 Java – Topic 9: Arrays (Singhal) Page 41 of 134


FIG. 9.25
The method then prints the names stored in the changed array (L9.10#63-65), and
after the method call is over, the main also prints the array (L9.10#23-25). The
output (F23.3#12 & #16) shows identical name list confirming the state in Figure
9.25.

Passing the array to method processArrayTwo


The method processArrayTwo first prints the address stored in array reference
“Names” in as received state (L9.10#72-74). As expected Figure 9.23 Line #21 prints
the same address as the one in main (F23.3#3). However, on line (L9.10#76), the
method processArrayTwo assigns a new array on the heap to the array reference
called “Names”. Figure 9.26 shows this changed situation.

CS3 Java – Topic 9: Arrays (Singhal) Page 42 of 134


FIG. 9.26
Ones the method processArrayTwo assigns the array reference Names to another
array by executing the code line (L9.10#76) ;
Names = new String[ ] { "Bertha", "Hagrid", "Harry Potter", "Gargoyle"};
the array reference Names points to a new array on heap and its connection to the
array in main method is severed. Therefore when printing inside the method
processArrayTwo (L9.10#82-84), this new array is printed (F23.3#26). However
when the method call is finished and control is returned to main, the array remains
unchanged. The stored values printed in main after the call to method
processArrayTwo (L9.10#34-36) show an unaltered array (F23.3#30 & #16).

Passing the array to method processArrayThree


The main method then passes the array to method processArrayThree (L9.10#39).
Notices that this method takes array as an argument that is a final reference
(L9.10#87).
public static void processArrayThree(final String [ ] Names)
Placing the word final before any reference parameter passed to a method enforces
the locking of reference parameter name and the memory location on the heap
whose address the reference stores. Thus the method processArrayThree is not
allowed to re-assign the reference “Names” to a new array. Therefore in this method
uncommenting the line L9.10#101 will cause a compile error. However, the method
can still alter the array! The lines, L9.10#91-94 store new names in the first four
elements in the array and it alters the array as shown in Figure 9.27.

CS3 Java – Topic 9: Arrays (Singhal) Page 43 of 134


FIG. 9.27
The names printed locally inside the method (L9.10#97-99) and then again in main
(L9.10#46-47) print identical results (F23.3#35 # #40).

A point of confusion for C++ Programmers


In many ways, the Java keyword final does resemble and act like the C++ word
const. For example the following two declarations, first one in C++ and second one
in Java have identical meaning.

const int val = 30;//C++ statement for declaring a named constant


final int val = 30;//Java statement for declaring a named constant

In the same vain, when an array is passed to a method in C++, if the keyword const
is placed before the array data type, then the method is allowed read only access to
the array. For example the method with the following header in C++ will have read
only access to the array called “Names”.

void processArrayThree (const string Names [ ] )

The header for the method processArrayThree given below looks almost like its
C++ counter part.

public static void processArrayThree (final String [ ] Names)

CS3 Java – Topic 9: Arrays (Singhal) Page 44 of 134


However, the Java method is vastly different in the sense that method is still allowed
to alter the array. Therefore C++ programmers learning Java need to remember
that use of keyword final for an array reference does not take away its write access
to the array, as the use of keyword const in C++ would6. In Java, whether the array
elements are immutable or not, depends upon the nature of elements stored in the
array. However, there is no way to make entire stand-alone array into an immutable
object in Java. For example the second line in the following code snippet in C++
would cause a compile error:
Compile error! The L
const int arr[4] = {1,2,3,4}; value, the array name arr
arr[0] = 10; // is a constant object.
However a similar code as shown in lines below in Java is will not cause a compile
error.

final int [ ] arr_final = {1,2,3,4}; No compile error! The only


arr_final[0] = 10; restriction is that arr_final is
not re-assignable

Unfortunately, even in C++ the use of const_cast operator can remove the
restriction of no write access originally imposed on a constant array. For example
the code below in C++ will not print the values 1, 2, 3, 4.

const int arr[4] = {1,2,3,4};


int * arr1 = const_cast<int*>(arr);
arr1[0] = 10;
for(int ind = 0; ind<4; ind++)
cout<<arr[ind]<<endl;
Rather, it will print values 10, 2, 3, 4, as the constancy of array arr is broken down
by the use of operator const_cast.

Anonymous Arrays
As mentioned earlier, one form of Java’s implicit array sizing declaration technique
allows the programmer to pass an anonymous array to a method as an argument. In
Listing 9.11 the main method passes an anonymous array to the caller method print,
which in turn prints it.

6
Even in C++, however, the use of const_cast can overturn the lack of write access to array which
was originally passed as a const.

CS3 Java – Topic 9: Arrays (Singhal) Page 45 of 134


Anonymous array
created on fly and passed
public class AnonymousArray
{ to the method print
public static void main(String[] args)
{
print ( new int[ ]{rnd( ),rnd( ),rnd( ),rnd( ),rnd( ),rnd( ),rnd( ), } );
}
/////////////////////////////////////////////////////////////////////
public static void print(int [ ] anon)
{
for(int ind=0; ind<anon.length; ++ind)
System.out.print (anon [ind] + " ");
System.out.println ( );
}
////////////////////////////////////////////////////////////////////////
public static int rnd( )
{
return (int)(10*Math.random( ));
}
}//Listing 9.11
The method rnd generates a random integer and returns its value to generate seven
elements for the anonymous array passed to method print inside the main. This
anonymous array is given a name anon in the method print, where it is printed to
console. This technique could be useful for a read-only array, which is generally
created for one time application. Notice that a lagging comma after the last element
in the anonymous array is ignored by Java, and does not cause a compile error. The
output of Listing 9.11 would print seven integers, randomly created by method
Math.random.

Arrays as Static and instance class variables


Similar to other reference types, arrays can be declared as static and/or instance
class variables. The initialization of array class data members is done exactly in the
manner available for other class data members. One can use all three techniques,
such as direct assignment, an initialization block, or a constructor to initialize the
array class members. In direct assignment, programmer would need to provide an
initialization list or an array length, whereas the use of initialization block or a
constructor can allow user to input a length and data subsequently. Table 9.3A
shows the design of fields of a class called Array Class.
Summary of Fields for class ArrayClass
private Console
static java.io.PrintStream PrintStream object to facilitate printing to
console.
private static int MAX
A default length parameter for String array
instance variable.

CS3 Java – Topic 9: Arrays (Singhal) Page 46 of 134


private Presidents
static java.lang.String[] An array of user defined length to store names
of former American presidents.
private static Singers
final java.lang.String[] An array of names of six American singers
with values "Elvis","Maddona","Barry Manilow",
"Rex Harrison", "Whitney", "Cindy Lauper"
private Students
java.lang.String[] An array to store only first name of students.
Table 9.3A
The class ArrayClass has three String arrays, in which the Presidents and Singers
are static and Students is non-static. The array Singers is final. The class
ArrayClass contains constructor, static initialization block, and methods, whose
design summary is provided by Table 9.3B.

CS3 Java – Topic 9: Arrays (Singhal) Page 47 of 134


Constructor Summary for ArrayClass
public ArrayClass()
Argument-less constructor calls the create method to get the length for the
array Students, and allocates memory for it.
Methods/blocks Summary for ArrayClass
Static initialization block to initialize the static array Presidents. Calls
methods create to get the array length and then calls method assigns to fill it
with user data.

private static void create(boolean option)


Depending upon the value of boolean parameter option, either gets the length
for the instance array variable Students or getes the length for and allocates
memory for the static String array called Presidents.
Parameters:
option - For true value of option the static array Presidents is created else
the length is set for the array instance variable Students.

private static void assign()


Sequentially assigns data sequentially into the array Presidents.

public static void printStaticArray()


Prints either the array Singers or Presidents or both.

public void fillArray()


throws java.io.IOException
Fills the instance array Students with user data.
Throws:
java.io.IOException

public void printStudents()


Prints the instance array Students
Table 9.3B
Two private static methods create and assign facilitate the creation of array objects
on heap and assigning values to their members. create method is called to either
create black Presidents or Students array based on user inputted lengths. Method
assign fills the static array Presidents, whereas fillArray fills the Students. Method
printStaticArrays prints either or both of static arrays (Singers and Presidents),
whereas printStudents prints the Students array.

Listing 9.12A shows the source code for class ArrayClass.


00001 import java.io.*;
00002 import javax.swing.*;
00003 import java.util.*;
00004
00005 public class ArrayClass

CS3 Java – Topic 9: Arrays (Singhal) Page 48 of 134


00006 {
00007 private static PrintStream Console = System.out;

private static final String [ ] Singers= {"Elvis","Maddona","Barry Manilow",


00009 "Rex Harrison", "Whitney", "Cindy Lauper"};
00010 private static String [ ] Presidents;
00011 private static int MAX = 5;
00012 private String [ ] Students;
00013
00014
00015 public ArrayClass()
00016 {
00017 create(false);
00018 Students = new String[MAX];
00019 }
00020 static
00021 {
00022 create(true);
00023 assign();
00024 }
00025
00026 private static void create(boolean option)
00027 {
00028 boolean done = false;
00029 do
00030 {
00031 String Mes1 = ("Enter the number of former US presidents, whose names\n"
00032 + " are to be stored in the array called Presidents: ");
00033 String Mes2 = ("Enter the number of students whose names are\n"
00034 + " to be entered in the array.");
00035 String Input = null;
00036
00037 if(option)
00038 Input = JOptionPane.showInputDialog (Mes1);
00039 else
00040 Input = JOptionPane.showInputDialog (Mes2);
00041
00042 if(Input!= null && Input.length() != 0)
00043 {
00044 int len = Integer.parseInt(Input.trim());
00045 if(len>0 && option)
00046 {
00047 Presidents = new String [len];
00048 done = true;
00049 }
00050 else if(len>0 && !option)

CS3 Java – Topic 9: Arrays (Singhal) Page 49 of 134


00051 {
00052 MAX = len;
00053 done = true;
00054 }
00055 else
00056 {
00057 JOptionPane.showMessageDialog(null, "Illegal array length");
00058 done = false;
00059 }
00060 }
00061 else
00062 {
00063 JOptionPane.showMessageDialog(null,"Illegal input/operation.");
00064 done = false;
00065 }
00066 }while(!done);
00067 }
00071 private static void assign()
00072 {
00073 boolean done = false;
00074 do
00075 {
00076 String Input = JOptionPane.showInputDialog("Enter first and last names"
00077 + " of up to " + Presidents.length + " presidential names to be stored.");
00078
00079 if(Input!= null && Input.length() != 0)
00080 {
00081 StringTokenizer St = new StringTokenizer(Input.trim());
00082 int tokens = St.countTokens ( );
00083
00084 if(tokens%2 !=0)
00085 {
00086 JOptionPane.showMessageDialog(null, "Only either first or"
00087 +" last name is entered for one of the president.");
00088 done = false;
00089 }
00090 else
00091 {
00092 if(Presidents.length<St.countTokens()/2)
00093 {
00094 JOptionPane.showMessageDialog(null,
00095 "Number of Presidential names entered exceeds array length.\n"
00096 +" Extra lagging names will not be stored.");
00097 }
00098
00099 for(int ind=0; ind<(Presidents.length)&& St.hasMoreTokens();

CS3 Java – Topic 9: Arrays (Singhal) Page 50 of 134


00100 ++ind)
00101 Presidents[ind] = St.nextToken( )+" " + St.nextToken( );
00102
00103 done = true;
00104 }
00105 }
00106 else
00107 {
00108 JOptionPane.showMessageDialog(null,"Illegal input operation.");
00109 done = false;
00110 }
00111 }while(!done);
00112 }
00116 public static void printStaticArray()
00117 {
00118 boolean done = false;
00119
00120 do
00121 {
00122 String Input = JOptionPane.showInputDialog("Enter 1 to print presidents "
00123 +" or 2 to print Singers or 3 to print both.");
00124
00125 if(Input!= null && Input.length() != 0)
00126 {
00127 Input = Input.trim();
00128 if(Input.equals("1"))
00129 {
00130 for(int ind = 0;
00131 (ind<Presidents.length)&& (Presidents[ind]!= null);
++ind)
00132 Console.print(Presidents[ind] + " ");
00133 Console.println();
00134 done = true;
00135 }
00136 else if(Input.equals("2"))
00137 {
00138 for(int ind = 0; ind<Singers.length; ++ind)
00139 Console.print(Singers[ind] + " ");
00140 Console.println();
00141 done = true;
00142 }
00143 else if(Input.equals("3"))
00144 {
00145 Console.println("Singers:");
00146 for(int ind = 0; ind<Singers.length; ++ind)
00147 Console.print(Singers[ind] + " ");

CS3 Java – Topic 9: Arrays (Singhal) Page 51 of 134


00148 Console.println("\nPresidents:");
00149

00150 for(int ind = 0;


00151 (ind<Presidents.length)&& (Presidents[ind]!= null); ++ind)
00152 Console.print(Presidents[ind] + " ");
00153 Console.println();
00154 done = true;
00155 }
00156 else
00157 {
00158 JOptionPane.showMessageDialog(null, "Invalid choice. Click ok.");
00159 done = false;
00160 }
00161 }
00162 else
00163 {
00164 JOptionPane.showMessageDialog(null,"Illegal input operation.");
00165 done = false;
00166 }
00167 }while(!done);
00168 }
00172 public void fillArray() throws IOException
00173 {
00174 JOptionPane.showMessageDialog
00175 (null,"Please observe the console output for further processing.");
00176 BufferedReader KB = IOManagement.getKeyboardReader();
00177 boolean done = false;
00178 do
00179 {
00180 Console.println("Enter only the first names of up to " + MAX+
00181 " Students to be entered in the array and then press enter key.");
00182 String Input = KB.readLine();
00183
00184 if(Input!= null && Input.length() != 0)
00185 {
00186 StringTokenizer St = new StringTokenizer(Input.trim());
00187 int tokens = St.countTokens();
00188 if(tokens>0)
00189 {
00190 if(tokens>MAX)
00191 Console.println("The number of students entered is larger "
00192 + " than array size. The extra names will be excluded.");
00193
00194 int index = 0;
00195 while(St.hasMoreTokens()&& index<MAX)

CS3 Java – Topic 9: Arrays (Singhal) Page 52 of 134


00196 this.Students[index++]= St.nextToken();
00197 done = true;
00198 }
00199 else
00200 {
00201 Console.println("No names entered.");
00202 done = false;
00203 }
00204 }
00205 else
00206 {
00207 Console.println("Illegal operation.");
00208 done = false;
00209 }
00210 }while(!done);
00211 }
00212
00213 public void printStudents()
00214 {
00215 Console.println("Printing the students in the array now.");
00216 for(int ind=0; ind<MAX &&(this.Students[ind] != null); ++ind)
00217 Console.print(this.Students[ind] + " ");
00218 Console.println();
00219 }
00223 }//Listing 9.12A
Static Members
The static array Singers is declared and initialized by direct assignment using an
initialization list (L9.12A#8). The static array reference Presidents is declared in line
L9.12A#10. The static initialization block (L9.12A#20-24) calls private methods
create and assign to allocate memory for array Presidents and then fill it with user
defined values respectively. The static int member MAX is used as a default
parameter for the length of instance array member Students.

void static method create


The void static method create takes a boolean parameter as an argument. For true
value of parameter option it displays the message Mes1 to the user, asking for the
length of array Presidents (L9.12A#31-32 &37-38). Same actions are taken for the
false value of option for the array Students (L9.12A#33-34 &39-40). Three if/else-
if/else blocks create either a Presidents array (L9.12A#45-49), or a Students array
(L9.12A#50-54), or inform user that an illegal array length has been entered
(L9.12A#55-59). The do while loop repeats the data input process, until either the
Presidents or the Students array of length greater than zero have been created.

void static method assign


The method assign populates the array Presidents with user-inputted data from the
keyboard. The restriction of using this method to only populate the static array is an

CS3 Java – Topic 9: Arrays (Singhal) Page 53 of 134


ad-hoc one, and can be removed in and advanced version. The method prompts the
user to enter the first and last names of the past presidents up to number equal to
the array length (L9.12A#76-77). A StringTokenizer object St takes the trimmed
user- inputted names String as an argument and numbers of tokens in it are
counted (L9.12A#81-82). If numbers of tokens are not even then user failed to enter
either the first or last name for one of the president and if block to inform user is
executed (L9.12A#84-89). Otherwise inside the attached else block (L9.12A#91-104)
program checks if array length is larger than half of number of tokens. If that is not
true then user is informed that number of names entered is larger than the array
length and extra names would be ignored (L9.12A#92-97). Notice that this limitation
is not necessary as we can easily recreate a new array to accommodate extra names.
A for loop populates the array Presidents up to its physical length (L9.12A#99-101).

void static method printStaticArray


The method prints to console, either the array Presidents or Singers or both. User is
prompted for their printing choice (L9.12A#122-123). For user choice one only the
filled portion of Presidents array is printed to console (L9.12A#130-134). For
choices two or three the filled lengths of Singers or both Singers and Presidents are
printed (L9.12A#136-155).

Non static members


The class ArrayClass has Students as an instance array data member. The
constructor calls the method assign to get user inputted length for the Students
array and assign method sets data member MAX equal to the user input
(L9.12A#52). The constructor then assigns the memory for the array on the heap
(L9.12A#18). The instance method fillArray populates the Students array with user
data. For the sake of simplicity we only ask user to input first names (L9.12A#180-
181). A StringTokenizer object St is created from user input, and number of tokens
in it are counted (L9.12A#186-187). If number of tokens entered is greater than zero
(L9.12A#188-198), then program checks to see if tokens exceed the array length
(L9.12A#190-192), in which case the user is informed that extra tokens would be
ignored. The array Students is then populated with user provided tokens, up to the
physical length of the array (L9.12A#194-196). User is looped through in case that
no names are entered or illegal entries were made. The method printStudents
displays only the filled portion of the Students array on the console.

Testing ArrayClass
Listing 9.12B shows two methods main1 and main2 used to test the
creation and printing of static arrays and instance arrays respectively.
00001 import java.io.*;
00002
00003 public class DriverArrayClass
00004 {
00005 public static void main(String[] args) throws IOException
00006 {

CS3 Java – Topic 9: Arrays (Singhal) Page 54 of 134


00007
00008 main1( );
00009 //main2( );
00010 System.exit (0);
00011 }
00012
00013 public static void main1()
00014 {
00015 ArrayClass.printStaticArray( );
00016 }
00017 public static void main2( ) throws IOException
00018 {
00019 ArrayClass Inst = new ArrayClass();
00020 Inst.fillArray();
00021 Inst.printStudents();
00022 }
00023
00024 }//Listing 9.12B
The method main1 calls the static method printStaticArray, and the call to this
static method loads the static initialization block (L9.12A#20-24), which calls the
static methods create and assign. This results in displaying the pop up box for user
to enter the length of array Presidents (Figure 9.28A).

FIG. 9.28A
Assuming that user entered array length to be five and bottom portion of Figure
9.28A shows the names entered on the console input then a message to the affect that
number of names entered exceed array length is displayed (Figure 9.28B).

CS3 Java – Topic 9: Arrays (Singhal) Page 55 of 134


FIG. 9.28B
When user is prompted to enter a choice to print the contents of static arrays, a pop
up box accepts user choice and the console displays the contents of the static arrays
printed as per user choice (Figure 9.28C).

FIG. 9.28C
Comparing Figures 9.28A and 9.28C one notice that the output does not print the
presidents Herbert Hoover and Franklin Roosevelt as the array length was not large
enough and was not expanded to include them. All the singers hard coded in the
declaration of array Singers are displayed.

If method main2 is executed then an instance Inst of ArrayClass is created


(L9.12B#19) which results in call to assign method, which prompts the user to input
the length for the Students array (Figure 9.28D).

FIG. 9.28D

CS3 Java – Topic 9: Arrays (Singhal) Page 56 of 134


main2 then calls the fillArray and printStudents methods (L9.12B#20-21) resulting
in data entry for student names and printing them to console (Figure 9.28E).

FIG. 9.28E
Notice that extra names are excluded.

Array of characters in Java though not a String can be printed


aggregately!
One must understand that unlike C++ an array of characters in Java is not a String.
For example, an array of characters such as Name below in C++ would be a string
and can be printed with the aggregate print operator cout<<.
Forms a string in
char Name[ ] = {‘J’,’a’,’m’,’e’,’s’,NULL}; C/C++
cout<<Name;

An array exactly like the one above will not compile in Java (as null in Java is not a
primitive value). However Java will print a char array, just by passing it to the
method println as below even though the array Names is not a String.

char [ ] Name= {'J','a','m','e','s'}; Prints James to


System.out.println (Name); console.

This special facility to print an array in Java aggregately is not extended to data
types other than char! Printing a char array aggregately is the only aggregate
operation Java allows on arrays.

Swapping of values
A common programming need is to have a method that would swap the value of two
variables of same type passed to it. For example in C++ a swap method written
below can be coded in such a manner that upon completion of method call the
values stored in variables num1 and num2 would be swapped.
Swap in C++ can be coded such
void swap (int & num1, int & num2) that after method call the values
stored in num1 and num2 are
swapped.

CS3 Java – Topic 9: Arrays (Singhal) Page 57 of 134


In swap method above, since both num1 and num2 are passed by reference, C++
code can switch values stored in them. Since in Java, all parameters are passed by
value only, and wrapper classes for all primitives are immutable objects, the swap
method written in above style will not work, as any swapping done by the method
would strictly be local. Listing 9.13 and its output show the ineffectiveness of
conventionally written swap method called swap1.
00001 import java.util.*;
00002
00003 public class Swap
00004 {
00005 public static void main(String[] args)
00006 {
00007 int Data1 = 10;
00008 int Data2 = 15;
00009 System.out.println("The current values of \n" +
00010 "Data1 = " + Data1 +"\n"+
00011 "Data2 = " + Data2);
00012 swap1(Data1,Data2);
00013 System.out.println("After calling swap1 the value of \n" +
00014 "Data1 = " + Data1 +"\n"+
00015 "Data2 = " + Data2);
00016 System.out.println("Declaring two one element int arrays D1, D2");
00017 int [] D1 = {33};
00018 int [] D2 = {55};
00019 System.out.println("The current values of \n" +
00020 "D1[0] = " + D1[0] +"\n"+
00021 "D2[0] = " + D2[0]);
00022 swap2(D1,D2);
00023 System.out.println("After calling the swap2 values of \n" +
00024 "D1[0] = " + D1[0] +"\n"+
00025 "D2[0] = " + D2[0]);
00026
00027 StringBuffer C1 = new StringBuffer(new Integer(Data1).toString());
00028 StringBuffer C2 = new StringBuffer(new Integer(Data2).toString());
00029 swap3(C1,C2);
00030 System.out.println("After calling swap3 the value of \n" +
00031 "Data1 = " + C1.toString() +"\n"+
00032 "Data2 = " + C2.toString());
00033
00034 Data1 = 1000;
00035 Data2 = -22222222;
00036
00037 System.out.println("The current values of \n" +
00038 "Data1 = " + Data1 +"\n"+
00039 "Data2 = " + Data2);
00040 C1 = new StringBuffer(new Integer(Data1).toString());

CS3 Java – Topic 9: Arrays (Singhal) Page 58 of 134


00041 C2 = new StringBuffer(new Integer(Data2).toString());
00042 swap3(C1,C2);
00043
00044 Data1 = Integer.parseInt(C1.toString());
00045 Data2 = Integer.parseInt(C2.toString());
00046 System.out.println("After calling swap3 the value of \n" +
00047 "Data1 = " + Data1 +"\n"+
00048 "Data2 = " + Data2);
00049
00050 double dbl1 = 99.999954;
00051 double dbl2 = -99.203;
00052 C1 = new StringBuffer(new Double(dbl1).toString());
00053 C2 = new StringBuffer(new Double(dbl2).toString());
00054 System.out.println("The current values of \n" +
00055 "dbl1 = " + dbl1 +"\n"+
00056 "dbl2 = " + dbl2);
00057 swap3(C1,C2);
00058 dbl1 = Double.parseDouble(C1.toString());
00059 dbl2 = Double.parseDouble(C2.toString());
00060 System.out.println("After calling swap3 the value of \n" +
00061 "dbl1 = " + dbl1 +"\n"+
00062 "dbl2 = " + dbl2);
00063
00064 C1 = new StringBuffer("Mary");
00065 C2 = new StringBuffer("John");
00066
00067 System.out.println("Before calling swap3 the value of \n" +
00068 "C1 = " + C1 +"\n"+
00069 "C2 = " + C2);
00070 swap3(C1,C2);
00071 System.out.println("After calling swap3 the value of \n" +
00072 "C1 = " + C1 +"\n"+
00073 "C2 = " + C2);
00074 //testing swap4
00075 int value1 = -77;
00076 int value2 = 900;
00077 System.out.println("Before calling swap4 the value of \n" +
00078 "value1 = " + value1 +"\n"+
00079 "value2 = " + value2);
00080
00081 Vector Vec1 = new Vector(1);
00082 Vector Vec2 = new Vector(1);
00083 Vec1.add(0,new Integer(value1));
00084 Vec1.trimToSize();
00085 Vec2.add(0,new Integer(value2));
00086 Vec2.trimToSize();

CS3 Java – Topic 9: Arrays (Singhal) Page 59 of 134


00087 swap4(Vec1,Vec2);
00088 value1 = ((Integer)Vec1.elementAt(0)).intValue();
00089 value2 = ((Integer)Vec2.elementAt(0)).intValue();
00090
00091 System.out.println("After calling swap4 the value of \n" +
00092 "value1 = " + value1 +"\n"+
00093 "value2 = " + value2);
00094 dbl1 = 99.999954;
00095 dbl2 = -99.203;
00096 Vec1.clear();
00097 Vec2.clear();
00098 Vec1.add(0,new Double(dbl1));
00099 Vec1.trimToSize();
00100 Vec2.add(0,new Double(dbl2));
00101 Vec2.trimToSize();
00102
00103 System.out.println("Before calling swap4 the value of \n" +
00104 "dbl1 = " + dbl1 +"\n"+
00105 "dbl2 = " + dbl2);
00106 swap4(Vec1,Vec2);
00107 dbl1 = ((Double)Vec1.elementAt(0)).doubleValue();
00108 dbl2 = ((Double)Vec2.elementAt(0)).doubleValue();
00109 System.out.println("After calling swap4 the value of \n" +
00110 "dbl1 = " + dbl1 +"\n"+
00111 "dbl2 = " + dbl2);
00112 }
00116 public static void swap1(int val1, int val2)
00117 {
00118 int temp = val1;
00119 val1 = val2;
00120 val2 = temp;
00121 }
00125 public static void swap2(int []num1, int [] num2)
00126 {
00127 int temp = num1[0];
00128 num1[0] = num2[0];
00129 num2[0] = temp;
00130 }
00134 public static void swap3(final StringBuffer S1, final StringBuffer S2)
00135 {
00136 char [] ch1 = S1.toString().toCharArray();
00137 char [] ch2 = S2.toString().toCharArray();
00138
00139 S1.setLength(ch2.length);
00140 S2.setLength(ch1.length);
00141

CS3 Java – Topic 9: Arrays (Singhal) Page 60 of 134


00142 for(int ind = 0; ind<ch2.length; ++ind)
00143 S1.setCharAt(ind, ch2[ind]);
00144
00145 for(int ind = 0; ind<ch1.length; ++ind)
00146 S2.setCharAt(ind,ch1[ind]);
00147 }
00151 public static void swap4(final Vector V1, final Vector V2)
00152 {
00155 Object Obj1 = V1.firstElement();
00156 Object Obj2 = V2.firstElement();
00157
00158 V1.clear();
00159 V2.clear();
00160
00161 V1.add(0,Obj2);
00162 V2.add(0,Obj1);
00163 V1.trimToSize();
00164 V2.trimToSize();
00165 }
00166 }//Listing 9.13

The method swap1 (L9.13#116-121) swaps the value of parameters passed to it


locally, but as shown by the output in Figure 9.29 (Lines #1 to #6), the values of
Data1 and Data2 in main remain unchanged. Therefore in Java primitives can
never be swapped by passing to a method. There is a chance however that primitives
wrapped in mutable reference types can be used for such swapping.
00001 The current values of
00002 Data1 = 10
00003 Data2 = 15
00004 After calling swap1 the value of
00005 Data1 = 10
00006 Data2 = 15
00007 Declaring two one element int arrays D1, D2
00008 The current values of
00009 D1[0] = 33
00010 D2[0] = 55
00011 After calling the swap2 values of
00012 D1[0] = 55
00013 D2[0] = 33
00014 After calling swap3 the value of
00015 Data1 = 15
00016 Data2 = 10
00017 The current values of
00018 Data1 = 1000
00019 Data2 = -22222222
00020 After calling swap3 the value of

CS3 Java – Topic 9: Arrays (Singhal) Page 61 of 134


00021 Data1 = -22222222
00022 Data2 = 1000
00023 The current values of
00024 dbl1 = 99.999954
00025 dbl2 = -99.203
00026 After calling swap3 the value of
00027 dbl1 = -99.203
00028 dbl2 = 99.999954
00029 Before calling swap3 the value of
00030 C1 = Mary
00031 C2 = John
00032 After calling swap3 the value of
00033 C1 = John
00034 C2 = Mary
00035 Before calling swap4 the value of
00036 value1 = -77
00037 value2 = 900
00038 After calling swap4 the value of
00039 value1 = 900
00040 value2 = -77
00041 Before calling swap4 the value of
00042 dbl1 = 99.999954
00043 dbl2 = -99.203
00044 After calling swap4 the value of
00045 dbl1 = -99.203
00046 dbl2 = 99.999954
//FIG. 9.29
In Java arrays are the mutable reference types in the sense that due to random
access, the members of an array can be written into by the method getting array as
an argument. The common logic in success of other three swap methods (swap2,
swap3, and swap4) is based on the following procedural facts.
• Wrap the primitive or objects to be swapped in a mutable reference type.
• The swap method swaps the mutable arguments passed to it.
• The swapped objects are now available to the caller method. And if desired
then the primitives that were wrapped into objects can now be unwrapped to
their original state.

Method Swap2
We illustrate above logic by exemplifying the method swap2, which accepts two
arrays, both with length one as arguments.
//watch PowerPoint presentation swap2.ppt now.
The main declares int arrays D1 and D2, each of length one and former storing a
value of 33, and later a value of 55 (L9.13#17-18, see also Figure 9.30A).

CS3 Java – Topic 9: Arrays (Singhal) Page 62 of 134


FIG. 9.30A
The values of D1[0] and D2[0] before passing to method swap2 are printed
(L9.13#19-21). In method swap2 the copies of D1 and D2 are called num1 and num2
(FIG 9.30B), which are exact copies of D1 and D2.

CS3 Java – Topic 9: Arrays (Singhal) Page 63 of 134


FIG. 9.30B
In first line of swap2, we save the value stored in num1[0] in a local variable temp
(Figure 9.30C).

FIG. 9.30C

CS3 Java – Topic 9: Arrays (Singhal) Page 64 of 134


Since the value of num1[0] has been saved, it is safe to copy the value of num2[0]
into num1[0] (Figure 9.30D).

FIG. 9.30D
This changes num1[0] value to 55. Finally the original value of num1[0] saved in
temp is copied into num2[0] (Figure 9.30E).

CS3 Java – Topic 9: Arrays (Singhal) Page 65 of 134


FIG. 9.30E
The swap is now complete. After the control is returned to main the values stored in
D1[0] and D2[0] have been swapped compared to the values stored before the call to
swap2 (Figure 9.30F).

CS3 Java – Topic 9: Arrays (Singhal) Page 66 of 134


FIG. 9.30F
Therefore the main prints (L9.13#23-25) the new swapped values stored in D1[0]
and D2[0] (F9.29#12-13).

Understand the general principle followed by the technology used by method swap2.
The data to be swapped are wrapped into objects, which are mutable, and then
references to these mutable objects are passed to swap method, which alters the
objects and the caller method then gets them in altered state. The principle
embedded in swap2 would swap any data type in Java. However, the limitation the
method has is that one must define a different swap method for different data type –
in other words the swap2 is not generic. A generic version of swap2 is designed in
swap3, which uses two StringBuffer objects as argument.

Method swap3
Strings in Java are immutable. Once its constructor constructs a Java String, it can
never be altered. However, the objects of class java.lang.StringBuffer are mutable.
A StringBuffer object can store a Java String and then allow modification on it.
Unfortunately the StringBuffer objects cannot be concatenated using the plus (+)
operator. Because StringBuffer is mutable, its object passed to a method allows the
method to alter it. Table 9.4 shows summary of important constructors and methods
of class java.lang.StringBuffer.

CS3 Java – Topic 9: Arrays (Singhal) Page 67 of 134


Constructor Summary For class StringBuffer
StringBuffer()
Constructs a string buffer with no characters in it and an initial capacity of
16 characters.
StringBuffer(int length)
Constructs a string buffer with no characters in it and an initial capacity
specified by the length argument.
StringBuffer(String str)
Constructs a string buffer so that it represents the same sequence of
characters as the string argument; in other words, the initial contents of the string
buffer is a copy of the argument string.
Table 9.4A
The three StringBuffer constructors can create an object of default size (16
characters), an object of user-defined length, or a StringBuffer object wrapping the
String passed to it. Table 9.4B shows the important methods in class StringBuffer.
Method Summary For Class StringBuffer
StringBuffer append(param P)
This overloaded method appends the string representation of
the param p argument to the string buffer. param can be of
following types: boolean, char, double, float, int, long, Object,
String, StringBuffer, and char[ ].
StringBuffer append(char[] str, int offset, int len)
Appends the string representation of a subarray of the char
array argument to this string buffer.
int capacity()
Returns the current capacity of the String buffer.
char charAt(int index)
The specified character of the sequence currently represented
by the string buffer, as indicated by the index argument, is
returned.
StringBuffer delete(int start, int end)
Removes the characters in a substring of this StringBuffer.
StringBuffer deleteCharAt(int index)
Removes the character at the specified position in this
StringBuffer (shortening the StringBuffer by one character).
void ensureCapacity(int minimumCapacity)
Ensures that the capacity of the buffer is at least equal to the
specified minimum.
void getChars(int srcBegin, int srcEnd, char[] dst,
int dstBegin)

CS3 Java – Topic 9: Arrays (Singhal) Page 68 of 134


Characters are copied from this string buffer into the
destination character array dst.
int indexOf(String str)
Returns the index within this string of the first occurrence of
the specified substring.
int indexOf(String str, int fromIndex)
Returns the index within this string of the first occurrence of
the specified substring, starting at the specified index.
StringBuffer insert(int offset, param p)
Inserts the string representation of the param p argument into
this string buffer. The param can be of following type: boolean,
char, double, float, int, long, Object, String and char [ ]. The
insertion begins at index offset in StringBuffer. That means that
offset value must be greater than zero but smaller than the length of
StringBuffer.
StringBuffer insert(int index, char[] str, int offset, int len)
Inserts the string representation of a subarray of the str
array argument into this string buffer.
int lastIndexOf(String str)
Returns the index within this string of the rightmost
occurrence of the specified substring.
int lastIndexOf(String str, int fromIndex)
Returns the index within this string of the last occurrence of
the specified substring.
int length()
Returns the length (character count) of this string buffer.
StringBuffer replace(int start, int end, String str)
Replaces the characters in a substring of this StringBuffer
with characters in the specified String.
StringBuffer reverse()
The character sequence contained in this string buffer is
replaced by the reverse of the sequence.
void setCharAt(int index, char ch)
The character at the specified index of this string buffer is set
to ch.
void setLength(int newLength)
Sets the length of this String buffer.
CharSequence subSequence(int start, int end)
Returns a new character sequence that is a subsequence of
this sequence.
String substring(int start)
Returns a new String that contains a subsequence of
characters currently contained in this StringBuffer.The substring

CS3 Java – Topic 9: Arrays (Singhal) Page 69 of 134


begins at the specified index and extends to the end of the
StringBuffer.
String substring(int start, int end)
Returns a new String that contains a subsequence of
characters currently contained in this StringBuffer.
String toString()
Converts to a string representing the data in this string
buffer.
Table 9.4B
Examination of list of member methods of StringBuffer class indicates two types of
mutators available. Methods such as append, insert, delete, deleteCharAt, replace,
and reverse return a StringBuffer object, although the returned object is same as
the caller object. void method setCharAt(int index, char ch) replaces the character
stored at index by character ch in its caller. One of the algorithms ALG 9.1 for
swap3 using two StringBuffer objects to be swapped is given below. A shorter
algorithm (shown in Listing in Appendix 9.1A) is now available.
ALG 9.1
public static void swap3(StringBuffer S1, StringBuffer S2)
1. Declare char array reference ch1 and set it to point to the array of the
characters in the StringBuffer S1.
2. Declare char array reference ch2 and set it to point to the array of the
characters in StringBuffer S2.
3. Set the length of StringBuffer S1 equal to the length of array ch2.
4. Set the length of StringBuffer S2 equal to the length of array ch1.
5. Copy all characters from array ch2 into the StringBuffer S1.
6. Copy all the characters from array ch1 into the StringBuffer S2.
In ALG 9.1 the steps one and two are coded by first calling the toString method of
StringBuffer class, which converts it to a String, and then calling toCharArray
method of String class, which returns an array of character for the caller String.
Once we have two character arrays – each storing the characters in the original
StringBuffer objects – we can set the desired lengths of these objects. The method
setLength from StringBuffer class changes the number of spaces available in its
object to the value passed to it. Since values of array ch2 are to be copied into S1, we
set the length of S1 equal to the length of array ch2. Similar procedure is repeated to
set the length of S2. Loops are then used to copy character arrays ch2 and ch1 into
S1 and S2 respectively using the StringBuffer class method setCharAt. The Figure
9.29 shows the results of call to method swap3 (F9.29#20-34).

In order to swap primitives the values passed to swap3 are first converted into an
object of their wrapper class, and then the StringBuffer forms of these objects are
passed to the swap3 method. For example (L9.13#34), Data1 has a value of 1000. It
is wrapped into a StringBuffer object as follows (L9.13#40) (Figure 9.31):

CS3 Java – Topic 9: Arrays (Singhal) Page 70 of 134


1. Wraps the primitive (int)
Data1 into it wrapper
Integer.

C1 = new StringBuffer(new Integer(Data1).toString());

2. Returns the String


3. Wraps the String form of Integer object form of Integer object.
into a StringBuffer object.

FIG. 9.31
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
First the primitive Data1 is wrapped into int wrapper Integer by calling Integer
class constructor and passing Data1 to it as an argument. Then toString method of
class Integer returns a String version of wrapper Integer. Finally the String version
of Data1 wrapped into an Integer is passed to the constructor of StringBuffer class
to create a StringBuffer object C1 in Figure 9.31. A process that reverse engineers a
StringBuffer object back into a primitive would be needed after the call to swap3 is
finished.

Action of method Swap3


//Go to PowerPoint Swap3.ppt
Before calling the Swap3 in the caller method two StringBuffer objects to be
swapped are created. Figure 9.32A shows two such objects C1 and C2 containing
Strings Marcy and John respectively.

CS3 Java – Topic 9: Arrays (Singhal) Page 71 of 134


FIG. 9.32A
Then the swap3 method is called. At that point the control of program is shifted to
the swap3 method and execution of its first line results in creation of copies of
references C1 and C2, as S1 and S2 (Figure 9.32B).

CS3 Java – Topic 9: Arrays (Singhal) Page 72 of 134


FIG. 9.32B
Notice that references C1 and S1 share the same pointee. It is true of references C2
and S2 as well. To save the contents of pointees of S1 and S2, we need to copy the
contents of StringBuffer objects S1 and S2 into two character arrays. The copying is
done first by getting a String version of StringBuffer object S1 by calling its member
method toString. Then the String thus returned calls its member method
toCharArray, which returns the contents of the String as a character array. Thus a
character array ch1 is created which has the same content as StringBuffer S1.
Therefore Marcy is copied into the array ch1. Similar process is followed to copy the
contents of StringBuffer S2 into the char array Ch2. At the end of line three in
swap3, the memory map of its stack and heap variables is shown by Figure 9.32C.

CS3 Java – Topic 9: Arrays (Singhal) Page 73 of 134


FIG. 9.32C
In above Figure S1, S2, Ch1, Ch2 are on stack, and all other objects including the
char arrays are on heap.

Since eventually the contents of S1 and S2 must be swapped, it would involve


copying “John” into the space in which “Marcy” is and vice versa. However we
must ascertain that number of characters in pointee of reference S1 is equal to the
length of character array ch2, which contains “John”. SetLength method of class
StringBuffer applied to object S1 reduces the number of characters in S1, equal to
length of Ch2 array, which is four. This results in deletion of last character in
Marcy. Similarly, the setLength method applied to object S2 expands its storage to
make it equal to the length of array Ch1. This results in adding an extra space after
the last character n in John. Now both StringBuffer objects have their inner spaces
adjusted equal to the array of characters that would be copied into them. Figure
9.32D shows the pointees of S1 and S2 with altered storage lengths.

CS3 Java – Topic 9: Arrays (Singhal) Page 74 of 134


FIG. 9.32D
The for loop and StringBuffer method setCharAt copies character by character the
contents of the array Ch2, into the StringBuffer object S1. After the execution of
line seven John is copied into the StringBuffer object S1 (Figure 9.32E). Then
contents of the array ch1 containing Marcy are copied into the StringBuffer object
S2. The swap process at this point is complete. Notice that methods used do not
change addresses stored in S1 and S2 (Figure 9.32E).

CS3 Java – Topic 9: Arrays (Singhal) Page 75 of 134


FIG. 9.32E
After the control is returned to the caller method the contents of C1 and C2 have
been swapped. Figure 9.32F shows the before and after picture in the caller method.

CS3 Java – Topic 9: Arrays (Singhal) Page 76 of 134


FIG. 9.32F
The advantage of using Swap3 over swap2 is that Swap3 is generic and can be used
for any data type, as long as the method toString, which returns the String version
of the objects to be swapped, is available, which is true of all primitive wrapper
classes, String, and StringBuffer. The use of swap3 does have a small learning curve,
however, as the user must learn to first engineer their primitives into StringBuffer
objects and then reverse engineer them back into primitives. The process of reverse
engineering StringBuffer back to primitive is shown in Listing 9.13 (Lines #44-45,
#58-59). For example the primitive int Data1 engineered into a StringBuffer object
in Figure 9.31 can be reverse engineered into primitive Data1 as follows:

Data1 = Integer.parseInt (C1.toString( ) );


In above code line, first the StringBuffer C1 calls its toString method to get the
String version of C1, which is then parsed by static method parseInt to return the
primitive value stored in C1 and assign that to storage location Data1. One
disadvantage of swap3 compared to non-generic method swap2 is that it creates
intermediate arrays during the method call, increasing the memory usage overhead.
This limitation can be avoided by client’s judicious use of next swapping method
swap4. The method swap4 uses objects of Java class java.util.Vector as arguments.

CS3 Java – Topic 9: Arrays (Singhal) Page 77 of 134


Method swap4 and Vector class
swap4 is a generic swap method like swap3, with a simpler algorithm. It uses a Java
class java.util.Vector, which we discuss next. As you have noticed that arrays in
Java, once created, have fixed length. At times we however need contiguous storage
construct, which can grow or shrink as we add more elements to it or remove
elements from it. The class Vector in java.util package is such a construct. Table
9.5A shows the fields in the Vector class.
Summary of Fields for class java.util.Vector
protected capacityIncrement
int The amount by which the capacity of the vector is automatically
incremented when its size becomes greater than its capacity.
protected elementCount
int The number of valid components in this Vector object.
protected elementData
Object[] The array buffer into which the components of the vector are
stored.
Table 9.5A
The Vector class has three protected7 fields, capacityIncrement, elementCount, and
elementData; the latter being an array of type java.lang.Object class. The elements
stored inside the object Vector are stored in its array called elementData. The field
elementCount keeps track of as to how many cells of array elementData are filled.
The field capacityIncrement stores the number by which the array elementData is to
be expanded, once it is filled and more elements are added to it. Figure 9.33A shows
schematically an object Vector class with its fields.

7
We shall discuss protected access in the next chapter. Basically the protected members are available
to the class declaring them as well as to its subclasses.

CS3 Java – Topic 9: Arrays (Singhal) Page 78 of 134


FIG. 9.33A
Table 9.5B gives the summary of constructors for Vector class.
Summary of Constructors for class java.util.Vector
Vector()
Constructs an empty vector so that its internal data array has size 10 and its
standard capacity increment is zero.
Vector(Collection c)
Constructs a vector containing the elements of the specified collection, in the
order they are returned by the collection's iterator.
Vector(int initialCapacity)
Constructs an empty vector with the specified initial capacity and with its
capacity increment equal to zero.
Vector(int initialCapacity, int capacityIncrement)
Constructs an empty vector with the specified initial capacity and capacity
increment.
Table 9.5B
The argument-less constructor constructs a Vector object to which up to ten
elements can be added with out an increment in the capacity. When more elements
are added, then each time a new Vector with added element is constructed. This
may however slow down the overall operation of adding elements to the Vector.

CS3 Java – Topic 9: Arrays (Singhal) Page 79 of 134


Therefore argument-less constructor is best used for those situations where one
would not need to add more than ten elements to a Vector.

The constructor Vector (int initialCapacity), allows user to predefine the initial
capacity. This is best used in those situations where user knows in advance as to how
many elements would be stored in the Vector, thus setting initialCapacity equal or
slightly larger than that.

The constructor Vector(int initialCapacity, int capacityIncrement) is optimizable


for most situations. If we know the number of elements to be added right after
creation of the Vector, we set initialCapacity equal to that. If we know as to how
many elements we would add at a time in later processing, we can specify
capacityIncrement equal to that.

Vector class has a long list of member methods and Table 9.5C summarizes them.
Summary of Methods for class java.util.Vector
void add(int index, java.lang.Object element)
Inserts the specified element at the specified
position in this Vector.
boolean add(java.lang.Object o)
Appends the specified element to the end of this
Vector.
boolean addAll(java.util.Collection c)
Appends all of the elements in the specified
Collection to the end of this Vector, in the order that they
are returned by the specified Collection's Iterator.
boolean addAll(int index, java.util.Collection c)
Inserts all of the elements in in the specified
Collection into this Vector at the specified position.
void addElement(java.lang.Object obj)
Adds the specified component to the end of this
vector, increasing its size by one.
int capacity()
Returns the current capacity of this vector.
void clear()
Removes all of the elements from this Vector.
java.lang.Object clone()
Returns a clone of this vector.
boolean contains(java.lang.Object elem)
Tests if the specified object is a component in this
vector.
boolean containsAll(java.util.Collection c)
Returns true if this Vector contains all of the

CS3 Java – Topic 9: Arrays (Singhal) Page 80 of 134


elements in the specified Collection.
void copyInto(java.lang.Object[] anArray)
Copies the components of this vector into the
specified array.
java.lang.Object elementAt(int index)
Returns the component at the specified index.
java.util.Enumeration elements()
Returns an enumeration of the components of this
vector.
void ensureCapacity(int minCapacity)
Increases the capacity of this vector, if necessary, to
ensure that it can hold at least the number of components
specified by the minimum capacity argument.
boolean equals(java.lang.Object o)
Compares the specified Object with this Vector for
equality.
java.lang.Object firstElement()
Returns the first component (the item at index 0) of
this vector.
java.lang.Object get(int index)
Returns the element at the specified position in this
Vector.
int hashCode()
Returns the hash code value for this Vector.
int indexOf(java.lang.Object elem)
Searches for the first occurence of the given
argument, testing for equality using the equals method.
int indexOf(java.lang.Object elem, int index)
Searches for the first occurence of the given
argument, beginning the search at index, and testing for
equality using the equals method.
void insertElementAt(java.lang.Object obj, int index)
Inserts the specified object as a component in this
vector at the specified index.
boolean isEmpty()
Tests if this vector has no components.
java.lang.Object lastElement()
Returns the last component of the vector.
int lastIndexOf(java.lang.Object elem)
Returns the index of the last occurrence of the
specified object in this vector.
int lastIndexOf(java.lang.Object elem, int index)
Searches backwards for the specified object,

CS3 Java – Topic 9: Arrays (Singhal) Page 81 of 134


starting from the specified index, and returns an index to
it.
java.lang.Object remove(int index)
Removes the element at the specified position in
this Vector.
boolean remove(java.lang.Object o)
Removes the first occurrence of the specified
element in this Vector If the Vector does not contain the
element, it is unchanged.
boolean removeAll(java.util.Collection c)
Removes from this Vector all of its elements that
are contained in the specified Collection.
void removeAllElements()
Removes all components from this vector and sets
its size to zero.
boolean removeElement(java.lang.Object obj)
Removes the first (lowest-indexed) occurrence of
the argument from this vector.
void removeElementAt(int index)
Deletes the component at the specified index.
protected void removeRange(int fromIndex, int toIndex)
Removes from this List all of the elements whose
index is between fromIndex, inclusive and toIndex,
exclusive.
boolean retainAll(java.util.Collection c)
Retains only the elements in this Vector that are
contained in the specified Collection.
java.lang.Object set(int index, java.lang.Object element)
Replaces the element at the specified position in
this Vector with the specified element.
void setElementAt(java.lang.Object obj, int index)
Sets the component at the specified index of this
vector to be the specified object.
void setSize(int newSize)
Sets the size of this vector.
int size()
Returns the number of components in this vector.
java.util.List subList(int fromIndex, int toIndex)
Returns a view of the portion of this List between
fromIndex, inclusive, and toIndex, exclusive.
java.lang.Object[] toArray()
Returns an array containing all of the elements in
this Vector in the correct order.

CS3 Java – Topic 9: Arrays (Singhal) Page 82 of 134


java.lang.Object[] toArray(java.lang.Object[] a)
Returns an array containing all of the elements in
this Vector in the correct order; the runtime type of the
returned array is that of the specified array.
java.lang.String toString()
Returns a string representation of this Vector,
containing the String representation of each element.
void trimToSize()
Trims the capacity of this vector to be the vector's
current size.
Table 9.5C
We discuss the methods in Vector class by dividing them into the following
categories: Methods to add elements to the Vector, methods to remove elements
from the Vector, methods to perform queries on the Vector, and other methods
which do not fit in above three categories.

Methods to add elements to the Vector


Primitives cannot be added to the Vector. All elements added to the Vector must be
java reference types. That means that elements added to the Vector can be classes,
array references, and interface types (See Figure 9.9). Generically we can say that
only objects of type java.lang.Object can be added to the Vector. This is not a
problem because all Java objects are of that type.

Method add(int index, Object element), adds the object element at the index passed
to it. The index can neither be negative, nor larger than the size of the Vector. If
there already is an element at the location index, then that and all lagging elements
are shifted to the higher index by one. Assume that a Vector Vec1 has the following
elements before add method is called.
Vector Vec1
[ “John”, “Mary”, “Ted”, “Adam”, “Tom”, “Pete”]

Then if we call the method add as follows:


Vec1 after the call
Vec1.add(3, “Marcy”); Vac1.add(3,”Marcy”);

the vec1 will change as follows:

[ “John”, “Mary”, “Ted”, “Marcy” ,“Adam”, “Tom”, “Pete”]

Method insertElementAt (Object obj, int index) works exactly like the method
add(int index, Object element). No elements are ever overwritten or removed in the
process of using methods with name add in them.

CS3 Java – Topic 9: Arrays (Singhal) Page 83 of 134


Methods add(Object o) and addElement(Object obj) work in identical fashion,
adding the Object to the end of the Vector, and increasing its size by one. For
example if we make the following two calls on the Vec1 created and expanded
previously, we would get a Vector shown in Figure 9.33B with two extra names
“Jefferson” and “Jeff” added to the end of the Vector.
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Vec1.add(Jefferson”);
Vec1.addElement(Jeff”);

[ “John”, “Mary”, “Ted”, “Marcy” ,“Adam”, “Tom”, “Pete”,


“Jefferson, “Jeff”]
Vec1 expanded by calls to add
and addElement
FIG. 9.33B
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Overloaded versions of two methods addAll add Collection of Java elements to a
Vector and its discussion must wait until we have learned more about Java interface
called Collection. The method Object set(int index, Object element), replaces
the member at location index by the object element and returns the displaced
member. The method void setElementAt (Object obj, int index) works
exactly like method set, except that the displaced member is not returned. For
example the call in Vector Vec1 shown in Figure 9.33B shown by the code snippet
below would print the name Ted, and replace Ted by Margo.
Replaces “Ted” with
System.out.println (Vec1.set(2, “Margo”)); Margo and prints “Ted”
on console.

Methods to remove elements from the Vector


In process of removing elements from a Vector we can remove all elements from it,
remove elements in certain index range, remove element at particular index, remove
the first occurrence of certain key, or remove elements belonging to a certain
collection from the Vector.

Methods clear and removeAllElements work exactly in the same fashion and
remove all elements from a Vector thus setting the size to zero. For example, a call
like Vec1.clear( ) on Vector in Figure 9.33B would result in deletion of all names and
a Vector of size zero.

Method Object remove(int index) removes the member at location index and
returns it to caller as a Java Object. On the other hand the method
void removeElementAt(int index) simply removes the element at location index.

CS3 Java – Topic 9: Arrays (Singhal) Page 84 of 134


Method boolean remove(Object o) or
boolean removeElement(Object obj) remove the first occurrence of the Object
o or obj from the caller Vector and return true if element was in the Vector, else
return false. The method boolean removeAll (Collection c) , when called on a
Vector attempts to remove all elements that match with the Collection c, and
returns true if operation was successful. Detailed understanding of this method must
await discussion of Collection interface.

Methods to query a Vector object


The method public int capacity( ) returns the maximum number of elements that
Vector can hold before next expansion. Method boolean contains(Object elem)
returns a true if Vector contains the object elem, otherwise it returns false. Method
boolean containsAll (Collection c) performs the query similar to contains,
except now it looks for the presence of entire Collection c in the Vector. The method
int indexOf (Object elem) searches the first presence of the object elem in the
Vector and if found returns its index. The method
int lastIndexOf (Object elem) searches the last occurrence of object elem in the
Vector and returns its index. If Vector is a mathematical set then if object elem is
present in the Vector then both methods indexOf and lastIndexOf would return the
same value. For example the following two code lines applied to the Vector Vec1 of
Figure 9.33B would print the same value of five on console.
Both will print
System.out.println (Vec1.indexOf (“Tom”)); 5 on console.
System.out.println (Vec1.lastIndexOf (“Tom”)); Vec1 is
described in
Figure 9.33B

Method int indexOf (Object elem, int index) starts to search forward for the
object elem from the location index, and if found returns the index of its first
occurrence. Obviously the returned value would be larger than the value of index
passed to the method. Method int lastIndexOf (Object elem, int index)
searches backwards starting from location index in the vector and if found returns
the index of first match. If found then returned value would be lower than the value
index passed to the method.

Method boolean equals (Object O) returns a true if contents of O are identical


to the caller object, otherwise it returns false. Method boolean isEmpty ( )
returns a true if Vector has zero size meaning it has no elements in it, otherwise it
returns false. Method public int size( ) returns the number of elements in the
Vector at the time of call. For example the following line applied to Vector Vec1 of
Figure 9.33B would print a value 9 on the console.

CS3 Java – Topic 9: Arrays (Singhal) Page 85 of 134


Will print 9 on console.
System.out.println (Vec1.size( ) ); Vec1 is described in
Figure 9.33B.

The method String toString( ) would return a String representation of the caller
Vector. For example the code snippet below would print all the names in the Vector
separated by comma and enclosed in square brackets.
Will print the following on console
String Str = Vec1.toString ( );
[John, Mary, Ted, Marcy, Adam,
System.out.println (Str); Tom, Pete, Jefferson, Jeff]
Vec1 is described in Figure 9.33B.

Method Object clone( ) would return a clone of caller Vector. This works exactly
the way clone method for array shown in Listing 9.5 works. The method
Object[ ] toArray ( ) returns an array of elements in the caller Vector in the
order in which they are arranged in the Vector. Method
Object elementAt (int index) returns the member of Vector at the location
index. On the other hand the method Object firstElement ( ) returns the element
at index zero in the Vector. The method Object lastElement ( ) returns the
element at the index size-1 in the Vector, where size indicates the number of
elements in the Vector.

Question: What will be printed by the following code lines, applied to


Vector Vec1 of Figure 9.33B?

System.out.println (Vec1.firstElement( ));


System.out.println (Vec1.lastElement( ));

Miscellaneous Methods for the Vector class


Method void trimToSize ( ) makes the capacity of the caller Vector equal to its
size or equal to number of elements in it. This means that all the “empty” cells after
the last filled cell are deleted. Method void ensureCapacity (int minCapacity)
ascertains that the caller Vector at least has the capacity equal to the minCapacity.
The capacity is unchanged if it is already larger than minCapacity. Method
void setSize (int newSize) changes the size of the Vector to newSize. If newSize
is smaller than the current size then all the elements from index newSize–1 to
size–1 are deleted. On the other hand if newSize is larger than the current size then
all the elements from index size-1 to newSize-1 are filled with null value. This
method must be used with great caution as it can either delete the
elements from the Vector or add null elements in it!

CS3 Java – Topic 9: Arrays (Singhal) Page 86 of 134


Discussion of Method Swap4
The algorithm of swap4 (ALG 9.2) is deceptively simple.
ALG 9.2
public static void swap4(final Vector V1, final Vector V2)
1. Set contents of Object Obj1 equal to the contents of first element in Vector
V1.
2. Set contents of Object Obj2 equal to the contents of first element in Vector
V2.
3. Delete all elements from Vector V1.
4. Delete all elements from Vector V2.
5. Add Obj2 to the location zero in Vector V1.
6. Add Obj1 to the location zero in Vector V2.
7. Trim the capacity of Vector V1 equal to its size.
Repeat the step seven for Vector V2.
The algorithm first copies the contents of the first elements in both Vectors into
stand-alone single Objects Obj1 and Obj2, and then after clearing both Vectors,
swap copies the Obj2 into first element of V1 and Obj1 into the same location in V2.
We now show the dynamics of call to swap4 and the action in it.

Before calling the swap4, the caller method, two int variables value1 and value2 are
declared (Figure 9.34A) (Also see lines #75 -76 of Listing 9.13).

FIG. 9.34A
Two vectors Vec1 and Vec2 are then created and value1 and value2 wrapped in
their respective Integer wrappers are added to the location zero into Vec1 and Vec2
respectively (Figure 9.34B) (See also lines #81-83 & #85 in Listing 9.13).

CS3 Java – Topic 9: Arrays (Singhal) Page 87 of 134


FIG. 9.34B
Notice that add method of Vector class used here takes two arguments. The first
argument is the index of the location, where the element will be added. Caller sets
that to zero, as only one element is to be added to the Vector. Second argument is
the object to be added. (Alternatively, we could have just used method add (Object
O), which would have had the same affect). All Java reference types are also
Objects; therefore instance of an Integer class can be added directly. The values
stored in Vec1 and Vec2 are only the addresses of actual objects8 on heap. When
swap4 method is called then control is transferred to the swap4 method, and copies
of Vec1 and Vec2 are passed to the method (Figure 9.34C) (Also see Line#151 in
Listing 9.13). The copies of Vec1 and Vec2 in swap4 are called V1 and V2.

8
Recall that Vector can never store primitives.

CS3 Java – Topic 9: Arrays (Singhal) Page 88 of 134


FIG. 9.34C
Notice that addresses stored in V1 and V2 are same as in Vec1 and Vec2
respectively. Now the swap4 makes copies of first element stored in Vec1 and Vec2
to save them (Figure 9.34D) (Also see Line #155-156 in Listing 9.13).

FIG. 9.34D

CS3 Java – Topic 9: Arrays (Singhal) Page 89 of 134


Since we must swap the values stored at index zero in both vectors, the next step is
to clear (delete) all elements from both vectors. The call to clear methods does that
(Figure 9.34E) (See also Lines #158-159 in Listing 9.13).

FIG. 9.34E
Notice that clear method only deletes the contents in the storage locations whose
addresses are stored in the Vector. The storage locations themselves are not
“garbage collected”. The locations whose addresses are stored in the Vector are
available to store new objects. Then in order to perform the swap, the contents of
Obj2 are added to the first location in V1, and that of Obj1 to the corresponding
location in V2 (Figure 9.34F) (See also Lines #161-162 in Listing 9.13).

CS3 Java – Topic 9: Arrays (Singhal) Page 90 of 134


FIG. 9.34F
The last two lines V1.trimToSize ( ) and V2.trimToSize( ), would be useful when
capacity of Vector is larger than its size. They just reduce the storage space the
Vector takes up. In the present example, they do not alter anything. The swap is
essentially complete now and the control is transferred to the caller method. In
caller method, primitives are extracted from the objects stored in Vec1 and Vec2
(Figure 9.34G) (See also Line#88-89 in Listing 9.13).

CS3 Java – Topic 9: Arrays (Singhal) Page 91 of 134


FIG. 9.34G
In extraction process, first the method Object elementAt (int index) of Vector
class returns the object stored at location zero in Object form. This Object is cast
back into Integer form by using the casting operator (Integer). Then the
int intValue ( ) method of Integer class is called to return the int stored inside the
Integer object. Using this process the value1 stores 900 and value2 stores –77.
Therefore the values of two int variables are swapped now. Figure 9.34H shows the
situation in caller method before and after the swap.

CS3 Java – Topic 9: Arrays (Singhal) Page 92 of 134


FIG. 9.34H
Notice that the addresses stored in Vec1 and Vce2 are never altered. Only the
contents of storage location of their pointees are altered. The output lines #35-46 in
Figure 9.29 confirm the success of swap4 in swapping the contents of objects passed
to it.

Swapping the two members of an array


In many sorting algorithms, the programmer needs to swap values stored in two
members of an array. One can of course use one of the methods, swap2, swap3, or
swap4 for that. However, it is convenient to pass the entire array and the values of
indices of array location, whose contents are to be swapped. Since arrays are
mutable, such alteration is reflected in the caller method. Listing 9.14 shows the
code for such a swaps. In this listing swap5 is usable only for int arrays, whereas the
swap6 can be used for all primitives and String data type. Though swap6 can be
extended to support user defined data types, we believe that, for such applications, it
would either be convenient to write a version of swap5 or use swap4 (discussed
earlier), which works for all data types.
00001
00002 public class SwapArrays
00003 {
00004 public static void main (String[] args)
00005 {
00006 int [] arr = {rnd(),rnd(),rnd(),rnd(),rnd(),rnd(),rnd(),};

CS3 Java – Topic 9: Arrays (Singhal) Page 93 of 134


System.out.println("Before swapping values at index two and five, the array is:");
00008
00009 for(int ind=0; ind<arr.length; ++ind)
00010 System.out.print(arr[ind] + " ");
00011 System.out.println();
00012 System.out.println("Calling the method swap5");
00013 swap5(2, 5, arr);
System.out.println("After swapping values at index two and five, the array is:");
00015
00016 for(int ind=0; ind<arr.length; ++ind)
00017 System.out.print(arr[ind] + " ");
00018 System.out.println();
00019
00020 int [] arr2 = {rnd(),rnd(),rnd(),rnd(),rnd(),rnd(),rnd(),};
System.out.println("Before swapping values at index 1 and 4, the array is:");
00022
00023 for(int ind=0; ind<arr2.length; ++ind)
00024 System.out.print(arr2[ind] + " ");
00025 System.out.println();
00026
00027
00028 System.out.println("Calling the method swap6");
00029 swap6(1,4,arr2);
00030 System.out.println("After swapping values at index 1 and 4, the array is:");
00031
00032 for(int ind=0; ind<arr2.length; ++ind)
00033 System.out.print(arr2[ind] + " ");
00034 System.out.println();
00035
String [] Str = {"John", "Mary", "Adam", "Ted", "Nina", "Ellen", "Bertha"};
System.out.println("Before swapping values at index 1 and 6, the String array is:");
00038
00039 for(int ind=0; ind<Str.length; ++ind)
00040 System.out.print(Str[ind] + " ");
00041 System.out.println();
00042
00043 System.out.println("Calling the method swap6");
00044 swap6(1,6,Str);
System.out.println("After swapping values at index 1 and 6, the String array is:");
00046
00047 for(int ind=0; ind<Str.length; ++ind)
00048 System.out.print(Str[ind] + " ");
00049 System.out.println();
50 }

CS3 Java – Topic 9: Arrays (Singhal) Page 94 of 134


00054 public static void swap5(int num1, int num2, int [ ] iarr)
00055 {
00056 int temp = iarr[num1];
00057 iarr[num1] = iarr[num2];
00058 iarr[num2] = temp;
00059 }
00063 public static void swap6(int num1, int num2, Object Obj_Arr)
00064 {
00065 if(Obj_Arr instanceof int [])
00066 {
00067 int [] arr = (int [ ])(Obj_Arr);
00068 int temp = arr[num1];
00069 arr[num1] = arr[num2];
00070 arr[num2] = temp;
00071 }
00072 else if(Obj_Arr instanceof byte [])
00073 {
00074 byte [] arr = (byte [ ])(Obj_Arr);
00075 byte temp = arr[num1];
00076 arr[num1] = arr[num2];
00077 arr[num2] = temp;
00078 }
00079 else if(Obj_Arr instanceof char [])
00080 {
00081 char [] arr = (char [ ])(Obj_Arr);
00082 char temp = arr[num1];
00083 arr[num1] = arr[num2];
00084 arr[num2] = temp;
00085 }
00086 else if(Obj_Arr instanceof short [])
00087 {
00088 short [] arr = (short [ ])(Obj_Arr);
00089 short temp = arr[num1];
00090 arr[num1] = arr[num2];
00091 arr[num2] = temp;
00092 }
00093 else if(Obj_Arr instanceof float [])
00094 {
00095 float [] arr = (float [ ])(Obj_Arr);
00096 float temp = arr[num1];
00097 arr[num1] = arr[num2];
00098 arr[num2] = temp;
00099 }
00100 else if(Obj_Arr instanceof long [])
00101 {
00102 long [] arr = (long [ ])(Obj_Arr);

CS3 Java – Topic 9: Arrays (Singhal) Page 95 of 134


00103 long temp = arr[num1];
00104 arr[num1] = arr[num2];
00105 arr[num2] = temp;
00106 }
00107 else if(Obj_Arr instanceof double [])
00108 {
00109 double [] arr = (double [ ])(Obj_Arr);
00110 double temp = arr[num1];
00111 arr[num1] = arr[num2];
00112 arr[num2] = temp;
00113 }
00114 else if(Obj_Arr instanceof boolean [])
00115 {
00116 boolean [] arr = (boolean [ ])(Obj_Arr);
00117 boolean temp = arr[num1];
00118 arr[num1] = arr[num2];
00119 arr[num2] = temp;
00120 }
00121 else if(Obj_Arr instanceof String [])
00122 {
00123 String [] arr = (String [ ])(Obj_Arr);
00124 String temp = arr[num1];
00125 arr[num1] = arr[num2];
00126 arr[num2] = temp;
00127 }
00128 }
00132 public static int rnd()
00133 {
00134 return (int)(10*Math.random ( ));
00135 }
00136
00137 }//Listing 9.14
Discussion of swap5
Method swap5 takes the two integers, which represent the indices of locations in the
array whose contents are to be swapped (L9.14#54). If these indices are num1 and
num2 and the array passed to the method is iarr, then first the value of element at
index num1 is saved in a temporary variable temp (L9.14#56). Then value of
element at location num2 is copied into location num1 (L9.14#57). Finally the value
saved in temp is copied into the location at num2 (L9.14#58).

Discussion of swap6
swap6 is usable for all primitive and String arrays (L9.14#63-128). It can be
modified to work for user defined data types. The header of method swap6 is given
below.
public static void swap6(int num1, int num2, Object Obj_Arr)

CS3 Java – Topic 9: Arrays (Singhal) Page 96 of 134


Notice that array is passed to the method as an Object reference, and not as
array of Objects (Object [ ]). We have mentioned before that all arrays are Java
reference types and can be passed to any method that expects an Object as an
argument. Once inside the method swap6 however, for further processing, the
identity of the reference Obj_Arr must be decoded. Such decoding is facilitated by
the use of Java operator called instanceof. Use of instanceof operator is one of the
techniques provided by Java for the run time type identification (RTTI) of objects.

Run Time Type Identification (RTTI)9


The technology called RTTI, allows run time identification of objects. Using Java’s
instanceof operator is one part of versatile RTTI technology. We have given a
description of operator instanceof in the appendix of chapter two. Most common
application of instanceof operator is to check the identity of a java.lang.Object
passed to a method. For example the code snippet given below would print true.

Integer I2 = new Integer (5); Will print true as Obj stores address of
Object Obj = I2; Integer I2, which is indeed and Integer
if (Obj instanceof Integer) instance.
System.out.println (true);

On the other hand if the selection structure in the above code is replaced as follows:

if(Obj instanceof Double)


System.out.println (true);
else
System.out.println (false);

The code will print false, because Obj is not an instance of Double. The instanceof
operator works only when the object on its left hand side and reference type on its
right hand side, two of them, are “related”. When we learn inheritance and
polymorphism, it will become clear that Object Obj and reference type Double are
related in the sense that Double is also of type Object. Instanceof operator would
give a compile error if compiler can decide that variable on its left is not convertible
to the type specified on the right. For example the following would be a compile
error.
Compile error because at compile
Integer I2 = new Integer(5); time it can be determined
if(I2 instanceof Double) unambiguously that I2 is not
System.out.println (true); convertible to type Double.

9
Further details of RTTI are discussed in a separate chapter later.

CS3 Java – Topic 9: Arrays (Singhal) Page 97 of 134


Followings are the rules for using instanceof operator:
• The right hand operand must be a reference type (User defined or Java
provided).
• The left-hand operand must be an instance of a Java reference type or null.
• Compile error will result if the location of requisite operands (left vs, right)
are swapped.
• Compile error would also be issued (as seen above), if the operand on left is
not convertible to the reference type on right. For example in last example,
where I2 (an Integer type) is not convertible to reference type Double, a
compile error is issued.
• Run time type checking is only done when either the left hand operand is null
or its address can be stored in the reference type on the right.

Method swap6 comprises a system of nested if/else blocks, where each block tests to
decode the identity of the array Obj_Arr at runtime. For example the first block
pre-test condition is:

if(Obj_Arr instanceof int [] )

Notice that data type (or reference type) of int array is int [ ], which is used on the
right side of instanceof operator. The expression inside the if parenthesis would
evaluate to true if indeed Obj_Arr is of type int [ ]. If Obj_Arr is a reference to an
int array, then the if expression evaluates to true and first block in swap6 (L9.14#66-
71) is executed. To perform swap for sake of convenience, Obj_Arr is cast to arr, an
int [ ] type (L9.14#67). Then algorithm of swap2 in Listing 9.13 is used to swap the
values in the array (L9.14#68-70). Understand that references arr and Obj_Arr
point to the same array. Therefore the swap made is reflected in the original array
passed to swap6.

Figure 9.35 gives the output for Listing 9.14.


00001 Before swapping values at index two and five, the array is:

00002 2 3 3 1 8 5 3
00003 Calling the method swap5
00004 After swapping values at index two and five, the array is:

00005 2 3 51 8 3 3
00006 Before swapping values at index 1 and 4, the array is:

00007 7 3 2 0 47 8
00008 Calling the method swap6

CS3 Java – Topic 9: Arrays (Singhal) Page 98 of 134


00009 After swapping values at index 1 and 4, the array is:

00010 7 42 0 37 8
00011 Before swapping values at index 1 and 6, the String array is:

00012 John Mary Adam Ted Nina Ellen Bertha


00013 Calling the method swap6
00014 After swapping values at index 1 and 6, the String array is:

00015 John Bertha Adam Ted Nina Ellen Mary


FIG. 9.35
One notices that the array created by call to random number generator method rnd
printed before call to swap5 has values 3 and 5 at indices two and five. However,
after calling swap5 (L9.14#13), the values are swapped (F9.35#5). Similarly the
success of swap done by swap6 is reflected by pairs of outputs on lines #7 & 10, and
#12 & 15 in Figure 9.35.

Returning arrays as return values from methods


Since in Java arrays are reference types, it allows methods to return arrays as
return value from methods. When only one arrays is to be returned from a method,
returning it as a value is the preferred way of doing it. Listing 9.15 shows the class
ReturnArray with method getIntArray, which returns an int array filled either by
keyboard input or file input. The program uses IOManagement class discussed in
chapter 8.

00001 import java.io.*;


00002 import java.util.*;
00003
00004 public class ReturnArray
00005 {
00006 protected static final int [ ] ZERO_LEN_ARR = new int[0];
00007 private static PrintStream Console = System.out;
00008
00009 public static void main (String[] args) throws IOException
00010 {
00011 BufferedReader KB = IOManagement.getKeyboardReader();
00012 int [] iarr = getIntArray(KB,true);
00013 Console.println("Printing the array entered by you;");
00014 printArray(iarr);
00015
00016 BufferedReader FR = IOManagement.getFileReader();
00017 iarr = getIntArray(FR,false);
00018 Console.println("Printing the array read from the file.");
00019 printArray(iarr);
00020

CS3 Java – Topic 9: Arrays (Singhal) Page 99 of 134


00021 FR.close();
00022 }
00026 public static int [] getIntArray(BufferedReader in, boolean flag) throws
IOException
00027 {
00028 StringTokenizer St = null;
00029 int [] arr = ZERO_LEN_ARR;
00030 if(flag)
00031 {
00032 boolean done = false;
00033 do
00034 {
00035 Console.print(" Enter all int data with space between numbers. Press"
00036 +" enter key when done: ");
00037 String Input = in.readLine();
00038
00039 if(!(Input == null)&&!Input.equals("") && !Input.equals("\t"))
00040 {
00041 St = new StringTokenizer(Input.trim());
00042 if(St.countTokens() == 0)
00043 {
00044 Console.println("No data entered");
00045 done = false;
00046 }
00047 else
00048 done = true;
00049 }
00050 else
00051 {
00052 Console.println("Invalid keyboard input.");
00053 done = false;
00054 }
00055 }while(!done);
00056
00057 arr = new int[St.countTokens()];
00058 int ind = 0;
00059 while(St.hasMoreElements())
00060 arr[ind++] = Integer.parseInt(St.nextToken());
00061 }
00062 else
00063 {
00064 String Data = "";
00065 String Line = null;
00066
00067 while((Line = in.readLine()) != null)
00068 {

CS3 Java – Topic 9: Arrays (Singhal) Page 100 of 134


00069 Data+=Line;
00070 }
00071 St = new StringTokenizer(Data.trim());
00072
00073 arr = new int[St.countTokens()];
00074 int ind = 0;
00075 while(St.hasMoreElements())
00076 arr[ind++] = Integer.parseInt(St.nextToken());
00077 }
00078
00079 return arr;
00080 }
00081
00085 public static void printArray(int [] arr)
00086 {
00087 for(int ind = 0; ind<arr.length; ++ind)
00088 Console.print(arr[ind] + " ");
00089 Console.println();
00090 }
00091 }//Listing 9.15
The key method in class ReturnArray is getIntArray, whose header is given below.

public static int [] getIntArray(BufferedReader in, boolean flag)

The method takes a BufferedReader object and a boolean flag as arguments. For
true value of the flag, user enters the data into the array from the keyboard,
whereas for false value from the input file. In either case the data input is stored in a
StringTokenizer object St (L9.15#41 & 71). Then the method creates int array of
size equal to the number of tokens in the object St (L9.15#57 & 73) and assigns the
local array reference arr to it.

The local array reference arr is initially set to point to the constant zero length
array ZERO_LEN_ARR (L9.15#29). For Java methods returning an array as a
value, it is important to return a zero length array rather than a null reference, for
cases where an empty array must be returned. Assume that a method in our case
study on Inventory report in chapter eight were to returns an array of number of
items in the inventory file. If for some reason the inventory is totally empty, the
method must return a zero length array rather than a null value, as processing a
zero length array would be easier for a client than processing a null value.
Therefore never initialize an array reference to a null value. Rather create a zero
length array as a way of initialization and reassign to a new length as needed.

The standard procedure for getting the tokens from the StringTokenizer object St,
parsing them is used to populate the elements of arr (L9.15#59-60 & 75-76). Finally
the method returns arr (L9.15#79). Figure 9.36 shows the typical results from the
Listing 9.15.

CS3 Java – Topic 9: Arrays (Singhal) Page 101 of 134


FIG. 9.36

Finding the largest value in an array


All Java primitives and string data types have a natural order. For example, the
alphabets and numbers have a natural order. Strings also have a natural order
based on the ASCII value of alphabets constituting strings. Such order is called
lexicographical order, which is similar, but not the same as alphabetical order. We
show, as how to write a method findLargest, to find the largest member in an array
filled contiguously with double values. The method findLargest must take array,
and its logical length as arguments and return the largest double value in the array
length count. The header of method findLargest, then becomes:

public static double findLargest (final double [ ] Arr, int count)

The algorithm for the method findLargest ( ) is given by ALG 9.3

CS3 Java – Topic 9: Arrays (Singhal) Page 102 of 134


ALG 9.3
1. Create a variable of the data type same as the
array.
2. Set the variable equal to the first element of the
array
3. Scan array element-by-element and compare the
value of the variable with the value stored in
the each element of the array.
4. If9.37
FIG. array element being scanned is larger than the
value in the variable, then set the variable
equal to this new value.
5. Return the value of variable from step 1 as the
method return value.

Listing 9.16 shows the complete program to find largest double value and other
methods to perform statistical calculations in a randomly generated array.
00001 import java.util.*;
00002 import java.lang.reflect.*;
00003 import java.text.*;
00004
00005 public class Statistics
00006 {
00007 protected static final double [] ZERO_LEN_ARR = new double[0];
00008 protected static final int MAX = 20;
00009 protected static DecimalFormat DF = new DecimalFormat("0.00");
00010
00011 private Statistics(){}
00012
00013 public static void main (String[] args)
00014 {
00015
00016 Random RN = new Random(System.currentTimeMillis());
00017 double [] dbl_arr = fillArray(RN);
00018 System.out.println("Printing only the filled portion of the array.");
00019 printArray(dbl_arr,MAX/2);
00020 printStatistics(dbl_arr, MAX/2);
00021
00022

CS3 Java – Topic 9: Arrays (Singhal) Page 103 of 134


00023 }
00024 public static void printStatistics(final double [] double_array, int count)
00025 {
00026 count = Math.abs(count);
00027 if(count>double_array.length)
00028 count = double_array.length;
00029
00030 System.out.println("The smallest value = " +
00031 DF.format(findLowest(double_array,count)));
00032 System.out.println("The mean value = " +
00033 DF.format(findMean(double_array,count)));
00034 System.out.println("The largest value = " +
00035 DF.format(findLargest(double_array,count)));
00036 System.out.println("The standard deviation of values = " +
00037 DF.format(findStdDev(double_array,count)));
00038 }
00039
00040 public static double [] fillArray(final Random RN)
00041 {
00042 double [] dbl_arr = new double[MAX];
00043
00044 for(int ind = 0; ind<dbl_arr.length/2; ind++)
00045 dbl_arr[ind] = rnd(RN);
00046
00047 return dbl_arr;
00048 }
00049
00050 public static double rnd(final Random RN)
00051 {
00052 return 50*RN.nextDouble();
00053 }
00054
00055 public static double findMean(final double [] double_array, int count)
00056 {
00057 count = Math.abs(count);
00058 if(count>double_array.length)
00059 count = double_array.length;
00060
00061 double sum = 0.0;
00062 for(int index1=0; index1<count; index1++)
00063 {
00064
00065 sum = sum + double_array[index1];
00066 }
00067 return sum/count;
00068 }

CS3 Java – Topic 9: Arrays (Singhal) Page 104 of 134


00069
00070 public static double findStdDev(final double [] double_array, int count)
00071 {
00072 count = Math.abs(count);
00073 if(count>double_array.length)
00074 count = double_array.length;
00075
00076 double st_dev = 0.0;
00077 double sum_square = 0.0;
00078 //Find sum of squares of all values in the array
00079
00080 for(int index1 =0; index1<count; index1++)
00081 {
00082 sum_square = sum_square + double_array[index1]*double_array[index1];
00083 }
00084 double mean = findMean(double_array, count);
00085 return Math.sqrt(sum_square/count - mean*mean);
00086 }
00087
00088 public static double findLowest(final double [] double_array, int count)
00089 {
00090 count = Math.abs(count);
00091 if(count>double_array.length)
00092 count = double_array.length;
00093 //finds the lowest value in the array
00094 double lowest = double_array[0];
00095
00096 for(int index1=0; index1<count; index1++)
00097 {
00098 if(double_array[index1]<lowest)
00099 lowest = double_array[index1];
00100 }
00101
00102 return lowest;
00103 }
00104
00105 public static double findLargest(final double [] double_array, int count)
00106 {
00107 count = Math.abs(count);
00108 if(count>double_array.length)
00109 count = double_array.length;
00110 //finds the lowest value in the array
00111 double largest = double_array[0];
00112
00113 for(int index1=0; index1<count; index1++)
00114 {

CS3 Java – Topic 9: Arrays (Singhal) Page 105 of 134


00115 if(double_array[index1]>largest)
00116 largest = double_array[index1];
00117 }
00118
00119 return largest;
00120 }
00121
00122 public static void printArray(final Object arr, int count)
00123 {
00124 count = Math.abs(count);
00125 int len = Array.getLength(arr);
00126
00127 if(count>len)
00128 count = len;
//Using StringBuffer is more efficient than using String
00129 StringBuffer Val = new StringBuffer("");
00130 //Determine if formatted output is needed
00131 Object Obj = Array.get(arr,0);
00132
00133 if(Obj instanceof Double ||Obj instanceof Float)
00134 for(int ind = 0; ind<count; ind++)
00135 Val.append(DF.format(Array.get(arr,ind))+ " ");
00136 else
00137 for(int ind = 0; ind<count; ind++)
00138 Val.append(Array.get(arr,ind)+ " ");
00139
00140 System.out.println(Val.toString());
00141 }
00142 }
//Listing 9.16

In Listing 9.16 the algorithm for method findLowest is similar to ALG 9.3, except
for the fact that step four is altered as follows:

If array element being scanned is smaller than the value in the


variable, then set the variable equal to this new value.

Our purpose in developing Listing 9.16 was to be able to process portion of an array
(called logical length) to find statistical parameters, such as lowest, highest, mean,
and standard deviation values. In fact the methods findLargest, findLowest,
findMean, and findStdDev are static methods that can be used by all clients of class
Statistics. The danger in using a partial array of course is that client class has to
ascertain that precondition of logical length (count) passed to processing methods is
neither negative, not larger than the physical length of the array. If the precondition
is violated then the method may try to access an out of bound array element,

CS3 Java – Topic 9: Arrays (Singhal) Page 106 of 134


triggering JVM to crash the program by throwing
ArrayIndexOutOfBoundsException. Therefore in all methods that are passed the
logical array length as argument, we add a piece of code to first set logical length
(count) equal to its absolute value (L9.16#26, 57, 72, 90, 107, & 124). Then we
ascertain that if in violation of precondition the logical length (count) has been set
larger than the physical length of the array, former is set equal to the latter
(L9.16#27-28, 58-59, 73-74, 91-92, 108-109, & 127-128).

Method printArray and class java.lang.reflect.Array


Method printArray is a generic array print method and deserves further
explanation. It uses static methods from class java.lang.reflect.Array for some its
functionality. This class provides methods to access and create arrays dynamically
at runtime. Table 9.6 gives a summary of methods available in the class Array.

Summary of Methods from java.lang.reflect.Array


static Object get(Object array, int index)
Returns the value of the indexed component in
the specified array object.
static boolean getBoolean(Object array, int index)
Returns the value of the indexed component in the
specified array object, as a boolean.
static byte getByte(Object array, int index)
Returns the value of the indexed component in the
specified array object, as a byte.
static char getChar(Object array, int index)
Returns the value of the indexed component in the
specified array object, as a char.
static double getDouble(Object array, int index)
Returns the value of the indexed component in the
specified array object, as a double.
static float getFloat(Object array, int index)
Returns the value of the indexed component in the
specified array object, as a float.
static int getInt(Object array, int index)
Returns the value of the indexed component in the
specified array object, as an int.
static int getLength(Object array)
Returns the length of the specified array
object, as an int.
static long getLong(Object array, int index)
Returns the value of the indexed component in the
specified array object, as a long.

CS3 Java – Topic 9: Arrays (Singhal) Page 107 of 134


static short getShort(Object array, int index)
Returns the value of the indexed component in the
specified array object, as a short.
static Object newInstance(Class componentType, int length)
Creates a new array with the specified component type
and length.
static Object newInstance(Class componentType, int[] dimensions)
Creates a new array with the specified component type
and dimensions.
static void set(Object array, int index, Object value)
Sets the value of the indexed component of the specified
array object to the specified new value.
static void setBoolean(Object array, int index, boolean z)
Sets the value of the indexed component of the specified
array object to the specified boolean value.
static void setByte(Object array, int index, byte b)
Sets the value of the indexed component of the specified
array object to the specified byte value.
static void setChar(Object array, int index, char c)
Sets the value of the indexed component of the specified
array object to the specified char value.
static void setDouble(Object array, int index, double d)
Sets the value of the indexed component of the specified
array object to the specified double value.
static void setFloat(Object array, int index, float f)
Sets the value of the indexed component of the specified
array object to the specified float value.
static void setInt(Object array, int index, int i)
Sets the value of the indexed component of the specified
array object to the specified int value.
static void setLong(Object array, int index, long l)
Sets the value of the indexed component of the specified
array object to the specified long value.
static void setShort(Object array, int index, short s)
Sets the value of the indexed component of the specified
array object to the specified short value.
Table 9.6
The static method getLength from Array class (L9.16#125), takes an Object as an
argument. If the argument is an array then method returns its length. Before we
print the elements in the logical length of the array to the console, we first determine
if a formatted output is needed. We get an instance of an array member using the
get method of class Array, and test to see if it is an instance of either Double type or

CS3 Java – Topic 9: Arrays (Singhal) Page 108 of 134


Float type (L9.16#131 &133).. Method get takes an array reference, and an array
index as arguments and returns the Object version of the member at index passed to
it. If the array is composed of primitives, then get returns it’s wrapped Object
version. For example if Object arr points to an array of double values, then the code

Will return primitive double at


Double Val = Array.get(arr, index); location index as object Double

will return a Double value of the primitive at the location index. We then build a
StringBuffer object containing values of all array members (L9.16#134-135 or 137-
138). We use StringBuffer instead of String as former is more efficient and its
mutability is not a problem in printArray method. In order to access the members
of the array through its Object reference arr, we use the static method get
(L9.16#134). The method printArray prints the StringBuffer object Val after
building it through the iteration over the logical array length (L9.16#135 or 138).
Since the main in Listing 9.16 uses an array of randomly generated double values
(using methods from class java.util.Random, the output for it would vary from one
run to another. However, the Figure 9.37 shows one of the typical output.

FIG. 9.37
The object RN of type Random is first created in main by passing to its constructor
a long value to seed the random number generation mechanism (L9.16#16). A
suitable seed value is obtained by calling the method currentTimeMillis ( ) from
System class, which returns the current time in computer clock as a long parameter.
Then the method rnd uses the method nextDouble to generate and return 50 times
of the random number generated by latter (L9.16#52).

Out of Bound Array Elements


If you declare an array for five elements but you try to store seven values in there,
then Java compiler will not stop you. For example, compiler will compile a program
shown in Listing 9.17, where seven values are stored in a five-element array.
However, the program will crash when you try to run it.

CS3 Java – Topic 9: Arrays (Singhal) Page 109 of 134


Out of bound
Index!!!!
Compiler will
not save you.

Listing 9.17
At compile time the compiler is not able to check for the out of bound array indices.
Therefore it will let you store data in memory locations that is not with in the
bounds of array size. The program crashes upon running because it is trying to
write the data in a memory block that is not assigned to it, and JVM crashes it. In
fact situation will be very serious if JVM did not crash the program, in which case
the program can overwrite into memory blocks used by other programs, causing
some other program to crash. Similar problem may arise when you try to print out
of bound array elements. In Java the low bound is always zero. So accessing a
negative array index is meaningless. The upper bound is one less than the maximum
length of the array. Accessing array index beyond the upper bound is also
meaningless though Java compiler will not give an error if you did that. Easiest way
to avoid out of bound array index in Java is to always use zero value as a lower
bound and the value less than the length field of array, which is accessible by using
dot operator with the array name (arr.length is array name is arr). As illustrated in
Listing 9.16 that when logical length is passed to a method for array processing, the
code should always check to ascertain that it is smaller than the physical length.

No Aggregate Operations on Array


Unlike some other programming languages, Java does not allow an aggregate
operation on arrays. For example if we declare two arrays as follows:
int [] Arr1 = new int[50];
int[] Arr2 = new int[50];
then Java will not allow copying Arr2 values into Arr1 using an aggregate
assignment like below:
Will not copy Arr2 elements into Arr1, even
Arr1 = Arr2; though it will compile!!!!
To copy one array, into another we can use the procedure described earlier using
either the clone method or arraycopy method from System class.

We also cannot compare arrays for equality by doing an aggregate comparison. For

CS3 Java – Topic 9: Arrays (Singhal) Page 110 of 134


Will compile, but will only
check for equality of addresses
stored in Arr1 and Arr2.

if(Arr1 == Arr2)
System.out.println(“They are equal”);

To see whether all elements of an array are exactly equal to all the elements of
another array, one may either do a member wise comparison or use the equals
method from class java.util.Arrays. Listing 9.18 shows both techniques. Figure 9.38
shows the output for Listing 9.18.
00001 import java.util.*;
00002 import java.lang.reflect.*;
00003
00004 public class CompareArrays
00005 {
00006 private CompareArrays(){}
00007 protected static DecimalFormat DF = new DecimalFormat("0.00");
00008 public static void main (String[] args)
00009 {
00010 int [] Arr1 = {1,2,3,4,5};
00011 System.out.println("\nPrinting Array1");
00012 printArray(Arr1, Arr1.length);
00013 int[] Arr2 = { 1,4,6,8,9,10};
00014 System.out.println("Printing Array2");
00015 printArray(Arr2, Arr2.length);
00016 int [] Arr3 = {1,2,3,4,5};
00017 System.out.println("Printing Array3");
00018 printArray(Arr3, Arr3.length);
00019 System.out.println("Testing equals method from Arrays class.");
00020 //use of equals method from class Arrays
00021 if(Arrays.equals(Arr1,Arr2))
System.out.println("Array1 and Array2 have same contents in same order.");
00023 else
00024 System.out.println("Array1 and Array2 are not equal");
00025
00026 if(Arrays.equals(Arr1,Arr3))
System.out.println("Array1 and Array3 have same contents in same order.");
00028 else
00029 System.out.println("Array1 and Array3 are not equal");
00030 //use of isEquals method developed below
00031 System.out.println("Testing isEqual method.");

CS3 Java – Topic 9: Arrays (Singhal) Page 111 of 134


00032 if(isEqual(Arr1,Arr2))
System.out.println("Array1 and Array2 have same contents in same order.");
00034 else
00035 System.out.println("Array1 and Array2 are not equal");
00036
00037 if(isEqual(Arr1,Arr3))
System.out.println("Array1 and Array3 have same contents in same order.");
00039 else
00040 System.out.println("Array1 and Array3 are not equal");
00041 }
00042
00043 public static boolean isEqual(final Object Arr1, final Object Arr2)
00044 {
00045 boolean result = true;
00046
00047 if(Arr1 == Arr2)
00048 result = true;
00049 else if(Arr1 == null && Arr2 != null)
00050 result = false;
00051 else if(Arr1 !=null && Arr2 == null)
00052 result = false;
00053 else
00054 {
00055 int len1 = Array.getLength(Arr1);
00056 int len2 = Array.getLength(Arr2);
00057
00058 if(len1 != len2)
00059 result= false;
00060 else
00061 {
00062 for(int ind=0; ind<len1; ++ind)
00063 {
00064 Object Obj1 = Array.get(Arr1,ind);
00065 Object Obj2 = Array.get(Arr2,ind);
00066 if(!Obj1.equals(Obj2))
00067 {
00068 result= false;
00069 break;
00070 }
00071 }
00072 }
00073 }
00074 return result;
00075 }
00079 public static void printArray(final Object arr, int count)
{

CS3 Java – Topic 9: Arrays (Singhal) Page 112 of 134


81 count = Math.abs(count);
int len = Array.getLength(arr);

84 if(count>len)
count = len;

87 //Using StringBuffer is more efficient than using String


StringBuffer Val = new StringBuffer("");
//Determine if formatted output is needed
90 Object Obj = Array.get(arr,0);

92 if(Obj instanceof Double ||Obj instanceof Float)


for(int ind = 0; ind<count; ind++)
Val.append(DF.format(Array.get(arr,ind))+ " ");
95 else
for(int ind = 0; ind<count; ind++)
Val.append(Array.get(arr,ind)+ " ");

99 System.out.println(Val.toString());
}
} //Listing 9.18

FIG. 9.38
In Listing 9.18, first we create three arrays Arr1, Arr2, and Arr3 (L9.18# 10,13 &
16), of which Arr1 and Arr3 are clones of each other, and Arr2 is different from
both. We print all there arrays (Figure 9.38 Lines 1 to 6). Program then uses the
equals method from Arrays class which uses the syntax similar to the line
(L9.18#21) to test for equality of two arrays passed to the method. If arrays are
identical in number, element values and element order then the equals method
returns true, else it returns false. Test results (Figure9.38) indicate inequality of

CS3 Java – Topic 9: Arrays (Singhal) Page 113 of 134


Arr1 and Arr2 but equality of Arr1 and Arr3. Then we test the homegrown array
equality test method isEqual (L9.18#31-40), which gives results identical to the equal
method of Arrays class. isEqual method (L9.18#43-75) performs element by element
comparison (L9.18#67-70) after it has exhausted all other possibilities for making
decision about equality of two arrays Arr1, and Arr2 passed to it. The possibilities
that isEqual checks for are:
• If two arrays point to same object reference. If that is true then a true is
returned (L9.18#47-48).
• If one of the array name stores a null reference and other does not then a
false is returned (L9.18#49-52).
• If lengths of two arrays are not same then a false is returned (L9.18#58-59).
• In element-by-element comparison if one element is different then a false is
returned (L9.18#63-68).
• If original value of boolean variable (L9.18#45), which was set to true is
never changed then the arrays are identical, in which case a true is returned.
We employ the method printArrays from Listing 9.17 to print the arrays.

Question: How would one test, when two arrays have same
data, but the order in which data is there, may be different?
In order to see if the two arrays have same data but in different order, we would
first check for the lengths of two arrays for equality. If lengths were equal, then we
would need to sort the two arrays in ascending or descending order and then use
equal method of Arrays class to test for the equality. Fortunately the Arrays class
makes the task of sorting most arrays almost trivial. Table 9.7 shows the summary
of methods for the class java.util.Arrays.

Summary of Methods for class java.util.Arrays


static List asList(Object[] a)
Returns a fixed-size list backed by the specified array.
static int binarySearch(param [] a, param key)
Searches the specified array of data type param for the
specified value using the binary search algorithm. param can be of
types: byte, short, char, double, float, int, long, and Object.
static int binarySearch(Object[] a, Object key, Comparator c)
Searches the specified array for the specified object using
the binary search algorithm.
static boolean equals(param [] a, param [] a2)
Returns true if the two specified arrays of data type param
are equal to one another. param can be any of the following data
types: byte, boolean, char, double, float, int, long, Object, and
Short.
static void fill(param[] a, param val)
Assigns the specified param value (val) to each element of

CS3 Java – Topic 9: Arrays (Singhal) Page 114 of 134


the specified array of param (a). The param can be any of the
following types: boolean, byte, chars, double, float, int, long,
Object, and Short.
static void fill(param [] a, int fromIndex, int toIndex, param val)
Assigns the specified param value val) to each element of the
specified range of the specified array of param (a). The param
can be any of the following types: boolean, byte, chars, double,
float, int, long, Object, and Short.
static void sort(param [] a)
Sorts the specified array of param into ascending natural
order. The param can be any of the following types: byte, char,
double, float, int, long, Object, and Short.
static void sort(param [] a, int fromIndex, int toIndex)
Sorts the specified range of the specified array of param into
ascending numerical order. The param can be any of the following
types: byte, char, double, float, int, long, Object, and Short.
static void sort(Object[] a, Comparator c)
Sorts the specified array of objects according to the order
induced by the specified comparator.
static void sort(Object[] a, int fromIndex, int toIndex,
Comparator c)
Sorts the specified range of the specified array of objects
according to the order induced by the specified comparator.
Table 9.7
The overloaded sort method can sort any kind of array in ascending order in the full
array length or in portion of it. One example of generic selection sort method using
a generic swap method (swap7) is shown in Appendix A9.2.

Except for character array one cannot print an array by doing aggregate operation.
int [ ] Arr1 = new int[50];
System.out.println(Arr1); //Will only print address stored in Arr1
Java does however allow character array to be printed aggregately. For example, a
character array char_arr as shown below is allowed to be printed aggregately.
char [] char_arr= {'h','e','l','l','o'};
System.out.println (char_arr);
The above array char_arr will print hello on a DOS screen.

We also cannot do any aggregate mathematical operations on arrays. For example,


the following is not allowed.
int [ ] Arr1= {1,2,3,4,5};
int [ ] Arr2= {1,4,6,8,9,10};

CS3 Java – Topic 9: Arrays (Singhal) Page 115 of 134


int [] Arr3 = Arr1 + Arr2;//Not Allowed. Compile error !!!!
To add one array into another, and store sum in a third array, one would need to do
element-by-element addition, using a loop. Example is shown in findMean method
of Listing 9.17.

Case Study: Getting Frequency of All characters in a Text File


One simple form of encryption is to replace every alphabet in an English text by any
other alphabet. For example, one encryption scheme can be to replace characters in
a text file as follows (case ignored):
a = c, b = d, c=e, d = f………x=z, y =a, z=b. To break this encryption one can
analyze a typical text of English writing and see, as to which characters occur at
what frequency, and then analyze the encrypted text for the frequency of
characters. By comparing the frequency of characters in encrypted and non-
encrypted text, one can break the encryption code designed above. Here we will only
discuss as how to find the frequency of characters in an English text file.

We are aware of the fact that all printable characters on keyboard have ASCII
values ranging from 32 to 126. What we can do is to create an integer array of 128
elements and as we read a character in the text, we increment the value stored in
that array cell number by one, whose index is equal to the ASCII value of character
just read. For example, we know that the ASCII value of character ‘A’ is 65. Then
each time we read the character ‘A’ in the data file, we increment the value stored
in the array cell with index 65 by one. A typical character frequency-counting array
may look like the figure 9.39 below (provided, the case is ignored).

CS3 Java – Topic 9: Arrays (Singhal) Page 116 of 134


int [] freqCount = new int[91];

FIG. 9.39
ALG 9.4 gives the short algorithm for such a program below.

ALG 9.4
Listing 9.19 gives a class DeEncrypt, whose methods implement the algorithm 9.4.

CS3 Java – Topic 9: Arrays (Singhal) Page 117 of 134


00001 import java.io.*;
00002 import javax.swing.*;
00003
00004 public class DeEncrypt
00005 {
00009 protected static final int LOWER_BOUND = 0;
00013 protected static final int MAX_SIZE = 128;
00017 protected static final char MIN_CHAR = ' ';
00021 protected static final char MAX_CHAR = '~';
00022
00027 private DeEncrypt( )
00028 {
00029
00030 }
00034 public static int [] fillArray(final BufferedReader BR)
00035 throws IOException
00036 {
00037 int [] Arr = new int[MAX_SIZE];
00038
00039 int ch =BR.read();
00040
00041 while(ch != -1)
00042 {
00043 //Ascertain that ch is a printable character
00044 char ch1 = (char)ch;
00045
00046 if(( ch1 >= '\u0020' && ch1 < '\u007E'))
00047 Arr[ch]++;
00048 ch = BR.read();
00049 }
00050 return Arr;
00051 }
00055 public static void printOccurence(final int Arr[ ], final PrintWriter Pw)
00056 throws IOException
00057 {
00058 //print only the character in printable range
00059 for(char index = MIN_CHAR; index<(char)Arr.length; ++index)
00060 if(Arr[index]>0)
00061 Pw.println(index +" occurred \t"+ Arr[index]+ "\ttime(s).");
00062 }
00063
00064 }

00001 import java.io.*;


00002 public class DriverDeEncrypt
00003 {

CS3 Java – Topic 9: Arrays (Singhal) Page 118 of 134


00004 public static void main(String[] args) throws IOException
00005 {
System.out.println("Standby to provide the name of input file to be analyzed.");
00007 BufferedReader BR = IOManagement.getFileReader();
System.out.println("Standby to provide the name of output file to write to.");
00009 PrintWriter Pw = IOManagement.getFileWriter();
00010 //int []freq_count = DeEncrypt.fillArray(BR);
00011 //DeEncrypt.printOccurence(freq_count,Pw);
00012 DeEncrypt.printOccurence(DeEncrypt.fillArray(BR),Pw);
00013 }
00014 }
//Listing 9.19
The method fillArray gets a BufferedReader object bonded to an input data file and
reads the file character-by-character (L9.19#39 & 48). If character read falls in the
printable range (‘\u0020’ to ‘\u007E’) then the value at the index equal to the ASCII
value of the character read is incremented by one. (L9.19#47). Finally the frequency
counter array is returned (L9.19#50). The method printOccurence would print the
printable character part of the array (L9.19#55-64) on the media of user choice.
For the data file shown below in Figure 9.40, the results of frequency of characters
are shown in Figure 9.41.
//*******************************************************************
WASHINGTON, May 6 President Bush appointed a new civilian
administrator for Iraq today, settling a sharp disagreement between the
State and Defense Departments over how best to manage that country
during its recovery and reconstruction.

The new administrator, L. Paul Bremer, who served as an ambassador at


large for counterterrorism in the Reagan administration, will outrank
Jay Garner, the retired Army lieutenant general who has been in charge
of postwar administration since the government of Saddam Hussein was
ousted by American-led military forces last month.

The Pentagon had hoped to retain control of the postwar effort, so the
decision is a victory for Secretary of State Colin L. Powell. It will
probably also help placate United Nations and European critics, who
have complained that Iraq should be governed by a civilian during this
interim period to lessen the appearance of a military occupation.

"The ambassador goes with the full blessing of this administration and
the full confidence of everyone in this administration," Mr. Bush said
in the Oval Office today, as Mr. Bremer sat between him and Defense
Secretary Donald H. Rumsfeld.

Mr. Bremer "is a person who knows how to get things done," the
president added.

Senior administration officials first began talking about appointing


Mr. Bremer more than a week ago, but no official announcement emerged
in the following days, and public comments by Mr. Powell and Mr.
Rumsfeld exposed the rift between the State Department and the Pentagon
on the interim administration of postwar Iraq.

CS3 Java – Topic 9: Arrays (Singhal) Page 119 of 134


During a Congressional hearing in late April, Mr. Powell was shown an
organizational chart that indicated a Pentagon official would oversee
the selection of a new government in Iraq.

"That is not a current and accurate chart," Mr. Powell snapped. "And it
will be even less accurate within the next few days."

But after several days passed and the White House still had said
nothing about Mr. Bremer, Mr. Rumsfeld issued an unusual statement of
support for Mr. Garner, saying he "is doing a truly outstanding job for
the nation; any suggestion to the contrary is flat untrue and
mischievous."

Mr. Rumsfeld also noted pointedly, "The White House has made no
announcements regarding other appointments."

That announcement finally came today. With Mr. Rumsfeld looking on,
smiling, the president hailed Mr. Bremer "as a can-do person."

Mr. Bremer served in the United States Foreign Service for 23 years and
is chairman and chief executive of the crisis-consulting practice at
Marsh Inc., a division of the Marsh & McLennan Companies. Before
joining the company in October 2000, he worked for Kissinger
Associates, the international consulting firm headed by former
Secretary of State Henry A. Kissinger. He has also served on the
president's Homeland Security Advisory Council.

General Garner remains busy in Iraq. On Monday, he met with a sheikh


and tribal chieftain in Basra who may become governor there.

"It was a very good meeting," the sheikh, Muzahem al-Tamimi, told
Agence France-Presse. "We are happy he came to see us. He asked my
opinion of the future of Iraq."

The United States also released more Iraqi prisoners of war, and
officials announced that all would soon be let go.

The military prisoners "will be gone within the next few days and
civilians within four or five days," said Maj. Stacy Garrity of the
800th Military Police Brigade at Camp Bucca, in southern Iraq, the main
detention facility. At its height, the camp held 7,000 prisoners, who
have been steadily released since hostilities began winding down, with
2,000 remaining.

In Paris, Attorney General John Ashcroft told an international law


enforcement conference that the looting of Iraq's national museum had
been committed by organized criminal groups "who knew precisely what
they were looking for" rather than by mobs, as first thought.

European Union culture ministers issued a statement decrying the thefts


and urging the return of "objects illegally removed from museums or
archaeological sites, without allowing them to become objects of trade
ending up in foreign museums or private collections."

Mr. Ashcroft and other law enforcement officials vowed to recover the
stolen artifacts and return them to Iraq.

CS3 Java – Topic 9: Arrays (Singhal) Page 120 of 134


//**********************************************************************
FIG. 9.40
//********************************************************
occurred 664 time(s).
" occurred 24 time(s).
& occurred 1 time(s).
' occurred 2 time(s).
, occurred 39 time(s).
- occurred 5 time(s).
. occurred 50 time(s).
0 occurred 11 time(s).
2 occurred 3 time(s).
3 occurred 1 time(s).
6 occurred 1 time(s).
7 occurred 1 time(s).
8 occurred 1 time(s).
; occurred 1 time(s).
A occurred 13 time(s).
B occurred 14 time(s).
C occurred 5 time(s).
D occurred 6 time(s).
E occurred 2 time(s).
F occurred 2 time(s).
G occurred 7 time(s).
H occurred 9 time(s).
I occurred 15 time(s).
J occurred 2 time(s).
K occurred 2 time(s).
L occurred 3 time(s).
M occurred 24 time(s).
N occurred 3 time(s).
O occurred 5 time(s).
P occurred 12 time(s).
R occurred 6 time(s).
S occurred 15 time(s).
T occurred 10 time(s).
U occurred 4 time(s).
W occurred 5 time(s).
a occurred 291 time(s).
b occurred 37 time(s).
c occurred 100 time(s).
d occurred 125 time(s).
e occurred 398 time(s).
f occurred 80 time(s).
g occurred 69 time(s).
h occurred 137 time(s).
i occurred 255 time(s).
j occurred 5 time(s).
k occurred 11 time(s).
l occurred 124 time(s).
m occurred 93 time(s).
n occurred 284 time(s).
o occurred 243 time(s).
p occurred 52 time(s).
q occurred 10 time(s).
r occurred 242 time(s).

CS3 Java – Topic 9: Arrays (Singhal) Page 121 of 134


s occurred 197 time(s).
t occurred 286 time(s).
u occurred 80 time(s).
v occurred 31 time(s).
w occurred 55 time(s).
x occurred 4 time(s).
y occurred 55 time(s).
z occurred 3 time(s).
//***************************************************
FIG. 9.41

CS3 Java – Topic 9: Arrays (Singhal) Page 122 of 134


Exercises:
10.1 Write the method findSmallest such that it returns an array of two integer.
The first integer would be the smallest value in the array, and second integer would
be the first index (in ascending order) where the smallest value is found. The length
is the logical length of the array. The header of the method is as follows.
int [ ] findSmallest1(final int[ ] nums int length)

10.2 Write the method findSmallest above such that it returns an array of integers
where the first value is the smallest value in the array and second value is the index
where the last occurrence of this lowest value takes place. The proto-type will then
become:
int [ ] findSmallest2(final int[ ] nums int length)

10.3 Modify the method findLargest in Listing 9.16 such that it returns an array of
integers of size three such that, the first integer is the largest value, second is the
index where (in ascending order) the first occurrence of largest value takes place,
and last value is the index where last occurrence of largest value takes place. The
header of the method is as follows:
int [ ] findlargest1(final int[ ] nums int length)

10.4 Palindrome Program: A palindrome is a word, which when spelled forward or


backwards is the same. For example, the words ana, or otto are palindromes. Write
a program, which will ask user to input a string. The program should test whether
string entered is a palindrome or not and tell the user the results. Use a loop to allow
user to enter as many strings (one at a time) as they wish.
(Hint: Store the string in a character array. Then store a backward copy of it in
another character array. Then compare two arrays, character by character to find
whether the string is a palindrome or not.)

10.5 Write a method find ( ) which takes an integer array, its logical length, and an
integer key as arguments. The method returns a true if key is found in the array,
otherwise it returns a false. The header of find is as follows:
boolean find(final int [ ] nums, int length, int key)

10.6 Write a method findLargerThan which takes same parameters as the method
find in exercise 10.5, but returns the number of integers in the array nums that are
larger than the integer key. The header of findLargerThan is given below:
int findLargerThan (final int [ ] nums, int length, int key)

10.7 Write a method findSmallerThan which takes same parameters as the method
find in exercise 10.6, but returns the number of integers in the array nums that are
smaller than the integer key. The header of findSmallerThan is given below:
int findSmallerThan (final int [ ] nums, int length, int key)

CS3 Java – Topic 9: Arrays (Singhal) Page 123 of 134


CS3 Java – Topic 9: Arrays (Singhal) Page 124 of 134
Appendix A9.1
import java.util.*;

public class Swap


{
public static void main(String[] args)
{
//uncomment below (main1) to test swap1 to swap4
//main1();

//uncomment below (main2) to test swap5 and swap6


main2();
}

public static void main1()


{
int Data1 = 10;
int Data2 = 15;
System.out.println("The current values of \n" +
"Data1 = " + Data1 +"\n"+
"Data2 = " + Data2);
swap1(Data1,Data2);
System.out.println("After calling swap1 the value of \n" +
"Data1 = " + Data1 +"\n"+
"Data2 = " + Data2);
System.out.println("Declaring two one element int arrays D1, D2");
Data1 = 33;
Data2 = 55;
System.out.println("The current values of \n" +
"Data1 = " + Data1 +"\n"+
"Data2 = " + Data2);
int [] D1 ={Data1};
int [] D2 ={Data2};
swap2(D1,D2);
Data1 = D1[0];
Data2 = D2[0];
System.out.println("After calling swap1 the value of \n" +
"Data1 = " + Data1 +"\n"+
"Data2 = " + Data2);

StringBuffer C1 = new StringBuffer(new Integer(Data1).toString());


StringBuffer C2 = new StringBuffer(new Integer(Data2).toString());
swap3(C1,C2);
System.out.println("After calling swap3 the value of \n" +
"Data1 = " + C1.toString() +"\n"+
"Data2 = " + C2.toString());

CS3 Java – Topic 9: Arrays (Singhal) Page 125 of 134


Data1 = 1000;
Data2 = -22222222;

System.out.println("The current values of \n" +


"Data1 = " + Data1 +"\n"+
"Data2 = " + Data2);
C1 = new StringBuffer(new Integer(Data1).toString());
C2 = new StringBuffer(new Integer(Data2).toString());
swap3(C1,C2);

Data1 = Integer.parseInt(C1.toString());
Data2 = Integer.parseInt(C2.toString());
System.out.println("After calling swap3 the value of \n" +
"Data1 = " + Data1 +"\n"+
"Data2 = " + Data2);

double dbl1 = 99.999954;


double dbl2 = -99.203;
C1 = new StringBuffer(new Double(dbl1).toString());
C2 = new StringBuffer(new Double(dbl2).toString());
System.out.println("The current values of \n" +
"dbl1 = " + dbl1 +"\n"+
"dbl2 = " + dbl2);
swap3(C1,C2);
dbl1 = Double.parseDouble(C1.toString());
dbl2 = Double.parseDouble(C2.toString());
System.out.println("After calling swap3 the value of \n" +
"dbl1 = " + dbl1 +"\n"+
"dbl2 = " + dbl2);

C1 = new StringBuffer("Mary");
C2 = new StringBuffer("John");

System.out.println("Before calling swap3 the value of \n" +


"C1 = " + C1 +"\n"+
"C2 = " + C2);
swap3(C1,C2);
System.out.println("After calling swap3 the value of \n" +
"C1 = " + C1 +"\n"+
"C2 = " + C2);
//testing swap4
int value1 = -77;
int value2 = 900;
System.out.println("Before calling swap4 the value of \n" +
"value1 = " + value1 +"\n"+

CS3 Java – Topic 9: Arrays (Singhal) Page 126 of 134


"value2 = " + value2);

Vector Vec1 = new Vector(1);


Vector Vec2 = new Vector(1);
Vec1.add(0,new Integer(value1));
Vec1.trimToSize();
Vec2.add(0,new Integer(value2));
Vec2.trimToSize();
swap4(Vec1,Vec2);
value1 = ((Integer)Vec1.elementAt(0)).intValue();
value2 = ((Integer)Vec2.elementAt(0)).intValue();

System.out.println("After calling swap4 the value of \n" +


"value1 = " + value1 +"\n"+
"value2 = " + value2);
dbl1 = 99.999954;
dbl2 = -99.203;
Vec1.clear();
Vec2.clear();
Vec1.add(0,new Double(dbl1));
Vec1.trimToSize();
Vec2.add(0,new Double(dbl2));
Vec2.trimToSize();

System.out.println("Before calling swap4 the value of \n" +


"dbl1 = " + dbl1 +"\n"+
"dbl2 = " + dbl2);
swap4(Vec1,Vec2);
dbl1 = ((Double)Vec1.elementAt(0)).doubleValue();
dbl2 = ((Double)Vec2.elementAt(0)).doubleValue();
System.out.println("After calling swap4 the value of \n" +
"dbl1 = " + dbl1 +"\n"+
"dbl2 = " + dbl2);
}
/**
*
*/
public static void swap1(int val1, int val2)
{
int temp = val1;
val1 = val2;
val2 = temp;
}
/**
*
*/

CS3 Java – Topic 9: Arrays (Singhal) Page 127 of 134


public static void swap2(int []num1, int [] num2)
{
int temp = num1[0];
num1[0] = num2[0];
num2[0] = temp;
}
/**
*
*/
public static void swap3(final StringBuffer S1, final StringBuffer S2)
{
String Str = S1.toString();
S1.setLength(0);
S1.append(S2.toString());
S2.setLength(0);
S2.append(Str);
}
/**
*
*/
public static void swap4(final Vector V1, final Vector V2)
{
Object Obj1 = V1.firstElement();
V1.clear();
V1.add(0,V2.firstElement());
V2.clear();
V2.add(0,Obj1);
V1.trimToSize();
V2.trimToSize();
}

public static void main2()


{
int [] arr = {rnd(),rnd(),rnd(),rnd(),rnd(),rnd(),rnd(),};
System.out.println("Before swapping values at index two and five, the array is:");

for(int ind=0; ind<arr.length; ++ind)


System.out.print(arr[ind] + " ");
System.out.println();
System.out.println("Calling the method swap5");
swap5(2, 5, arr);
System.out.println("After swapping values at index two and five, the array is:");

for(int ind=0; ind<arr.length; ++ind)


System.out.print(arr[ind] + " ");

CS3 Java – Topic 9: Arrays (Singhal) Page 128 of 134


System.out.println();

int [] arr2 = {rnd(),rnd(),rnd(),rnd(),rnd(),rnd(),rnd(),};


System.out.println("Before swapping values at index 1 and 4, the array is:");

for(int ind=0; ind<arr2.length; ++ind)


System.out.print(arr2[ind] + " ");
System.out.println();

System.out.println("Calling the method swap6");


swap6(1,4,arr2);
System.out.println("After swapping values at index 1 and 4, the array is:");

for(int ind=0; ind<arr2.length; ++ind)


System.out.print(arr2[ind] + " ");
System.out.println();

String [] Str = {"John", "Mary", "Adam", "Ted", "Nina", "Ellen", "Bertha"};


System.out.println("Before swapping values at index 1 and 6, the String array is:");

for(int ind=0; ind<Str.length; ++ind)


System.out.print(Str[ind] + " ");
System.out.println();

System.out.println("Calling the method swap6");


swap6(1,6,Str);
System.out.println("After swapping values at index 1 and 6, the String array is:");

for(int ind=0; ind<Str.length; ++ind)


System.out.print(Str[ind] + " ");
System.out.println();
}
/**
*
*/
public static void swap5(int num1, int num2, int [ ] iarr)
{
int temp = iarr[num1];
iarr[num1] = iarr[num2];
iarr[num2] = temp;
}
/**
*
*/
public static void swap6(int num1, int num2, Object Obj_Arr)

CS3 Java – Topic 9: Arrays (Singhal) Page 129 of 134


{
if(Obj_Arr instanceof int [])
{
int [] arr = (int [ ])(Obj_Arr);
int temp = arr[num1];
arr[num1] = arr[num2];
arr[num2] = temp;
}
else if(Obj_Arr instanceof byte [])
{
byte [] arr = (byte [ ])(Obj_Arr);
byte temp = arr[num1];
arr[num1] = arr[num2];
arr[num2] = temp;
}
else if(Obj_Arr instanceof char [])
{
char [] arr = (char [ ])(Obj_Arr);
char temp = arr[num1];
arr[num1] = arr[num2];
arr[num2] = temp;
}
else if(Obj_Arr instanceof short [])
{
short [] arr = (short [ ])(Obj_Arr);
short temp = arr[num1];
arr[num1] = arr[num2];
arr[num2] = temp;
}
else if(Obj_Arr instanceof float [])
{
float [] arr = (float [ ])(Obj_Arr);
float temp = arr[num1];
arr[num1] = arr[num2];
arr[num2] = temp;
}
else if(Obj_Arr instanceof long [])
{
long [] arr = (long [ ])(Obj_Arr);
long temp = arr[num1];
arr[num1] = arr[num2];
arr[num2] = temp;
}
else if(Obj_Arr instanceof double [])
{
double [] arr = (double [ ])(Obj_Arr);

CS3 Java – Topic 9: Arrays (Singhal) Page 130 of 134


double temp = arr[num1];
arr[num1] = arr[num2];
arr[num2] = temp;
}
else if(Obj_Arr instanceof boolean [])
{
boolean [] arr = (boolean [ ])(Obj_Arr);
boolean temp = arr[num1];
arr[num1] = arr[num2];
arr[num2] = temp;
}
else if(Obj_Arr instanceof String [])
{
String [] arr = (String [ ])(Obj_Arr);
String temp = arr[num1];
arr[num1] = arr[num2];
arr[num2] = temp;
}
}
/**
*
*/
public static int rnd()
{
return (int)(10*Math.random());
}
}
Appendix A 9.2
import java.lang.reflect.*;
import java.util.*;
import java.text.*;

public class Swap7AndSelSort


{
public static void main(String[] args)
{
testInt();
testdouble();
testInt();
testdouble();
testInt();
testdouble();
testString();
/*testSelectionSort();*/
}

CS3 Java – Topic 9: Arrays (Singhal) Page 131 of 134


public static void testString()
{
String [] Str = {"John", "Mary", "Adam", "Ted", "Nina", "Ellen", "Bertha"};
System.out.println("Before swapping values at index 1 and 6, the
String array is:");

for(int ind=0; ind<Str.length; ++ind)


System.out.print(Str[ind] + " ");
System.out.println();

System.out.println("Calling the method swap7");


swap7(1,6,Str);
System.out.println("After swapping values at index 1 and 6, the String array is:");

for(int ind=0; ind<Str.length; ++ind)


System.out.print(Str[ind] + " ");
System.out.println();
}

public static void testInt()


{
Random RN = new Random(System.currentTimeMillis());
int [] arr =
{rnd(RN),rnd(RN),rnd(RN),rnd(RN),rnd(RN),rnd(RN),rnd(RN),};
System.out.println("Before swapping values at arr[2] and arr[5], array arr is:");

for(int ind=0; ind<arr.length; ++ind)


System.out.print("arr[" +ind+"] = "+ arr[ind] + " ; ");
System.out.println();
System.out.println("Calling the method swap7");
swap7(2, 5, arr);
System.out.println("After swapping values at arr[2] and arr[5], array arr is:");

for(int ind=0; ind<arr.length; ++ind)


System.out.print("arr[" +ind+"] = "+ arr[ind] + " ; ");
System.out.println();
}

public static void testdouble()


{
DecimalFormat DF = new DecimalFormat("0.0");
Random RN = new Random(System.currentTimeMillis());
double [] arr = {rndDouble(RN),rndDouble(RN),rndDouble(RN),
rndDouble(RN),rndDouble(RN),rndDouble(RN),rndDouble(RN),};
System.out.println("Before swapping values at arr[2] and arr[5], array arr is:");

CS3 Java – Topic 9: Arrays (Singhal) Page 132 of 134


for(int ind=0; ind<arr.length; ++ind)
System.out.print("arr[" +ind+"] = "+ DF.format(arr[ind]) + " ; ");
System.out.println();
System.out.println("Calling the method swap7");
swap7(2, 5, arr);
System.out.println("After swapping values at arr[2] and arr[5], array arr is:");

for(int ind=0; ind<arr.length; ++ind)


System.out.print("arr[" +ind+"] = "+ DF.format(arr[ind]) + " ; ");
System.out.println();
}

public static void swap7(int num1,int num2, Object Obj_Arr)


{
//save the value at num1
Object Value1 = Array.get(Obj_Arr,num1);
//set the value at num1 equal to value at num2
Array.set(Obj_Arr,num1,Array.get(Obj_Arr,num2));
//save the value at num2 equal to the saved value
Array.set(Obj_Arr,num2,Value1);
}

public static int rnd(Random RN)


{
return Math.abs(RN.nextInt()%100);
}

public static double rndDouble(Random RN)


{
return Math.abs(10.0*RN.nextDouble());
}

public static void selectionSort(Object Arr, int size)


{
int pass_number = 0;
Comparable Largest = null;
int index_largest = 0;

for(; pass_number<size;pass_number++)
{
Largest = (Comparable)Array.get(Arr,0);
index_largest = 0;
for(int index = 0; index<size-pass_number; index++)
if((Largest.compareTo(Array.get(Arr,index)))<0)
{

CS3 Java – Topic 9: Arrays (Singhal) Page 133 of 134


Largest = (Comparable)Array.get(Arr,index);
index_largest = index;
}

swap7(index_largest, size-pass_number-1, Arr);


}
}

public static void testSelectionSort()


{
int[] Arr = new int[30];
Random RN = new Random(System.currentTimeMillis());
for(int ind =0; ind<Arr.length; ++ind)
Arr[ind] = rnd(RN);

System.out.println("Before sorting the array is:");

for(int ind =0; ind<Arr.length; ++ind)


System.out.print(Arr[ind]+ " ");
System.out.println();
selectionSort(Arr,Arr.length);
System.out.println("After sorting the array is:");

for(int ind =0; ind<Arr.length; ++ind)


System.out.print(Arr[ind]+ " ");
System.out.println();

CS3 Java – Topic 9: Arrays (Singhal) Page 134 of 134


CS 3: Java
Chapter 10: Classes and Inheritance
Author: Satish Singhal Ph. D.
Version 1.0
In this chapter we revisit the access modifiers in Java and discuss inheritance,
interfaces, and abstract classes – all-powerful concepts in object-oriented
programming. Here is the sequence of topics to be discussed.
Access Modifiers in Java
Inheritance with in Classes
Inheritance from Interfaces
Abstract Classes
Local classes
Asynchronous Programming
Inner Classes
Nested Interface
Overriding Super class methods
Having learned the above essential topics, we can progress towards learning about
the abstractions needed to learn and represent graphical programming and error
handling.

Access Modifiers
The access modifiers regulate the access of java classes, fields and methods. There
are four different access modifiers.
1. public
2. private (An outer java class cannot be declared private. But
inner classes can be declared private).
3. protected (An outer java class cannot be declared protected.
But inner classes can be declared protected).
4. No modifier is specified.
A minimal java class declaration may be done as follows:
//************************************************* Note the absence of
class MyClass package name! This
{ means that class is in an
unknown package and is
//---------------- not accessible outside it!
}//Listing 10.1
//**********************************************

Lecture Inheritance Page 1 of 112


In defining the class in Listing 10.1 no modifier is used before the word class. Thus
the class MyClass becomes what is called “package-private” or package visible.
What that means is that MyClass is visible only to the classes, which are in the same
package in which MyClass would be. All java classes are part of a package. If no
package statement appears in the source code of the class, then the class becomes
part of an un-named package, where the package is essentially the folder in which
the file MyClass.java will reside. The folder name cannot be used to access the
classes in it, the way a package name can be.

Most useful form of java class declaration is as follows:


//************************************************* Includes the package
package datastructures; name of which the class
is member.

public class MyClass2


{
//---------------- Class is declared
} public.

Listing 10.2
//**********************************************
Why is above form useful? Because now the class MyClass2 being declared as public
becomes accessible to rest of the world by virtue of being part of a named package1.
All Sun Java Classes are defined in this manner (All public, all members of some
named package.)2
Modifiers private and protected are not used for the outer
classes, but they can be used for the inner or nested classes. We
will discuss additional modifiers for classes after we have discussed the topic of
inheritance.

1
The package naming requires that name must be unique. Sun uses the system of reverse domain
notation. For example the packages from Oracle Corporation may have names such as
com.oracle.packagename. Since the name com.oracle will be unique, all packages become unique,
with out any chance of naming conflict and confusion.
2
The details of compiling packages are given at the Web site below:
http://www.yoda.arachsys.com/java/compiling.html

Lecture Inheritance Page 2 of 112


Modifiers for fields and methods
Stand alone static Modifier:
All useful java classes have fields and methods in them. Depending upon use of
keyword static, the fields and methods in a java class may of any of the two types:
• Instance Fields
• Class Fields
• Instance Methods
• Class Methods
The class fields and class methods use the modifier static in their declaration
whereas the instance methods and fields do not use the modifier static. Example is
shown in Listing 10.3.
Instance field
//*************************************************
public class MyClass
{ Class field
int value;
static int standard_num;
Class method
static int findSquare(int val)
{
return val*val;
} Instance method

public String toString( )


{
String Str = "The values of class members of class MyClass\n";
Str = Str + "standard_num = " + standard_num + “\n”;
Str = Str + "value = " + value;
return Str;
}
}
Listing 10.3
//**********************************************
Class fields and class methods can be invoked by using the class name alone.
However, instance methods and instance fields are invoked by using the instance of
the particular class. Listing 10.4 gives the code for testing the class MyClass. The
results of running the program in Listing 10.4 are given in Figure 10.1.

Lecture Inheritance Page 3 of 112


TestMyClass is the client class
residing in the same package
as MyClass.
//*************************************************************
public class TestMyClass
{
public static void main(String[] args)
Setting the value of an
{ instance field. Field
MyClass Temp1 = new MyClass( ); named “value” had no
modifier attached to it.
Temp1.value = -10;

MyClass.standard_num = 100; Setting the value


of a class field.
MyClass Temp2 = new MyClass( );
Temp2.value = -30;
Calling instance
System.out.println (Temp1.toString( )); method.
System.out.println (Temp2.toString( ));

int num = MyClass.findSquare (5); Calling class


System.out.println ("Value of square of 5 = " + num);
}
}
Listing 10.4
//**********************************************************************

Lecture Inheritance Page 4 of 112


FIG. 10.1
It is clear from the Listing 10.3 and 10.4 that:
• Instance variables and methods can be accessed3 by
qualifying them with the name of the instance of the class.
For example if Temp1 is an instance of MyClass, then
Temp1.value qualifies the value field of the instance
Temp1.
• Using class name one can access class variables and
methods. For example static variable standard_num can be
accessed by using the class name MyClass as
MyClass. standard_num.

We also must understand that static variables have only one copy for all the
instances of a class, whereas non-static variables will have number of
copies, equal to the number of instances for that class.

Other Modifiers For Fields and Methods:


If no modifier is specified, then a field or method is package-private or package
visible. The examples are shown in Listing 10.3 and 10.4. The other modifiers that
can be used for the fields and methods are:
• public
• private
• protected

3
Methods and variables must be package-private(no access modifier used), public, or protected in
order to be accessed inside another class in the same package. Public methods and variables are
accessible everywhere.

Lecture Inheritance Page 5 of 112


Fields and methods that are declared public are accessible everywhere as long as the
class in which they are declared is also public. The access mechanism for public
identifiers is somewhat similar to the example shown in Listing 10.4. Figure 10.2
shows the visibility domain of public modifiers in more detail.
Class “ a class”
must be
declared
public. And
must be in a
named
package.

FIG. 10.2
As shown in Figure 10.2, the public field in the class “a class” is visible inside all of
its subclasses as well as inside all the client4 classes.

Protected fields and methods are visible and accessible in the derived classes and in
the classes in the same package, but not in any other classes. We discuss the
protected fields in more detail after we discuss the inheritance. The Figure 10.3
below shows the visibility of protected fields in more detail.

4
Client classes are the one, which may make use of “a class” either as a local variable or as a class
level variable.

Lecture Inheritance Page 6 of 112


Also visible to
clients inside
the package, in
which the class
“a class” is !!
Clients that lie outside
the package also lie
outside the area of
Need not lie inside the same
visibility!
package in which “ a class” is!
FIG. 10.3
As shown in Figure 10.3, the protected fields and methods are visible to all sub
classes and classes in the same package, but not to the clients that are outside the
package. A sub class may lie inside or outside the package.

Private fields and methods are not visible outside the class they are declared. Private
fields can only be accessed, outside their native class by using a public method to
allow access to them. Figure 10.4 shows the visibility of private fields and methods in
more detail. The sub-classes inherit the private members of super
class, but have no access to them. To access the private but inherited
members, the super class must have a public method available, which can get the
access to the private fields.

Lecture Inheritance Page 7 of 112


FIG. 10.4 Sub classes inherit the private
fields and methods but they do not
have direct access to them.

When fields and methods have no access modifier


attached (package private), the access to them is even
more restricted than the protected modifier. The
package private fields and methods are visible only
inside the package. In fact even subclasses of a class
that lies outside the package has no direct access to
them!

Lecture Inheritance Page 8 of 112


The Figure 10.5 below shows how the visibility of package-private fields and
methods work.

Package – Private or N o M odifier


Package
Field w ith no boundary
m odifier

a class
A rea of
Client 1 visibility.
C lients and
Subclass 2 subclasses,
Client 2 both m ust
Subclass 1 lie inside
the
package

FIG. 10.5

Inheritance
When we write a Java classes, we try to model a part of the reality of the world. For
example, when we write a complex number class, we model the behavior of complex
numbers in the class. However, in reality the things are related. By modeling the
related things together, we can see that how modeling one thing, can
help us model something related to it. Using Java’s mechanism of establishing
inheritance relationship between classes can model reality more effectively. Let us
take an example of vehicles in the world. Every vehicle has at least one property –
speed. We can write a class called vehicle, which has one data member called speed.
However, there are many kinds of vehicle in the world. For example, the vehicle
may be a wheeled vehicle, which will move on roads and surfaces or it may be an
airplane that will fly in air. Both vehicles such as airplane and vehicle with wheels
have a relationship with general concept vehicle. We can say that an airplane is-a
vehicle. We can also say that a vehicle with wheels is-a vehicle. When objects have
this “is-a” type relationship between each other, then an inheritance relationship
exists between them. Using this concept of “is-a” type relationship, we can set up an
inheritance hierarchy between vehicles of various types as follows (Figure 10.6).

Lecture Inheritance Page 9 of 112


Microsoft PowerPoint
Presentation

FIG. 10.6

Now, at each level of above inheritance hierarchy, new properties are added to the
system of related objects. For example, we may ask the question, as to what is the
most common property to all vehicles? Obvious answer is that all vehicles have
speed. So now, we take this system of inheritance relationships and start filling it
with properties. This is dynamically presented below.

Microsoft PowerPoint
Presentation

We can see that all vehicles have a property speed, and all airplanes have a property
called “engine thrust”. We keep adding one or more new property at each level of
inheritance derivation in our system. The Figure 10.7 below shows the result.

Lecture Inheritance Page 10 of 112


FIG. 10.7
Based on the inheritance relationship we established above, and based on the
properties assigned at each level, now we may start writing the code for this system
of related classes. However, let us look at few definitions here. These are
summarized in the Figure 10.8 below.

FIG. 10.8
At each level of inheritance, the class, which is the source of inheritance, is called a
base class or a super class. Moreover, the class that results from inheritance is called
a derived class of subclass. The phrase subclass should not be taken to mean that
somehow the derived class is “lesser” in some way. In fact, if anything it has more
data members. In the present system that we have built here, the Vehicle class is the
base class or super class, where as the with respect to the vehicle class, the class

Lecture Inheritance Page 11 of 112


Airplane is a derived class or subclass. We illustrate that in the Figure 10.9 and
10.10

FIG. 10.9

FIG. 10.10

Lecture Inheritance Page 12 of 112


Syntax For writing classes related by inheritance
Taking the example of the system of inheritance we built in the Figure 1 0.6, we
show the syntax for establishing the inheritance relationship between classes below
(Figure 10.11).

Uses the keyword


public class Vehicle extends to establish
{ inheritance!
//Fields and Methods
}

public class Airplane extends Vehicle


{
//Fields and Methods
}

FIG. 10.11
Generally in java classes that are not expected to be extended, the data members are
declared private. One characteristic of private data members is that, they are visible
to the methods in the class, but invisible to rest of the world. Inheriting from a base
class with all data members declared private complicates the matter somewhat. Java
allows another form of access specifier for the data members of a class, which makes
them invisible to world outside the class and its package, but visible to derived
classes. This specifier is called “protected”. As shown in Figure 10.3, the protected
data members are visible in the derived classes and in the client classes in the same
package.

Lecture Inheritance Page 13 of 112


public class Vehicle Visible to classes Airplane and
{ Jet. However, invisible to client
protected double speed; code, like main function, when
doing black box testing and
client lies outside the package.
}

public class Airplane extends Vehicle


{
protected int numberOfwings;
}

public class Jet extends Airplane


Visible to class Jet, but invisible
{ to client code, like main
protected double enginethrust; function, when doing black box
} testing and client lying outside
the package.
FIG. 10.12

By making the field of class Vehicle, for example in this case, the speed protected,
has the affect of class Airplane having two fields, speed and numberOfwings.
Similarly, the class Jet has three fields, speed, numberOfwings, and enginethrust.
What we do now is that we add fields, constructors, and a method called describe ( )
to all classes in the Figure 10.7. This results in the code given in Listing 10.5 below.

In Listing 10.5, the method describe for each class has a single output statement
describing the type of vehicle the class represents. The process by which a derived
class provides a specialized version of a method with same name as in its super class
is termed as overriding the super class method. If Vehicle class has a method called
describe and none of its sub classes have a method named describe then all sub
classes would inherit the describe method from class Vehicle. However if any of the
sub class provides a method named describe with same header, then sub class is free
to implement it in any way it chooses. Overriding methods of class super class
java.lang.Object is an important topic in Java, which will be discussed shortly. We
now show the source code for various classes from the Figure 10.7.

Lecture Inheritance Page 14 of 112


public class Vehicle
{
protected double speed;
Chains the constructor with no
public Vehicle( ) argument to the constructor
with speed as an argument!
{ Keyword this refers to calling
this (0.0); the constructor, in this case the
} one with one argument.

public Vehicle (double init_speed)


{
speed = init_speed;
}
public void describe( )
{
System.out.println ("I am an abstract Vehicle\n");
}
}

Listing 10.5 – Part A


There are two constructors in the Listing 10 .5 part A. The first one is argument-
less, and second one has arguments equal to the number of fields to be initialized in
the class. The two constructors are chained together. The chaining of constructors is
done as follows:
• Write the argument-less constructor first.
• From with in the argument-less constructor, call the constructor with one
argument using the reference operator “this”, and provide a default value for
the argument of the constructor.
• Inside the one argument constructor, set the value of the field, equal to the
constructor argument.
The biggest advantage of chaining constructors is that it allows us to set some
default values for the class fields. Java will always provide a constructor, even if one
is not authored, but hazards of doing that are too great at times. Besides, the
constructor provided by Java will set the class fields to some fundamental values,
which may not always be the best choice. Therefore, it is best to always write

Lecture Inheritance Page 15 of 112


constructors and chain them together. We modify the Listing 10.5 A somewhat by
putting an output statement inside each constructor. Figure 1 0.5 B to 10.5 G show
the code for all the classes diagrammed in the Figure 10.7. We discuss them starting
on page 22.

public class Vehicle


{
protected double speed;

public Vehicle()
{
this(0.0);
System.out.println ("From Vehicle CTOR #1");
}

public Vehicle( double init_speed)


{
speed = init_speed;
System.out.println ("From Vehicle CTOR #2");
}

public void describe()


{
System.out.println ("I'm an abstract Vehicle\n");
}
public double getSpeed( )
{
return speed;
}
}
Listing 10.5 – Part B

Lecture Inheritance Page 16 of 112


public class Airplane extends Vehicle
{
protected int numberOfWings;

public Airplane()
{
this(0);
System.out.println("From Airplane CTOR #1");
}

public Airplane( double init_speed)


{
this(init_speed, 0);
System.out.println("From Airplane CTOR #2");
}

public Airplane( double init_speed , int init_wings )


{
super(init_speed);
numberOfWings = init_wings;
System.out.println("From Airplane CTOR #3");
}

public void describe()


{
super.describe();
System.out.println("I'm a general Airplane.\nI travel “ +
through the air.\n");
}

public int getNumWings( )


{
return this.numberOfWings;
}
} Listing 10.5 – Part C

Lecture Inheritance Page 17 of 112


public class Proplane extends Airplane
{
protected int numberOfProps;

public Proplane()
{
this(0);
System.out.println("From Proplane CTOR #1");
}

public Proplane( double init_speed)


{
this(init_speed,0);
System.out.println("From Proplane CTOR #2");
}

public Proplane( double init_speed, int init_wings)


{
this(init_speed, init_wings, 0);
System.out.println("From Proplane CTOR #3");
}

public Proplane( double init_speed, int init_wings, int numProps)


{
super(init_speed, init_wings);
numberOfProps = numProps;
System.out.println("From Proplane CTOR #4");
}

public void describe()


{
super.describe();
System.out.println("I'm a PropPlane.\nI have propellers “ +
to fly.\n");
}
} Listing 10.5 – Part D

Lecture Inheritance Page 18 of 112


public class Jet extends Airplane
{
protected double engineThrust;
public Jet()
{
this(0);
System.out.println("From Jet CTOR #1");
}

public Jet( double init_speed)


{
this(init_speed,0);
System.out.println("From Jet CTOR #2");
}

public Jet( double init_speed, int init_wings)


{
this(init_speed, init_wings, 0.0);
System.out.println("From Jet CTOR #3");
}

public Jet( double init_speed, int init_wings, double thrust)


{
super(init_speed, init_wings);
engineThrust = thrust;
System.out.println ("From Jet CTOR #4");
}

public void describe()


{
super.describe();
System.out.println("I'm a Jet.\nI am propelled by a fast jet engine.\n");
}

public double getEngineThrust()


{
return engineThrust;
} Listing 10.5 – Part E
}

Lecture Inheritance Page 19 of 112


public class VehicleWithWheels extends Vehicle
{
protected int numberOfWheels;

public VehicleWithWheels()
{
this(0);
System.out.println("From VehicleWithWheels CTOR #1");
}

public VehicleWithWheels( double init_speed)


{
this(init_speed, 0);
System.out.println("From VehicleWithWheels CTOR #2");
}

public VehicleWithWheels( double init_speed , int init_wheels )


{
super(init_speed);
numberOfWheels = init_wheels;
System.out.println("From VehicleWithWheels CTOR #3");
}

public void describe()


{
super.describe();
System.out.println("I'm a general Vehicle With Wheels.\nI use “ +
wheels to travel on the land.\n");
}
} Listing 10.5 – Part F

Lecture Inheritance Page 20 of 112


public class Car extends VehicleWithWheels
{
protected double horsepower;

public Car( )
{
this(0.0);
System.out.println("From Car CTOR #1");
}
public Car( double init_speed)
{
this(init_speed, 0);
System.out.println("From Car CTOR #2");
}
public Car( double init_speed,int nWheels)
{
this(init_speed, nWheels, 0.0);
System.out.println("From Car CTOR #3");
}

public Car( double init_speed,int nWheels, double init_hp)


{
super(init_speed, nWheels);
horsepower = init_hp;
System.out.println("From Car CTOR #4");
}

public void describe()


{
super.describe();
System.out.println("I am a Car. I'm the most “ +
common wheeled vehicle.\n"); Listing 10.5 – Part G
}
}

Lecture Inheritance Page 21 of 112


Writing the Constructor for the derived classes:
Since the derived classes inherit a part of them from their super class, during the
construction of derived classes, the super class constructor is always called5. Note
that except the java class Object, all classes in java are derived classes!! Therefore,
any time a class is instantiated, the constructor of class Object is always called.

With exception of java class Object; ALL


classes in java are derived classes!!!
How can we confirm that an Object class constructor is always called, when any
java class is instantiated? We can do a very simple experiment to prove this. In
Listing 10.6, we create a class called AnyClass.

Listing 10.6
We create an instance Temp of class AnyClass by calling the operator new and
calling the default java provided constructor. Then we call an instance method
hashCode( ), to print the hash code for the Temp. The resulting output is shown in
the Figure 10.13 below.

FIG. 10.13
The class AnyClass does not have a method called hashCode. Therefore, where did
the method hashCode come from? It actually came from the class Object, which is
the super-class for AnyClass. Moreover, the Object part of AnyClass instance Temp
is built, when during the constructor call new AnyClass( ), the Object class

5
If derived class constructor does not make an explicit call to the super class constructor, then Java
will automatically call the default super class constructor.

Lecture Inheritance Page 22 of 112


constructor is called. This is done automatically, even if there is no constructor or no
explicit call to the super class constructor is made. The hashCode method call just
prints the memory location, where the object “Temp” happens to be located on the
heap part of the memory.
Looking at the Listing 10.5 C, we observe that for the class Airplane we have three
constructors, the argument-less, one argument and two arguments. The super class
constructor, using the word super is called from the two arguments constructor.

Testing Inheritance – Polymorphism in Action


The word Polymorphism means, “having many forms”. When a class is a base class
then it can hold the reference to the instances of all derived classes. A reference type
of base class then, can have many forms, as it can polymorph itself in forms to act
like any of its base classes. For example in the system of inheritance shown in
Listing 10.5 (also see Figure 10.7), the reference type Vehicle can point to the objects
of type Airplane, Jet, Proplane, car, and VehicleWithWheels. We test the
polymorphism in the Listing 10.7.
public class TestInheritance Veh1 points to an
{
public static void main(String[ ] args)
object of type Jet.
{
Vehicle Veh1 = new Jet(500,4, 200);
Jet class describe method
Veh1.describe( ); is called.
Veh1 = new Airplane(400, 2);

Veh1.describe( );
Veh1 now points to an
Veh1 = new Car ( 60, 4, 20); object of type Car.

Veh1.describe( ); Car class describe method is


called.
}
}
Listing 10.7 Comment [p1]: Figure 10.13,

The output of the Listing 10.7 is shown in the Figure 10.14.

Lecture Inheritance Page 23 of 112


FIG. 10.14 Comment [p2]: Listing 10.7

Sequence of Constructor Calls


In Listing 10.7, the statement below calls the Jet constructor,
Vehicle Veh1 = new Jet (500,4, 200);
The Jet class constructor, which takes three arguments, first calls its super class
constructor with parameter speed equal to 500 and number of wings equal to 4. The
super class to Jet is Airplane. The two-argument constructor in Airplane class calls
its super class constructor with the parameter speed equal to 500. Now although the
Vehicle class does not show an explicit call to a constructor to its super class (Java
Object class), an Object class constructor is nevertheless called. After that the speed
is set equal to 500 by executing the statement in Vehicle class one argument
constructor as:
speed = init_speed;

Therefore, in order to build an instance of Jet class, the constructor calls are made
in the following sequence (Figure 10.15).

Lecture Inheritance Page 24 of 112


Sequence of Construction of Jet
class instance
Object part is
Time created first!
Object
Constructor call

Vehicle Constructor call


Vehicle part
is created
Airplane Constructor call next

Jet part is
Jet Constructor call created Last!

FIG. 10.15 Comment [p3]: Listing 10.7

The Figure 10.14 shows the output statements coded in the constructors of Vehicle,
Airplane, and Jet class, when the Jet class constructor in the Listing 10.17 is called.
These output statements are:
From Vehicle CTOR #2
From Airplane CTOR #3
From Jet CTOR #4
There is no output statement in the Object class constructor so we do not see a
similar statement from that. However, the sequence of other three-constructor call
is similar to the sequence shown in the Figure 10.15. General conclusion drawn is as
follows:

In Java constructor calls are made in the sequence of inheritance hierarchy


of an object. The Java Object class constructor will ALWAYS be called
first, followed by the sequence of inheritance hierarchy of an object being
created.

Lecture Inheritance Page 25 of 112


Dynamic Binding or Late Binding
One powerful manifestation of polymorphism is dynamic binding or late binding.
We emphasized earlier that a derived class inherits ALL data and methods from a
super class. In Listing 10.5, the method describe exists in all classes, which means
that sub classes override the describe methods of their super classes. The second
statement in Listing 10.7 makes a call to the method describe as follows:
Veh1.describe( );
Veh1 is a reference of type Vehicle. How does it know:
• That it is pointing to a Jet type object
• That Veh1.describe ( ) must call the describe method
from Jet class?
The answer to the first question lies in fact that all constructor calls are made at the
run time, when an object is created on the heap part of the memory. At run time
when Veh1 points to the Jet type object, Java Virtual machine (JVM) records that
fact. Also all the instance method calls (instance of a class calling a non-static
method) are resolved not at the compile time, but at the run time6. Then JVM
correctly binds the object type to the method that belongs to the object. This
happens irrespective of the type of reference pointing to the object. Therefore, even
though in statement Veh1.describe ( ), the Veh1 is a Vehicle reference type, JVM
knows that Veh1 is pointing to a Jet type object and at run time the describe method
from Jet class is invoked, giving the output (Figure 10.14):
I'm an abstract Vehicle

I'm a general Airplane.


I travel through the air.

I'm a Jet.
I am propelled by a fast jet engine.
The mechanism where JVM will correctly bind an object to “its” method at run
time is called dynamic binding, late binding, or run time binding.

Limitations of Dynamic Binding


Calling describe method for a Jet Object using the Vehicle Class reference worked
because both Vehicle as well as Jet have a method called describe with identical
header. What if we remove the method describe from the class Vehicle? When we
remove the method describe from the Vehicle class and try to compile the Listing
10.7, we get the following compiler errors:
TestInheritance.java:14: cannot resolve symbol
symbol : method describe ( )

6
All the static or class method calls are resolved at the compile time.

Lecture Inheritance Page 26 of 112


location: class Vehicle
Veh1.describe( );
^
TestInheritance.java:19: cannot resolve symbol
symbol : method describe ()
location: class Vehicle
Veh1.describe( );
^
TestInheritance.java:21: cannot resolve symbol
symbol : method describe ()
location: class Vehicle
Veh1.describe( );
All of a sudden because of absence of describe method from the Vehicle class, the
Vehicle reference Veh1 can no longer bind to the describe methods in its descendent
objects. This is because JVM knows how to correctly bind the method name and
object type, only when the method with the same header exists in the super class and
sub class. A super class reference, pointing to a subclass object has no way of
knowing about those methods, which do not also exist in the super class. The super
class reference to a sub class object in such case is only usable by using the
instanceof operator and by proper type casting7. This is shown in Listing 10.8.
public class TestInheritance
{
public static void main(String[ ] args) If Temp is type Jet,
{ then instanceof will
Object Temp = new Jet(500, 4, 200); return true otherwise it
will return false.

if(Temp instanceof Jet)


{ Now it is safe to cast
Jet Jet1 = (Jet)(Temp); Temp into Jet Type
Jet1.describe();
System.out.println("The speed of Jet = " +
Jet1.getSpeed());
System.out.println ("The number of wings in Jet = "
+ Jet1.getNumWings( ));
System.out.println ("The Engine thrust for Jet = " +
Jet1.getEngineThrust( ));
}

7
We describe up-casting and down casting between references related by inheritance in the chapter
on Runtime Type Identification (RTTI).

Lecture Inheritance Page 27 of 112


}
Comment [p4]: Figure 10.15
} Listing 10.8
In Listing 10.8, the Boolean expression inside the if clause first decides whether the
Temp is indeed type Jet or not? If Temp is not of type Jet, then instanceof operator
will return a false and the statements in the scope of if clause will not be executed.
But if Temp is indeed type Jet, then instanceof operator returns a Boolean true, and
the statements in the scope of if clause are executed. Then it becomes safe to cast the
Temp to Jet type reference, since we already know that it is Jet type. After that, all
the Jet class instance methods can be called using the new reference Jet1 (Listing
10.8). The results of running Listing 10.8 are shown in Figure 10.16.

FIG. 10.16 Comment [p5]: Listing 10.8

One can see that all Jet class methods are called properly and they give proper
results by following the procedure described in the Listing 10.8.

Further advantages of polymorphism will be discussed after we have discussed the


interfaces and Java’s limited form of multiple inheritance.

Lecture Inheritance Page 28 of 112


Preventing Inheritance
Some times for security and other reasons it is necessary that another class never
inherits a class. Defining a class final prevents it from another class inheriting it. All
wrapper and String related classes in java.lang package are final classes. The syntax
of defining a class to become final is as follows:

public final class FinalClass


{
//-----------------------------
}
A compile error will result if another class tries to extend the class FinalClass. An
important example of a Java class that is defined as final is Java String class. Once a
String object is created by its constructor, it can never be altered because the String
class is a final class and it has no methods to alter its data fields. Such objects are
called immutable objects. Strings are used as username and passwords in the Java
Web Services environments. Their immutability makes Java network transactions
more secure. All Java wrapper classes such as Integer, Double, and Boolean etc. are
also immutable and final classes.

Interfaces in Java
The fundamental unit of programming in java is a class, but in object oriented
programming, the fundamental design unit is a reference type. Interfaces are a way
to define reference types with out defining a class. This adds to Java’s power of
object-oriented programming. Interfaces define reference types in abstract form as
a collection of public method headers and static constants. Interface contains no
implementation of methods; therefore, we can say that an interface is an expression
of pure design. On the other hand, the classes are mixture of design and
implementation. Java classes can implement interfaces by using the keyword
implements. For example if I design an interface called ElCaminoCollegeInterface
and then get a class Student to implement it, then class Student would be written as
follows:

public class Student implements ElCaminoCollegeInterface { /*code*/}

The classes that implement interface are agreeing to a design contract


enforced by the interface method headers and static constants. The
method names inside the interface are “holy”. They cannot be changed by the
implementing subclasses. This is crucial in Graphical Interface Programming in
Windows, where when the user clicks on an icon, or presses a key on the keyboard,
the Operating System fires an event object to the program and then in order to
respond to the user action, the program must execute a certain method. There is a

Lecture Inheritance Page 29 of 112


contract with the operating system that if “you send me an object name
X, I will execute the method name Y”. This contract cannot be violated.
Implementation of methods named inside the interfaces enforces this contract.
Interface can contain zero or more abstract methods and/or public static final fields
(see sidebar below). The interfaces with no methods in them can be considered
marker interfaces. Interfaces are also stored in .java files, just the way classes are.

public interface SomeInterface


{
/*Can contain zero or more public abstract methods
and zero or more public static final fields.
Cannot contain private or protected fields or methods.
Cannot contain instance or class variables.*/
}

What is an abstract method? An abstract method simply provides the proto-type of


a method, which is a header without a body. The syntax of writing an abstract
method is as follows:

[Access Specifier] [Other Specifier] abstract returnType methodName


([Argument List]);

In above list the entities inside square brackets are optional. Inside an interface only
return type, method name and argument list are required. Abstract methods can be
specified with in classes also, in which case they would need the keyword abstract
attached in front. Most important thing is that abstract methods have no method
body.

Interface can be implemented by a class or be extended by another interface. A class


can implement more than one interface. The class implementing an interface can
implement the inherited abstract methods in any manner in which the designer of
the class chooses to do so. The syntax of implementing and writing an interface is as
follows:

The class implementing a java interface uses keyword implements to implement it.
(see below).

Lecture Inheritance Page 30 of 112


public class SomeClass implements SomeInterface
{
/*Inherits all the methods and static constants from
SomeInterface.
Must provide implementation (code) for all the inherited
methods else be declared as an abstract class explicitly using
the keyword abstract*/
}

A class implementing an interface must either provide implementation of all of its


methods or be declared as an abstract class8. For example let us take a system of an
interface MyInterface, a class implementing it MyClass, and a driver class
DriverMyClass to test MyClass (Listing 10.9)
public interface MyInterface
{
void printHello( );
}

public class MyClass implements MyInterface


{
public void printHello()
{
System.out.println("Hello from implemented method of "
+" interface MyInterface");
}
}
/////////////////////////////////////////////////////////
public class DriverMyClass
{
public static void main(String[] args) If method printHello is
{ commented out then all
MyClass MC1 = null; statements in main will give
MyClass MC2 = new MyClass( ); compile error!
MC2.printHello();
}
}//Listing 10.9 Comment [p6]: Figure 10.16

8
Abstract class cannot be instantiated, though it can be used as a reference type. We discuss abstract
classes shortly.

Lecture Inheritance Page 31 of 112


In implementing interface MyInterface the class MyClass adheres to a contract that
it would provide a body for the method printHello whose header is designed in
MyInterface. Therefore inside the main method of driver class DriverMyClass, or
elsewhere the MyClass will behave like a normal class in the sense that it can be
instantiated and its public methods can be called. The execution of main method in
Listing 10.9 will print to console a string “Hello from implemented method of
interface MyInterface".

However, as soon as the method printHello in class MyClass is commented out, all
statements inside the main will give a compile error shown in the Figure 10.17.
DriverMyClass.java:7: cannot resolve symbol
symbol : method printHello ( )
location: class MyClass
MC2.printHello();
^
.\MyClass.java:1: MyClass is not abstract and does not override abstract method
printHello() in MyInterface
public class MyClass implements MyInterface
^
2 errors
FIG. 10.17 Comment [p7]: Listing 10.9

The main thrust of compile errors is error #2, where compiler indicates that class
MyClass is breaching the contract with interface MyInterface by not overriding or
implementing the method printHello. If one declares the class MyClass abstract
using the syntax:

public abstract MyClass implements MyInterface


{

then the statement

MyClass MC1 = null;

will compile, however one still cannot instantiate the abstract class MyClass to
create instance MC2. Therefore classes not overriding or implementing the methods
from their implemented interface must be declared abstract explicitly by using
keyword abstract.

Interfaces can have inheritance relationships between themselves as well. An


interface can be “extended” from one or more interfaces. The syntax is as follows:

Lecture Inheritance Page 32 of 112


public interface SomeInterface extends Interface1
{

}
public interface SomeInterface extends Interface1, Interface2
{

}
Note that keyword “extends” is used when an interface extends another interface.

We show an example of writing a java interface and its implementation in Listing


10.10 (A-C) below.

public interface Door


{ Only abstract methods!!! Use
public void open( ); of access specifier public is
public void close( ); optional and can be left out.
}//Listing 10.10A
Provides implementation
for all the methods
inherited from interface
public class CarDoor implements Door
Door!
{
public void open( )
{
System.out.println (“Watch traffic. Enter the car”);
}
public void close( )
{
System.out.println ( "Look out, closing the door");
}

}//Listing 10.10B

public class TestDoor A reference of type Door


{ can point to an object of
public static void main( String[ ] args ) type CarDoor because
{ CarDoor is-a Door.
Door Instance1 = new CarDoor( );

Lecture Inheritance Page 33 of 112


Instance1.open( );
CarDoor Instance2 = new CarDoor( );
Instance2.close( );
}
}//Listing 10.10C Comment [p8]: Figure 10.17

As one knows that a door has two main processes – open the door or close the door.
Therefore the interface Door is given two abstract methods open and close, and in
this case, both are void method and take no arguments. Now, lots of objects in world
have doors. Homes have doors. Cars have doors. Trucks have doors. To the degree
that behaviors of all doors (in cars, homes, trucks) is same (they all open or close),
the classes for these objects can all implement interface Door. In this sense the
interfaces design behavior of objects! Of course all classes implementing Door
interface can implement their interface methods open and close in their own way.
For example the message printed by the close method of class HomeDoor may be
different from the one for class CarDoor as per its needs.

Once a class implements an interface it also develops an inheritance relationship


with the implemented interface. For example we can say that a Car Door is-a Door.
Or a Home Door is-a Door. And as discussed earlier under polymorphism, the
inherited class instance can be pointed to by a reference of type of its super class.
Therefore the reference type Door can hold the address of a CarDoor type object
created on heap (first statement in the main method in Listing 10.10C). Figure 10.18
shows the inheritance relationship between interface Door and class CarDoor.

Lecture Inheritance Page 34 of 112


FIG. 10.18 Comment [p9]: Listing 10.10

The diagram simply means that CarDoor is a subclass or derived class from
interface Door. If contract to implement methods open and close is kept then a
reference of type Door can hold the address of object of type CarDoor. Therefore
the first statement in the main method of class Test Door given below compiles fine.

Door Instance1 = new CarDoor( );

Now the Instance1 (which is a Door type reference) can be used to call any of the
methods inherited from interface Door by the class CarDoor. Thus Intance1.open
would execute the code inside the open method in CarDoor class. Implementing an
interface, apart from forming a contractual relationship of implementing interface
methods, also provides an additional reference type for a class. The output of
Listing 10.10C is shown in Figure 10.19.

FIG. 10.19 Comment [p10]: Listing 10.10

Lecture Inheritance Page 35 of 112


Multiple Inheritance Using Java Interfaces
Java interfaces can provide a limited form of multiple inheritance, in the sense that
more than one reference types can represent any class that implements more than
one interface. Figure 10.20 below shows the most difficult case of multiple
inheritance, which is also called the “diamond” multiple inheritance.

In C++ Person,
Person Student, Voter, and
StudentVoter can
all be classes!

Student Voter

StudentVoter

FIG. 10.20 Comment [p11]: Listing 10.10

C++ allows classes to be derived as a result of multiple inheritances. Therefore in


C++, Person, Student, Voter and StudentVoter can all be classes. The class
StudentVoter may inherit the fields and virtual functions from all of its super
classes. This at times may cause ambiguities and special care is needed to remove
them. Java however, would not allow the inheritance shown in Figure 10.20 if all the
entities shown are coded as classes. One allowable scenario in java is that entities
Person and Voter are declared as interfaces, and then Student and StudentVoter
can be declared as classes (Figure 10.21).

Lecture Inheritance Page 36 of 112


In java, diamond
inheritance as this
Figure is possible by
making entities Person
Person and Voter as Interfaces.

Voter
Student

StudentVoter

FIG 10.21 Comment [p12]: Listing 10.10

The advantage of such multiple inheritance is that an object of StudentVoter Class


may be represented by a reference of following types: Object, Person, Student,
Voter, and StudentVoter. This is one of the key advantages of multiple inheritance.
Limitation however is that unlike C++ in java, Person and Voter being interfaces,
they cannot contain any protected and instance fields. Java in this sense only
allows “behavioral” multiple inheritance.

Codes for classes and interfaces in Figure 10.21 are shown in Listing
10.11. The UML diagram for Figure 10.21 is shown in the Figure 10.22

Lecture Inheritance Page 37 of 112


StudentVoter
Shown on next page!

Lecture Inheritance Page 38 of 112


FIG. 10.22
As shown in the UML diagram, we put two methods in the interface Person
getName( ) and getAge( ). These methods relate to the fact that each person will
have an age or name. More methods may be added in the Person interface, but for
the illustration purpose two methods include would suffice. The coded person
interface is shown below in the Listing 10.11 Part A.
public interface Person
{

String getName( );

int getAge( );
}
Listing 10.11 Part A Comment [p13]: Figure 10.22

Interface Voter extends interface Person. That means that the methods in the
Person interface are also automatically inherited by the interface Person. We
however, include some static constant strings in the Voter interface to hard code the
possible party a student voter may be member of. We also include a method
getParty( ) in the Voter interface, which returns the party of the student voter as a
string. The coded Voter interface is shown in the Listing 10.11 Part B.

Lecture Inheritance Page 39 of 112


public interface Voter extends Person
{
String PARTY1 = "Republican";
String PARTY2 = "Democrat";
String PARTY3 = "Liberatarian";
String PARTY4 = "Independent";
String PARTY5 = "None";

String getParty( );
}
Listing 10.11 Part B Comment [p14]: Figure 10.22

After coding the two interfaces, now we can code the necessary classes. First, we Comment [p15]: Figure 10.22
code the class Student, which derives from interface Person. Class Student has
name, age and gpa as fields, and we have shown all the necessary chained
constructors (Listing 10.11 Part C). Since Person interface is implemented by the
class Student, we provide the implementation of the methods getAge( ) and
getName( ). We also code some helper methods such as getGpa( ), and toString( ).
The method getGpa( ) is unique to class student, as only a person, who is a student
can have gpa. The toString ( ) method overrides the corresponding method in the
Object class. The code for the class Student is shown in the Listing 10.11 Part C.
public class Student implements Person
{
protected String Name;
protected int age;
protected double gpa;
//Chained constructors
public Student()
{
this("");
}

public Student(String Init_Name)


{
this(Init_Name,0);
}

public Student(String Init_Name, int init_age)


{
this(Init_Name, init_age, 0.0);
}

public Student(String Init_Name, int init_age, double init_gpa)


{
this.Name = Init_Name;
this.age = init_age;

Lecture Inheritance Page 40 of 112


this.gpa = init_gpa;
}

//Implementation of inherited abstract methods


public String getName()
{
return this.Name;
}

public int getAge()


{
return this.age;
}

//Other helper methods

public double getGpa()


{
return this.gpa;
}

public String toString()


{
String Str = "The name is = " + this.Name + "\n";
Str += "The age = " + this.age +"\n";
Str+= "The GPA = " + this.gpa + "\n";
return Str;
}
}
Listing 10.11 Part C Comment [p16]: Figure 10.22

The class StudentVoter extends Student and implements interface Voter. Note that
since class Student already implemented the abstract methods from Person class,
the class StudentVoter need not do that, unless it wishes to provide a specialized
version of the interface methods by overriding them. The general rule that applies
here is that if any of the super-classes implement the methods of an interface, they
are already available to all sub-classes. However, the StudentVoter must implement
the abstract method getParty( ) from the Voter interface. The StudentVoter class
introduces two new fields, the date of last vote (lastvote) and Party of the
StudentVoter (Party). This is because the StudentVoter inherits all the fields from
the Student class, it in effect, has five fields and needs six chained constructors. It
has helper methods such as getLastVote and over-rides the toString method from
object class9. Listing 10.11 Part D shows the code for the class StudentVoter.

9
We discuss overriding the Object class methods in more detail later.

Lecture Inheritance Page 41 of 112


public class StudentVoter extends Student implements Voter
{
private int lastvote; //records the year of last vote 0 for new voter
private String Party;
//Constructors
public StudentVoter()
{
this("");
}
public StudentVoter(String Init_Name)
{
this(Init_Name,0);
}
public StudentVoter(String Init_Name, int init_age)
{
this(Init_Name, init_age, 0.0);
}
public StudentVoter(String Init_Name, int init_age, double init_gpa)
{
this(Init_Name, init_age,init_gpa,0);
}
public StudentVoter(String Init_Name, int init_age, double init_gpa,
int init_lastvote)
{
this(Init_Name, init_age,init_gpa,init_lastvote,"");

}
public StudentVoter(String Init_Name, int init_age, double init_gpa,
int init_lastvote, String Init_Party)
{
super(Init_Name, init_age,init_gpa);
this.lastvote = init_lastvote;
if(Init_Party.equals(StudentVoter.PARTY1))
this.Party = PARTY1;
else if(Init_Party.equals(StudentVoter.PARTY2))
this.Party = PARTY2;
else if(Init_Party.equals(StudentVoter.PARTY3))
this.Party = PARTY3;
else if(Init_Party.equals(StudentVoter.PARTY4))
this.Party = PARTY4;
else if(Init_Party.equals(StudentVoter.PARTY5))
this.Party = PARTY5;
else
{
System.out.println("Bad party name. Setting party to none.");
this.Party = PARTY5;

Lecture Inheritance Page 42 of 112


}
}
//Implementation of inherited abstract methods
//Only Voter interface methods need be implemented
//Since the Person interface methods are already implemented by the
//Super class Student
public String getParty()
{
return this.Party;
}
//Helper methods
public String toString( )
{
String Str = super.toString();
Str += "The year of last vote = " + this.lastvote + "\n";
Str += "The party affiliation is = " + this.Party + "\n";
return Str;
}
public int getLastVote( )
{
return this.lastvote;
}
}
Listing 10.11 Part D Comment [p17]: Figure 10.22

The class TestDiamond is written to test the diamond inheritance formed by the
interfaces and classes and is shown in Listing 10.11E. We create three objects, two
of type StudentVoter and one of type Student. The references used to point to them
are StudentVoter, Student and Person. In creation of all objects we call the
constructor with largest number of arguments for that class. The object STVoter1 is
of type StudentVoter. It can be printed directly by the System.out.println because
the method toString ( ) of StudentVoter class is overrides the object class toString
method to correctly print the StudentVoter objects. The methods getName, getAge,
getGpa, getParty are easily called using STVoter1 because STVoter1 is a
StudentVoter Type reference pointing to a StudentVoter type object.

Next we create a Person type reference Person_Gen which points to a Student


object. This is now polymorphism in play, as one can use a Person type reference to
point to Student or StudentVoter object. The Person_Gen reference being a Person
type can only be used to call the methods of Person interface on the object of type
Student. Therefore one can only call methods getName and getAge. Attempt to call
method getGpa will cause compile error, but if Person_Gen is cast into a reference
of type Student, then a call to getGpa method can be made easily. We assign an
additional reference to object being pointed to by Person_Gen. This additional
reference is Student type called Stu1. Then we go ahead and use Person_Gen
reference to point to a new object of StudentVoter type (name field for this object
being “Barney Bush”). This is possible because a StudentVoter is also a Person type.

Lecture Inheritance Page 43 of 112


public class TestDiamond StudentVoter type
{ object being
public static void main(String[] args) pointed to by same
{ type reference.
StudentVoter STVoter1 = new StudentVoter("Elliot John",
23,3.92,1998,"Republican");
System.out.println(STVoter1);
System.out.println("The party of "+ STVoter1.getName() + " is "
+ STVoter1.getParty( ));
System.out.println("The age of "+ STVoter1.getName() + " is "
+ STVoter1.getAge( ));
System.out.println("The year of last vote by "+ STVoter1.getName()
+ " is " + STVoter1.getLastVote( ));
System.out.println("The gpa of "+ STVoter1.getName()
+ " is " + STVoter1.getGpa( ));
//Showing Multiple inheritance behavior
//A reference of type Person can point to both Student and
//Student Voter
Person Person_Gen = new Student("Mary Smith",29,3.0);
Person Stu1 = Person_Gen;
System.out.println("\n" + Person_Gen);
System.out.println("The age of "+ Person_Gen.getName() + " is "
+ Person_Gen.getAge( ));
/*uncommneting the code below will cause compile error
Because getGpa cannot be called with Person Type reference
Person_Gen must be cast into a Student type reference.*/
/*System.out.println("The gpa of "+ Person_Gen.getName()
+ " is " + Person_Gen.getGpa( ));*/
System.out.println ("The gpa of "+ Person_Gen.getName()
+ " is " + ((Student)(Person_Gen)).getGpa( ));

Person_Gen = new StudentVoter("Barney Bush",45,3.99,1996,"Democrat");


System.out.println("\n" + Person_Gen);

Person [ ] Array = {STVoter1,Stu1,Person_Gen};


//Calling the polymorphic sort method
selectionSort(Array);
//Print the sorted array
System.out.println ("Printing the sorted array - sorted based on name.");
for (int ind=0; ind<Array.length; ind++)
System.out.println (Array [ind]);
}
/**The method selection sort accepts an array of type
* person and sorts the array alphabetically based on name.Reference
* to sorted array can be used to print the array in the caller method
*/

Lecture Inheritance Page 44 of 112


public static void selectionSort(Person [ ] list)
{
Person largest = null;
int length = list.length;
int passCount ;
int L_Index ;
int S_Index;
for ( passCount = 0 ; passCount < length ; passCount++ )
{
largest = list[0];
L_Index = 0; //Find the index of largest
for ( S_Index=0; S_Index < (length - passCount) ; S_Index++ )
{
if((largest.getName()).compareTo(list[S_Index].getName())<0)
{
L_Index = S_Index;
largest = list [S_Index];
}
}
list [ L_Index ] = list [ length - (passCount+1) ] ; //swap now
list [ length - (passCount+1) ] = largest ;
}
}
}
Listing 10.11 Part E Comment [p18]: Figure 10.22

Polymorphic Sorting Method


The power of polymorphism and multiple inheritance is shown in Listing 10.11-E in
form of polymorphic methods selectionSort, which takes an array of Person type as
an argument and sorts the array alphabetically based on first name. Notice that the
beauty of this method is that Person array passed to it may have all elements as
• Student Type
• StudentVoter Type
• Mixture of Student and StudentVoter both.
Still, the method will sort the array correctly based on the name in alphabetical
order. The results of test run based on Listing 10.11 Part E (TestDiamond class) are
shown in Figure 10.23. We see that all class objects represented by their respective
objects behave as expected. Next we create an array of type Person, and put three
objects in it, which are respectively, of type StudentVoter, Student, and
StudentVoter. Their references are mixed type. The first one has a reference of type
StudentVoter (STVoter1), the second one of type Student (Stu1) and third of type
Person (Person_Gen). Person array can hold any of the reference types shown in
Figure 10.23.

Lecture Inheritance Page 45 of 112


The polymorphic
method selectionSort
sorts the Person type
array alphabetically.

FIG. 10.23 Comment [p19]: Listing 10.11

The method selectionSort is a standard sorting method, which works based on a


well-known comparison based sort principle of array sorting technology. The
method looks for the object, which has the largest member (in this case the name)
and bubbles it to the end of the array. The maximum number of passes required to
sort the array are one less than the array size.

We can see very clearly from the results that the polymorphic method selectionSort
works nicely as it takes an array of mixed Student and StudentVoter type objects
and sorts them in the alphabetical order by the name. Becoming able to write
polymorphic methods is another main advantage of inheritance in Java.

Lecture Inheritance Page 46 of 112


Abstract Classes
Object oriented languages as Java and C++ use a concept of abstract classes, so that
an object of certain type can be conceptualized and then extended further. For
example, take the concept of round shapes in geometry. The roundness is a property
that is present in many different forms in real objects. The circle, spheres, and,
elliptical objects have roundness. However, the concept roundness is a bit abstract,
so if we wrote a class to capture this concept, we may never be able to truly find a
real object for which the class Roundness can be a template. The concepts and
behaviors, that apply to other objects, but are too abstract to make concrete, are
often written in the form of abstract classes. In java, the abstract classes have
following main properties.

Abstract Class
1. The abstract class has at least one abstract method. An
abstract method is a method, which has no body or definition.
It just has a signature and return type.
2. The usefulness of abstract class lies in it being
extended by other classes or other classes being derived
from it.
3. An abstract class cannot be instantiated, though it can
be used as a reference type for the sub class objects.

FIG. 10.24 Comment [p20]: Listing 10.11

Example of an abstract class and its extension.


Let us consider the following inheritance hierarchy (Figure 10.25).

Abstract_Shape_I
nher.ppt

Lecture Inheritance Page 47 of 112


FIG. 10.25 Comment [p21]: Listing 10.11

A shape is a general abstract concept. We know that a shape can have area and in
some cases volume. A shape certainly has a name. However, shape is abstract
enough that we can define an abstract class called Shape to model it. We would
never need an instance of class Shape because there is no real object in the world
that is called “Shape”.

Now there can be many types of shapes. A point is a shape, which is infinitesimal in
size. However, it has properties such as coordinates x and y in the Cartesian system.
Therefore, the Class Point can extend the general concept of Shape to a concrete
form. Hence, we derive the class Point from Shape.

A Square has a center point just like a Point and a class Square can inherit the
coordinates x and y from class Point. Nevertheless, Square shape has additional
property like a length or edge. Therefore, we derive the class Square from Point.

Finally, a Cube has the same properties or fields as the Square does – like a central
point, and an edge, but has a volume, which square does not have. Yet, no new fields
are needed if we were to derive the class Cube from class Square.

Converting the Inheritance Design Into The Source Code:


Now we convert the above design into source code, first by writing various classes in
the inheritance hierarchy and then writing a driver class program to test them.

Lecture Inheritance Page 48 of 112


Uses the
keyword
class Shape abstract
The Listing 10.12 below gives the code for the abstract class Shape.

Implemented
Methods

Abstract
Method

Comment [p22]: Figure 10.25


Listing 10.12
The class Shape is an abstract class because it has one un-implemented
(abstract) method getName( ). The syntax requires that the keyword
“abstract” be included in the declaration of method signature.

A class can also become abstract if it derives from an abstract class and
does not provide implementation for the abstract methods for its
parent. The keyword abstract would be then required in class
declaration.

Lecture Inheritance Page 49 of 112


class Point
The source code for the class Point is given below in the Listing 10.13
public class Point extends Shape
{ Fields are x and y
protected int x; coordinates for the
protected int y;
Point.

public Point()
{ Default and
this(0);
explicit
}
constructors,
public Point(int a) all chained
{ together.
this(a,0);
}
public Point(int a, int b)
{
this.x = a;
this.y = b;
}
abstract method from
public String getName() the parent class Shape
{ implemented.
return "Point";
}

public void setPoint(int a, int b)


{
this.x = a;
this.y = b;
}

public void setX(int x1) Other


{ methods of
this.x = x1; class Point.
}

public void setY(int y1)


{
this.y = y1;
}

public int getX()

Lecture Inheritance Page 50 of 112


{
return this.x;
}

public int getY()


{ Overrides the toString
return this.y; method from Object
} class.

public String toString( )


{
return "[" + this.x + ", " + this.y + "]";
}
}
Listing 10.13 Comment [p23]: Figure 10.25

class Square
The source code for the class Square is given below in the Listing 10.14.
public class Square extends Point
{
protected double edge; New field edge is
added. It inherits x
public Square() and y.
{
this(0.0);
}

public Square(double edge1) Constructors


{
this(edge1,0,0);
}

public Square(double edge1, int a)


{
this(edge1, a, 0);
}

public Square(double m_edge, int a, int b)


{ Methods
super(a,b);
setEdge(m_edge);
}

public void setEdge(double m_edge)


{

Lecture Inheritance Page 51 of 112


this.edge = (m_edge >= 0 ? m_edge : 0 );
}

public double getEdge()


{
Overrides the
return this.edge;
super class
}
methods
public double area( )
{
return this.edge*this.edge;
}

public String toString( )


{
return "center = " + super.toString() + " ; Edge = " + this.edge;
}

public String getName()


{
return "Square";
}
}//End of class Square
Listing 10.14 Comment [p24]: Figure 10.25

class Cube
The source code for the class Square is given below in the Listing 10.15. Does not
need any new fields.
public class Cube extends Square
{
public Cube()
{ Constructors
this(0.0);
}
public Cube(double edge1)
{
this(edge1,0,0);
}

public Cube(double edge1, int a)


{
this(edge1, a, 0);
}
public Cube(double m_edge, int a, int b)

Lecture Inheritance Page 52 of 112


{
super(m_edge, a , b);
}
Overrides the super
class methods.
public double volume()
{
return this.edge*this.edge*this.edge;
}

public double area()


{
return 6*this.edge*this.edge;
}

public String toString( )


{
//return super.toString() + " ; Height = " + this.edge;
return super.toString();
}

public String getName()


{
return "Cube";
}
}//end of class Cube
Listing 10.15 Comment [p25]: Figure 10.25

The UML(Unified Modeling Language) diagram for all these classes is given on next
page (Figure 10.26).

Lecture Inheritance Page 53 of 112


FIG. 10.26 Comment [p26]: Listing 10.15

Testing of Classes in Figure 10.26


Listing 10.16 provides a main method to test the classes in Figure 10.26, where the
class on the top of hierarchy, Shape is an abstract class.
00001 import javax.swing.JOptionPane;
00002 import java.text.*;
00003
00004 public class TestShapes
00005 {

Lecture Inheritance Page 54 of 112


00006 public static void main(String[] args)
00007 {
00008 DecimalFormat precision2 = new DecimalFormat( "0.00" );
00009 boolean done = false;
00010 String Input = "";
00011 String Output = "";
00012
00013 while(!done)
00014 {
00015 Input = JOptionPane.showInputDialog("Please enter the "
00016 +"x coordinate of the shape.\n");
00017 int x_cord = Integer.parseInt(Input);
00018 Input = JOptionPane.showInputDialog("Please enter the "
00019 +"y coordinate of the shape.\n");
00020 int y_cord = Integer.parseInt(Input);
00021 Input = JOptionPane.showInputDialog("Please enter the "
00022 +"edge of the shape. Enter 0 for the point.\n");
00023 double edge = new Double(Input).doubleValue();;
00024 Shape Gen_Shape = null;
00025 if(edge == 0)
00026 {
00027 Gen_Shape = new Point( x_cord,y_cord);
00028 Output = Gen_Shape.getName() + ": " + Gen_Shape.toString() + " ; "
00029 + "Area of Point = " + precision2.format(Gen_Shape.area())+ " ; "+
00030 "Volume of Point = " + precision2.format(Gen_Shape.volume());
00031 }
00032 else
00033 {
00034 Input = JOptionPane.showInputDialog("Please enter "
00035 +"whether the data you just entered are for [S]quare or [C]ube");
00036 if(Input.equals("S") || Input.equals("s"))
00037 {
00038 Gen_Shape = new Square(edge,x_cord,y_cord);
00039 Output = Gen_Shape.getName() + ": " + Gen_Shape.toString() + " ; "
00040 + "Square Area = " + precision2.format(Gen_Shape.area())+ " ; "+
00041 "Square Volume = " + precision2.format(Gen_Shape.volume());
00042 }
00043 else if(Input.equals("C") || Input.equals("c"))
00044 {
00045 Gen_Shape = new Cube(edge,x_cord,y_cord);
00046 Output = Gen_Shape.getName() + ": " + Gen_Shape.toString() + " ; "
00047 + "Cube Area = " + precision2.format(Gen_Shape.area())+ " ; "+
00048 "Cube Volume = " + precision2.format(Gen_Shape.volume());
00049 }
00050 }
00051

Lecture Inheritance Page 55 of 112


00052 JOptionPane.showMessageDialog(null, Output);
00053
00054 Input = JOptionPane.showInputDialog("More shapes? "
00055 +"Enter [Y]es to continue or [N]o to exit.\n");
00056 if(Input.equals("Y") || Input.equals("y"))
00057 done = false;
00058 else
00059 done = true;
00060 }
00061 System.exit(0);
00062 }
00063 }
//Listing 10.16 Comment [p27]: Figure 10.26

The purpose of this program is to get from the user the properties of shapes and
then display properties, such as central coordinates of shape, and if relevant then
display its area and volume. The coordinates of the center of a Shape, be it a point,
square or cube would not change with its type. In Lines (L10.16#15-20), user input
for Shape’s center x, y coordinates are accepted and parsed. The user is prompted
to input the edge of the Shape or zero if the Shape is a point (L10.16#21-23).
Understand that all instantiable objects such as Point, Square and Cube are derived
from super class Shape. Therefore the reference type Shape can hold the address of
any of them. We declare a general Shape type reference Gen_Shape (L10.16#24). If
data for edge entered by the user were zero, then it is certain that the shape is a
point. In that case the first if block is executed (L10.16#24-31). Inside the if block the
final point object is constructed with user provided center coordinates x_coord and
y_coord (L10.16#27), and a super class reference Gen_Shape points to this derived
class Point object. An Output String is built to describe the properties of this Shape
object, first by getting its name, and central coordinates by calling member methods
getName and toString (L10.16#28). Then to add its area and volume to the overall
description, the methods area and volume are called (L10.16#29-30). Understand
that class Point does not actually have the coded area and volume methods, and it
automatically binds to its super class Shape’s implemented methods area and
volume for their execution. The JOptionPane outside the else block displays the
properties of the Shape (L10.16#52). Figure 10.27 shows the system of displays when
the user constructs a Point shape.

Lecture Inheritance Page 56 of 112


FIG. 10.27 Comment [p29]: Listing 10.16

User is given, through the display, all the correct properties of Point type object
constructed by them (Figure 10.27). Notice that even though point object created on
Line (L10.16#27) was represented by a Shape type reference (Gen_Shape), due to
the property of dynamic binding, Java correctly recognizes the object to be of Point
type and only calls the methods from Point class to build the property String
Output.

If edge value selected is not zero then user may wish to construct either a square or
a cube (both these shapes having an edge). In that case the else block in Listing
10.16 (L10.16#32-50) is executed. And if after entering the center coordinates of 10,

Lecture Inheritance Page 57 of 112


and 10, the user also entered an edge value of 10 for a cube object, the displays of
Figure 10.28 print the properties of Cube constructed by the user.

Lecture Inheritance Page 58 of 112


FIG. 10.28 Comment [p28]: Listing 10.15

Here also though reference of type Shape (Gen_Shape) holds the address of Cube
object created at line (L10.16#45), Java does the correct dynamic binding by calling
the appropriate methods for area and volume for the Shape object Cube. We shall
soon discuss advantages of extending other Java abstract classes called adapter
classes, which implement some methods for a Java interface but leave one of more
methods unimplemented. Adapter classes simplifies coding in creating some
graphical user interface programs.

Lecture Inheritance Page 59 of 112


Other Related Topics
Local Class Definitions:
Java allows classes to be defined locally inside the methods. The locally defined
classes are not allowed to have any access modifier attached to them, but they can be
declared final. They are visible only inside the method in which they are defined.
The locally defined classes cannot have static fields or methods and they themselves
cannot be static. Irrespective of access modifier used for the fields and methods of
local classes, their members are all public and visible in the method in which they
are defined. However, they can extend other classes and implement interfaces like
regular classes. Listing 10.17 shows a declaration of local class SomeClass and its
use. The results of running the program are shown in the Figure 10.29

Listing 10.17 Comment [p30]: Figure 10.28

Lecture Inheritance Page 60 of 112


FIG 10.29 Comment [p31]: Listing 10.17

Local classes like Listing 10.17 can be defined inside any method, constructor or
initialization block10. Local classes can access, with in scope, locally defined constant
reference types11 or class level static variables directly. The instance fields of locally
defined final class variables can also be accessed. The method in which local class is
declared can return their instance as a method return value or pass their instance as
a parameter to another method.

10
An initialization block is located at the class level as a stand-alone block (bounded with curly
braces). The initialization blocks may be marked as static or may be unmarked. Code in all static
blocks is executed “once” when program is run first time. Non-static or unmarked blocks are
executed each time a class constructor call is made.
11
Local constant reference types can be declared as follows:
final AnyClass Var1 = new AnyClass( );
Note that in this case the reference Var1 is constant, which means that Var1 cannot be used to point
to another object of type AnyClass later in the program sequence. This does not however make the
object to which Var1 is pointing to immutable (or unchangeable). The java objects are immutable
only if their class is defined as final and they have no methods available to change their state after
construction.

Lecture Inheritance Page 61 of 112


Asynchronous Programming
When we give a graphical component in a user interface the capability to respond to
user actions (like keystrokes or mouse actions), such programming is called
asynchronous programming. It is so because the user action will not be tied by the
sequential flow and execution that program source code has. The program may be
doing ten different things, but if user presses certain keys or clicks mouse then the
program has to respond to it. The whole process requires interaction of three
agents:
1. User
2. Operating System (assume Windows for discussion)
3. The program
When user takes an action, like pressing a key or clicking certain active area of the
program window, the operating system fires an object (called windows event) to
the program. This is the way of operating system informing the program that
certain event has taken place in the program. However, this communication from
the operating system to the program will go unheard unless the program has some
intelligence to “listen” to those messages from the operating system. Adding so-
called “listeners” to the graphical components, which user can activate in the
program (by clicking a mouse or using keyboard), provides this intelligence. These
listeners are ever present in the background to receive any messages that operating
system sends them. After receiving the message from the operating system, the
listener would execute one or more program methods to respond to the user action.
These methods are called event handlers.

The listeners are added to graphical or GUI components by invoking one of their
method which has a name similar to:
Object of a class that would have
event handling method is passed
as an argument.
addSomeListener ( ).

In addition, a method that adds a listener will take as its argument an object, which
can invoke an event handling method or event handler. The process of adding a
listener is called “registering” a GUI component with the event listener. The object
passed as an argument to addSomeListener method, is a java class that has the
event handling method in it.

First we show graphical programming in its “unintelligent” form to see as how we


can simply paint a GUI canvass using the passive Java components. A minimal
stand-alone graphical program is created using the class java.awt.Frame class from
java awt package. awt stands for Abstract windowing toolkit, that was a graphical
package introduced in Java 1.1. Since then Sun has introduced another “light
weight” graphical classes package called swing (javax.swing). Swing is lightweight
because it does not depend so much on the operating system on which graphics are

Lecture Inheritance Page 62 of 112


being displayed for its functionality. Therefore most swing GUI would look similar
on most platforms. There is one-to-one mapping between most awt and swing
classes. For example the class Frame in awt package has a counterpart in swing
called JFrame. Most advanced programming must be done using swing, however
for basic learning purposes, either package starts out well.

Listing 10.18 A &B show one of the technique to create a simple awt and swing
windows.
1. Create object of
import java.awt.*;
Frame class.
public class TryWindow1
{
static Frame aWindow = new Frame("My awt Window!! Do Not Touch.");

public static void main(String[] args)


{
//Showing a simple window. It has nothing and does not
//close easily 2. Set Frame
aWindow.setBounds (50,100,400,150); coordinates
(bounds).

3. Make the
Frame
aWindow.setVisible (true);
visible.
}
}//Listing 10.18A Comment [p32]: Figure 10.29

The program imports the java.awt package and creates a static data member of type
Frame called aWindow, which is initialized by calling the Frame class constructor
that takes a String as an argument. We shall see soon that the String in the Frame
class constructor argument shows up as the header of the Window Frame created.
The Frame class inherits the method setBounds called in the main from one of its
super class called Component. The Figure 10.30 shows the overall inheritance
hierarchy for the Frame class.

Lecture Inheritance Page 63 of 112


java.lang.Object
java.awt.Component
java.awt.Container
java.awt.Window
java.awt.Frame
FIG 10.30 Comment [p33]: Listing 10.18A

Frame class would inherit all public and protected methods from all of its four
super classes. The method setBounds (inherited from Component class) has the
following header and details (Figure 10.31).
public void setBounds(int x, int y, int width,
int height)
Moves and resizes this component. The new location of the top-
left corner is specified by x and y, and the new size is specified by
width and height.
Parameters:
x - the new x-coordinate of this component
y - the new y-coordinate of this component
width - the new width of this component
height - the new height of this component
FIG. 10.31 Comment [p34]: Listing 10,18A

In calling method setBounds the first two arguments provide the x, and y
coordinates of top left corner of the Frame, and other two, its width and height. The
method setVisible also inherited from Component class can make the Frame visible
or invisible (Figure 10.32).
public void setVisible(boolean b)
Shows or hides this component depending on the value of
parameter b.
Parameters:
b - if true, shows this component; otherwise, hides this
component
FIG. 10.32 Comment [p35]: Listing 10.18A

Since we wish the Frame aWindow to show up, we pass the argument true when
calling method setVisible. The execution of main in Listing 10.18A gives a GUI
shown in Figure 10.33.

Lecture Inheritance Page 64 of 112


Point 50, 100 in pixels from top
left corner of screen.

Height = 150

Width = 400

FIG. 10.33 Comment [p36]: Listing 10.18A

The Frame object having the title passed to it as a String in the constructor call
shows up with its top left corner placed at the location x = 50 pixels and y = 100
pixels, with 450 pixel width and 150 pixel height. It is important to understand at
this point that in Windows and other GUI programming the top left corner of the
display is considered as origin (0,0). The y-axis is positive downward on left edge of
the monitor and x axis is positive from left to right emanating from top left corner of
the monitor. Unfortunate thing with this Frame window is that it would not even
close by clicking on X on its top right corner and user would need to use Control +
Alt + Delete in order to shut it down.

The JFrame window from swing package is closeable by clicking on X on top right
corner and is better behaved. Listing 10.18B shows the code for creating a JFrame
window and Figure 10.34 shows its look and feel.
import javax.swing.*;

public class TryWindow1Swing


{
static JFrame aWindow = new JFrame("My Swing Window!! Do Not Touch.");

public static void main(String[] args)


{
//Showing a simple window. It has nothing but closes easily
aWindow.setBounds(50,100,400,150);
aWindow.setVisible(true);
}
}//Listing 10.18B Comment [p37]: Figure 10.33

Lecture Inheritance Page 65 of 112


FIG. 10.34 Comment [p38]: Listing 10.18B

It is should not be surprising to see that methods setBounds and setVisible apply to
JFrame equally well as JFrame actually derives from Frame class (Figure 10.35).
java.lang.Object
java.awt.Component
java.awt.Container
java.awt.Window
java.awt.Frame
javax.swing.JFrame
FIG. 10.35 Comment [p39]: Listing 10.18B

We mentioned that Window created by Frame class in Figure 10.33 is not closeable.
This has to do with the fact that Frame window has not been given “intelligence” to
close when user hits on X button on top right corner. How is this intelligence
imparted to a window? Few pages ago we mentioned that when user clicks mouse or
presses a key, the operating system fires an object called window event and send
that to the program. For program to do anything about it a listener must be present
to listen for messages from operating system. In Listing 10.18A, there is no such
listener present. Listeners are Java Interfaces, which contain some predefined
method headers. The interface that must be implemented for closing the window in
Listing 10.18A (thus close the window by clicking on x button) is called a
WindowListener in java.awt.event package. Table 10.1 gives the methods included
in the interface WindowListener. Any class implementing WindowListener

Lecture Inheritance Page 66 of 112


interface, in order to be instantiated, must override and implement the methods in
Table 10.1.
Summary of Methods for WindowListener Interface
void windowActivated(WindowEvent e)
Invoked when the Window is set to be the active Window.
void windowClosed(WindowEvent e)
Invoked when a window has been closed as the result of calling
dispose on the window.
void windowClosing(WindowEvent e)
Invoked when the user attempts to close the window from the
window's system menu.
void windowDeactivated(WindowEvent e)
Invoked when a Window is no longer the active Window.
void windowDeiconified(WindowEvent e)
Invoked when a window is changed from a minimized to a normal
state.
void windowIconified(WindowEvent e)
Invoked when a window is changed from a normal to a minimized
state.
void windowOpened(WindowEvent e)
Invoked the first time a window is made visible.
Table 10.1 Comment [p40]: Fig. 10.35, Listing 10.18B

All methods in Table 10.1 can also be called event handlers. For example when
user would click the top right X button to close window (when properly added), the
method windowClosing would be activated and code inside it would be executed
to close the window. So our task of writing a closeable awt window program breaks
down as follows:
1. Write a class that implements WindowListener Interface and in that provide
bodies for all seven methods inherited from the interface.
2. Register the Frame object, which created the Window with this class (or
listener).

Best way to perform task #1 is do declare an inner class which would implement a
WindowListener interface. There are ways around it, that can avoid using inner
classes, but such avoidance in the long run reduces one’s learning of GUI
programming, and is not worth even to begin with. Therefore we first digress and
discuss inner classes in Java.

Inner Classes:
Java allows one to define classes as members of classes. Some time such classes are
also called nested classes. However, the Java Specification document points out a
subtle difference between the inner classes and nested classes. First, let us discuss

Lecture Inheritance Page 67 of 112


few more definitions. A stand-alone class is not allowed to be declared static. For
example class shown in side bar below would cause compile error.

static class ExplicitStatic Compile time error. A


{ stand-alone class
cannot be declared
} static.

However, a nested class can be declared static. For example, the declaration like
below is OK.

public class Outer


{
This is
static class NetsedClass OK!!
{
Can declare static variables and constants.
}
}

public class Outer


{
class InnerClass This is
{ also
//Cannot declare static variables!! OK!!
//Can declare static constants!
}
}

public class Outer


{
class InnerClass extends SomeClass
{ This is
//Cannot declare static variables!! also OK!!
//Can declare static constants!
}
}
Lecture Inheritance Page 68 of 112
Now we can explain the subtle semantic difference between nested classes and inner
classes. The static inner classes are called nested classes, whereas their non-static
counterparts are called inner classes. The nested classes can declare static variables
and constants, but inner classes can only declare static constants. Of course both can
declare instance variables and constants. Nested & inner classes can also be
declared abstract or final if needed.

Instantiation of Inner Classes


A static inner class or a nested class can be instantiated all by itself, even if the class
it is enclosed in is not instantiated. Of course one gets access to a nested static class,
just like one gets access to a static member, by using the class name. Listing 10.19
shows the syntax needed to declare instances of static and non-static inner classes.
public class Outer
{
public static class NestedClass
{

}
Needed because NestedClass is
public class InnerClass enclosed and needs to be qualified by
{ its outer class. Since Nested class is
static, just the class name is enough
}
}
for qualification!

public class TestOuter


{
public static void main(String[] args)
Data type {
for both Outer.NestedClass Temp = new Outer.NestedClass();
also need
to be Outer Temp_Outer = new Outer();
qualified
Outer.InnerClass Inst_Inner = Temp_Outer.new InnerClass( );
}

} Qualified name of the constructor of InnerClass needs dot


operator with the instance of outer class to which the instance
Inst_Inner belongs.

Listing 10.19 Comment [p41]: Fig. 10.35, Table 10.1,

Lecture Inheritance Page 69 of 112


The data type for inner classes is defined by their qualified name. Inside class
Outer, we declared inner classes NestedClass and InnerClass as public. Therefore
their qualified names are: Outer.NestedClass and Outer.InnerClass.

In instantiating a static inner class, we use the following syntax:

DataType InstanceName = new QualifiedConstructorName;

The qualified constructor name is simply the outer class name dotted with the static
class name. One can see that a static inner class can be instantiated with out the
need to instantiate its outer class first! This is not true for instantiation of a non-
static inner class. The latter requires, that for its instantiation, an object of its outer
class be present first. Therefore in Listing 10.19, first we create an instance of Outer
class called Temp_Outer. The left hand side of expression for instantiating the non-
static InnerClass remains similar to the one for static NestedClass. However, its
constructor call must be associated and qualified with the object of Outer class as its
instance cannot exist independently. Therefore in Listing 10.19 we use the following
syntax to create an object of InnerClass (Figure 10.36):

Name of the Outer class object


associated with the instance Constructor for the
Inst_Inner InnerClass.

Outer.InnerClass Inst_Inner = Temp_Outer.new InnerClass( );

FIG. 10.36 Comment [p42]: Listing 10.19, Table 10.1

The dot operation between instance of Outer class Temp_Outer and new operator
may shock some of you. However one must understand that no property of
(including instantiation) an inner non-static class can be independent of an instance
of outer class as it is not different compared to an instance variable. Therefore you
may consider that an “unqualified” name for the constructor of non-static class
inner class, outside its enclosing class does not exist. In fact the object Temp_Outer,
after the line in Figure 10.36 is executed would schematically look like the one given
in Figure 10.37.
Comment [p43]: Listing 10.19, Table 10.1
Object Object
Temp_Outer Inst_Inner

FIG. 10.37

Lecture Inheritance Page 70 of 112


There is an alternate syntax for instantiating an inner class, by calling the outer
class constructor in the same line. For example statement below can also create the
object of Inst_Inner.

Outer.InnerClass Inst_Inner = new Outer ( ).new InnerClass( );

Imparting intelligence to Window of Listing 10.18A


As discussed before, in order to make the window in Listing 10.18A closeable, we
must create a listener, which implements WindowListener interface and then
register the Frame component aWindow with this listener. One way to create a
window listener is to create a static inner class inside the class TryWindow1 that
would implement the WindowListener interface. Schematically, the modified
TryWindow1 class would look Listing 10.20A.
import java.awt.*;
1. Needed because WindowListener interface is
import java.awt.event.*;
in java.awt.event package
public class TryWindow1
{
static Frame aWindow = new Frame("My awt Window!! Do Not Touch.");

2. Implements the bodies


of seven event handlers
static class CloseWindow implements WindowListener from WindowListener
{ interface.

//code for bodies of 7 event handler methods from WindowListener Interface


}
3. Registration of Window
component with the object
public static void main(String[] args) containing event handlers!
{

aWindow.addWindowListener (new CloseWindow( ) );

aWindow.setBounds (50,100,400,150);

aWindow.setVisible (true);
}
}//Listing 10.20A Comment [p44]: Figure 10.37, Table 10.1
Comment [p45]: Figure 10.37, Table 10.1
One lengthy process in Listing 10.20A is to implement the seven methods inherited
from WindowListener interface. The truth is that the only event handler needed to

Lecture Inheritance Page 71 of 112


make the window closeable from Table 10.1 is the method windowClosing. Java
helps us out of this tedium by availing us an abstract class
java.awt.event.WindowAdapter in which they have done all the work for us that is
to provide a blank implementation of all but one (windowClosing) method from
Table 10.1. Adapter classes are provided, so that they can be extended to provide a
simple functionality to a GUI component, such that in the adapter class, all the un-
needed methods are given a null implementation. Therefore in modifying the Listing
10.20A, we make the static class CloseWindow extend the class WindowAdapter,
and then inside it we provide the implementation of needed event handler method
called windowClosing (Listing 10.20B).
import java.awt.*;
import java.awt.event.*;
public class TryWindow2
{
static Frame aWindow = new Frame("My AWT Window!! It will close now.");
//Make window closeable
//Need an object that will listen to user actions

private static class CloseWindow extends WindowAdapter


{
public void windowClosing(WindowEvent event)
{
aWindow.dispose( );

System.exit(0);
}
}

public static void main(String[] args)


{
//Add the listening capability to Window aWindow
aWindow.addWindowListener(new CloseWindow( ));
aWindow.setBounds(50,100,400,150);
aWindow.setVisible(true);

}
}
//Listing 10.20B Comment [p46]: Figure 10.37, Table 10.1

The sidebar below describes the overall functioning of Listing 10.20B.

Lecture Inheritance Page 72 of 112


1.In
The Frame
Listing object
10.20 is registered
we accomplish with aof“listener”
the closing by calling
program window its inherited
as follows.
method addWindowLsitener. This method takes an argument of “type”
WindowListener. WindowAdapter happens to be a class of type
WindowListener, which has a method called “windowClosing”, which will be
executed if user acts to close the window.

2. To provide this “listener” object, we write a nested class in our program,


which extends the class WindowAdapter. (WindowAdapter is an abstract
class, so it needs to be extended).

3. Inside our nested class (CloseWindow) we write an event handling method


called windowClosing( ) and we put the code to close the window inside that
method.

The Window created by Listing 10.20B looks similar to the one created in Figure
10.33, except for the fact that now it is closeable. The method dispose that is called
inside the event handler windowClosing, is inherited by the Frame class, from its
super class java.awt.Window, which has the following description (Fig. 10.38).
public void dispose( )
Releases all of the native screen resources used by this Window, its subcomponents,
and all of its owned children. That is, the resources for these Components will be
destroyed, any memory they consume will be returned to the OS, and they will be
marked as undisplayable.

The Window and its subcomponents can be made displayable again by rebuilding
the native resources with a subsequent call to pack or show. The states of the
recreated Window and its subcomponents will be identical to the states of these
objects at the point where the Window was disposed (not accounting for additional
modifications between those actions).
FIG. 10.38 Comment [p47]: Listing 10.20B, Table 10.1

Following sequence of events takes place when the user clicks on X button on top
right corner of the window created by Listing 10.20B.

• Operating system fires, an object of type WindowEvent to


tell the program that user has pressed the mouse or
pressed keystrokes (Alt F4) to close the window.
• The listener which is an object of type WindowClosing
also of type WindowAdapter and WindowListener – due

Lecture Inheritance Page 73 of 112


to inheritance relationships), gets the message from
window event object and executes the code with in its
method windowClosing( ).
• The code with in the windowClosing( ) method executes
and closes the window.
For procedural programmers it is daunting to see that our program has no explicit
call to the method windowClosing in the main. But this is the key behind
asynchronous programming. Since program cannot anticipate as to when user
action will take place, it must be on the stand bye to execute in response to user
actions any time such actions are born. This is exactly what the event listeners and
their event handling methods accomplish. In this chapter we wished to show the
relationship between asynchronous programming and use of inner classes, and
event handlers. We shall expand on these concepts in the graphics-programming
chapter 14. In rest of this chapter we discuss remaining concepts for classes and
interfaces.

Anonymous Classes and alternate methods to add listeners


Anonymous or no name classes are declared on the fly, by using the operator new.
They behave just like locally defined classes, except they are for one time use only as
they have no name. For example related to class AnyClass of Listing 10.17, the
program statement below can create a no-name instance of class AnyClass:

new AnyClass( );

In a form such as shown by the above statement, they can only show an output from
the constructor being called (if any). Anonymous classes are more useful when they
are instantiated and used to return them as values from methods, or provide some
other “one time” functionality. The rules as to which local and class level
parameters anonymous classes can access are same as for the local classes discussed
earlier.

Although one of the better practices for adding listeners for Java graphical
components is shown in Listing 10.20B, where nested class is used, at times the use
of local class or an anonymous class can also achieve the same purpose. In Listings
10.21A the programs simply show up a Java graphical window with a label (an
instance of class java.awt.Label) in it, which can be closed by clicking on the close
icon on top right side and free the system resources.

Lecture Inheritance Page 74 of 112


1. Uses inheritance as
import java.awt.*; the class extends from
import java.awt.event.*; Frame class.

public class AwtWindowWithLabel extends Frame


{
2. Declares an instance
variable of type Label
private Label My_Label;
3. Calls the super
public AwtWindowWithLabel()
class (Frame class)
{
constructor.
super ("A Simple Window with a label in it!");

My_Label = new Label("Java Window Label"); 4. Calls the Label


class constructor to
create the object
My_Label.

add(My_Label); 5. Uses the add method inherited


from super class Container to add
the Label to the object of class
AwtWindowWithLabel.
setSize(400,120);
6. Uses the setSize method from
super class Container to set the
setVisible(true);
size of object of class
}
AwtWindowWithLabel.
public static void main(String[] args)
{
7. A variable final AwtWindowWithLabel Temp = new AwtWindowWithLabel();
to be used by
a local class class HelpCloseWindow extends WindowAdapter
must be 8. Local class
{
declared extends
public void windowClosing(WindowEvent Evt)
final! WindowAdapter
{
class and
Temp.dispose();
implements the
System.exit(0);
event handler
}
method!
}
Temp.addWindowListener (new HelpCloseWindow( ));
}
}//Listing 10.21A Comment [p48]: Listing 10.21A, Table 10.1,
Fig. 10.38

Lecture Inheritance Page 75 of 112


Figure 10.39 below shows the output of the Listing 10.21A.

FIG. 10.39 Comment [p49]: Listing 10.21A, Table 10.1,


Fig.10.39

Description of Listing 10.21A

Instance Variable and Constructor


In Listing 10.20A & B, we used a static class level Frame object to create a window.
Al alternate way to do that is to have a class extend the class java.awt.Frame
(bubble #1-L10.21A). Now one can add additional graphical components to the
Frame that would be an object of class AwtWindowWithLabel. We declare a Label
variable (bubble #2-L10.21A). Inside the constructor of class
AwtWindowWithLabel, we call its super class (Frame) constructor to pass the string
message that would be printed on the top of the window frame (bubble #3-L10.21A).
We then create the Label object to which the reference My_Label would point to by
calling the Label class constructor (bubble #4-L10.21A). The constructor takes the
string, which would be printed on the Label object as an argument. The add method
inherited from super class Container is used to paste the Label My_Label at the
default location on the Frame that would be an instance of class
AwtWindowWithLabel (bubble #5-L10.21A). setSize method inherited also from
super class Container is used to set the size of window to be displayed (bubble #6-
L10.21A).

main method and adding event handler


The call to constructor of class AwtWindowWithLabel would execute all the
constructor code, thus creating a Frame object with label on it. However the local
variable in main of type AwtWindowWithLabel needs to be declared final because
local and anonymous classes can only refer to final variables declared in their access
scope (bubble #7-L10.21A). We declare a local class HelpCloseWindow that extends
the abstract class WindowAdapter. Inside it we implement, the WindowAdapter
class abstract method windowClosing (event handler) with standard code to dispose
the Frame object (Temp in this case) (bubble #8-L10.21A). In last line of Listing
10.21A, the Frame object Temp is registered with the WindowListener object by
using the method addWindowListener and passing to it an instance of class
HelpCloseWindow. The execution of main method creates a window shown in
Figure 10.39, which shows the label created in constructor (bubble #4-L10.21A).
This window is closable by clicking on X on top right corner or by pressing on
alt+F4 keys.

Lecture Inheritance Page 76 of 112


At this point we shall contrast use of nested class to implement the event handler
(Listing 10.20B), vs. using the local class to achieve the same purpose (Listing
10.21A). The advantage of using nested class is that the Frame object can be created
in any method (not just main method) and closed there by passing the instance of
nested class implementing event hander. On the other hand the local class use is
limited only to the method in which it is declared.

Anonymous class
Though use of nested class is most versatile, however, if only one window is to be
created in the entire program, then we can use an anonymous class, which can
extend the Java class WindowAdapter (or any other adapter or listener class) for
one time use only. The Listing 10.21B shows the code for such anonymous class and
its use. The results of Listings 10.21A and 10.21B are identical.

Lecture Inheritance Page 77 of 112


import java.awt.*;
import java.awt.event.*;

public class WindowUsingAnonymous extends Frame


{
private Label My_Label;
public Window1()
{
super("A Simple Window with a label in it!");
My_Label = new Label("Hello From a java Window");
add(My_Label);
setSize(400,120);
setVisible(true);
}
public static void main(String [ ] args)
{
final WindowUsingAnonymous Temp = new WindowUsingAnonymous ( );

1. Notice that when we use the


anonymous class to be extended or
implemented, the use of keyword
extends or implements is omitted.

Temp.addWindowListener (
new WindowAdapter( )
2. Pair of braces
{
after the
public void windowClosing (WindowEvent Evt)
constructor call
{
defines the body
Temp.dispose ( );
of anonymous
System.exit(0); 3. The
class
} unimplemented
} and other methods
); are now coded
} inside the pair of
4. The right parenthesis for the braces { }, which
}
method addWindowListener define the
Listing 10.21B seems out of place and awkward anonymous class.
but is syntactically correct!

Lecture Inheritance Page 78 of 112


The anonymous class in Listing 10.21B, inside the parentheses for method
addWindowListener, is directly instantiated by calling the constructor for the class
WindowAdapter and implementing the method windowClosing all at once. While it
almost appears as if in Listing 10.21B we are calling a constructor of the abstract
class WindowAdapter (a forbidden practice), that is not the case. The constructor
call applies to entire anonymous class, and not to the WindowAdapter class, which
is being extended. Here the constructor call and extending the WindowAdapter class
are broken down into two sections. The portion,

new WindowAdapter( )

instantiates the anonymous class, while the portion,

{
public void windowClosing (WindowEvent Evt)
{
Temp.dispose ( );
System.exit (0);
}
}

extends the WindowAdapter class by implementing its abstract method


windowClosing( ). When the anonymous class and its implemented methods are not
written in the block format shown in Listing 10.21B, the confusion may take place
as the right closing parenthesis for method addWindowListener may appear out of
place. For example let us write the code to call method addWindowListener and
extending the WindowAdapter class in format below.

Temp.addWindowListener (
new WindowAdapter( )
{
public void windowClosing (WindowEvent Evt)
{
Temp.dispose ( );
System.exit (0);
}
});
Important thing to remember here is that the last right parenthesis, just before
semicolon is the right member of pair of parentheses for the argument list for the
method addWindowListener.

Lecture Inheritance Page 79 of 112


Nested Interfaces
Java allows local12 definitions of classes but not of interfaces. For example, a code of
types illustrated by Listing 10.22, where various forms of inner classes are decalared
is allowed.
public class LocalClasses
{
{ Class defined within a stand-alone
class Class1 non-static block.
{

}
}

static
{ Class defined within a stand-alone
class Class2 static block.
{

}
}

public LocalClasses( )
{
class Class3
{ Class defined within a constructor.

}
public static void main(String[ ] args)
{
class Class4 Class defined within a static method. Same
{ way the classes can be defined within non-
static methods as well.
}
}
} Listing 10.22

12
Local definition means defining with in a stand-alone block, constructor, or a method.

Lecture Inheritance Page 80 of 112


Comment [p50]: Table 10.1, Fig. 10.39, Listing
10.22
Java would not allow the interfaces to be defined locally, the way local classes have
been defined in the Listing 10.22 (inside stand alone block, static block, constructor
and static & non-static methods). Java does however allow one to define nested
interfaces. A nested interface means that an interface may be defined as a nested
member of a class or of another interface. For example, an interface definition like
the Listing 10.23 is allowed.
public class EncloseInterface
{
interface NestedInterface1
{

}
}

Listing 10.23
The nested interface (in this case NestedInterface1) may use the modifiers public,
protected, private and static as needed. Static and public nested interface acts like a
stand-alone interface, but the enclosing class defines its name and accessibility. A
class cannot implement the interface it encloses within itself. However, other classes
can implement an interface nested inside another class. For example, a code similar
to the Listing 10.24 is allowed.

public class EncloseInterface


{
interface NestedInterface1
{ Note that to access the
nested interface it must be
} qualified with the class,
} which encloses it.

class Class1 implements EncloseInterface.NestedInterface1


{
}

Listing 10.24
Also, note that the Class1 could implement the nested interface NestedInterface1
because it was not defined private. Privately defined nested interfaces can only be
implemented with in their member class. For example, a code similar to Listing
10.25 is allowed.

Lecture Inheritance Page 81 of 112


public class EncloseInterface
{
private interface NestedInterface1 Private nested interfaces are
{ only visible within their
member class.
}
{
class someclass implements NestedInterface1
{
}
}
}

Listing 10.25
Interfaces can nest other interfaces and classes as well. The members of nested
interfaces are also all public. A class that implements an enclosing (or outer
interface is only responsible for implementing the methods in the enclosing
interface. For example, in Listing 10.26, the class MyClass only needs to implement
method1. It is not responsible to implement method2 or method3. On the other hand
the class TheirClass, which extends the abstract class and implements both, the
nested and outer interface, must implement all method1, method2, and method3.

Lecture Inheritance Page 82 of 112


public interface InterfaceNesting
{
void method1( );

interface NestedInterface2
{
void method2( );

abstract class ClassInInterface


{
public abstract void method3 ( );
}
}

class MyClass implements InterfaceNesting


{ Only responsible to
public void method1( ){ } implement the method1.
}

class YourClass implements InterfaceNesting.NestedInterface2


{
public void method2( ){ } Only responsible to
} implement method2.

class TheirClass extends InterfaceNesting.ClassInInterface


implements InterfaceNesting.NestedInterface2,
InterfaceNesting
{
public void method1( ){ } Must implement all
public void method2( ){ } method1, method2 and
public void method3 ( ) { } method3.
}

Listing 10.26 Comment [p51]: Listing 10.26, Table 10.1,


Figure 10.39

Lecture Inheritance Page 83 of 112


Overriding super class methods
Sub classes are allowed to override the super class methods they inherit. The rules
for overriding are as follows:
1. One obvious rule is that an instantiable subclass must provide
implementation and in the process override all the abstract methods in its
super class. (Same rule applies for implemented interfaces).
2. The methods that are declared final in the super class cannot be overridden!
3. In process of overriding, a sub class is allowed to relax the accessibility to a
method, but it cannot make it more restrictive compared to the access level
defined by the super class.
We show examples of these rules. Listing 10.27 Shows two classes Parent, and Child,
where the Child extends the Parent.
public class Parent
{
protected void print1( )
{
System.out.println ("From protected method print1: Parent class");
}

public final void print2( )


{
System.out.println ("From super class: Parent class");
}

public void print3( )


{
System.out.println ("From public method print3: Parent class");
}

private void print4( )


{
System.out.println ("From private method print4: Parent class");
}
}
////////////////////////////////////////////////////
public class Child extends Parent
{
public void print1( )
{
System.out.println ("From public method print1: Child class");
}

Lecture Inheritance Page 84 of 112


/*public final void print2( )
{
System.out.println ("From sub class: Child class");
}
*/

/*protected void print3( )


{
System.out.println ("From protected method print3: Child class");
}*/

public void print4( )


{
System.out.println ("From public method print4: Child class");
}

public void print3( )


{
System.out.println ("From public method print3: Child class");
}
}//Listing 10.27 Comment [p52]: Listing 10.27, Table 10.1, Fig.
10.39
As given, both classes compile fine since the rules for overriding methods have been
obeyed by the Child class. However if we uncomment the code for method print2 in
Child class, the following compile error is issued (Figure 10.40A).
Child.java:8: print2( ) in Child cannot override print2( ) in Parent; overridden
method is final
/**/public final void print2( )
^
1 error
///////
FIG. 10.40A Comment [p53]: Fig. 10.40A, table 10.1,
Listing 10.27
Compiler message in this case is clear. Child class cannot override the final method
print2 in Parent class. Another compile error would be issued if the commented out
protected print3 method in Child class is uncommented, and the public print3 is
commented out (Figure 10.40B).

FIG. 10.40B Comment [p54]: Fig. 10.40B, Table 10.1,


Listing 10.27

Lecture Inheritance Page 85 of 112


The message in this case is that print3 that was public in Parent class cannot be
assigned a weaker access privilege which is protected.

We know that all Java classes implicitly extend the Java class on the top of
inheritance hierarchy java.lang.Object. The Object class has the following protected
and public methods that are automatically are inherited by all Java classes (Table
10.2).
Summary of Methods for Object class
protected clone()
Object Creates and returns a copy of this object.
boolean equals(Object obj)
Indicates whether some other object is "equal to"
this one.
protected finalize()
void Called by the garbage collector on an object when
garbage collection determines that there are no more
references to the object.
final Class getClass()
Returns the runtime class of an object.
int hashCode()
Returns a hash code value for the object.
final void notify()
Wakes up a single thread that is waiting on this object's
monitor.
final void notifyAll()
Wakes up all threads that are waiting on this object's monitor.
String toString()
Returns a string representation of the object.
final void wait()
Causes current thread to wait until another thread invokes the
notify() method or the notifyAll() method for this object.
final void wait(long timeout)
Causes current thread to wait until either another thread
invokes the notify() method or the notifyAll() method for this
object, or a specified amount of time has elapsed.

Lecture Inheritance Page 86 of 112


final void wait(long timeout, int nanos)
Causes current thread to wait until another thread invokes the
notify() method or the notifyAll() method for this object, or
some other thread interrupts the current thread, or a certain
amount of real time has elapsed.
Table 10.2 Methods declared final cannot be
overridden
The 11 methods listed in Table 10.2 are present in all Java classes! Out of them,
Java classes can override only five of the non-final methods. However, the default
implementation of some of them is rarely useful. Most Java classes would need to
override at least some of the non-final Object class inherited methods for better
functionality. This is because there are implicit contracts that Java expects one to
follow in overriding the Object class methods. Excellent book by Joshua Bloch titled
“Effective Java”, describes the techniques and contracts involved in overriding
Object methods nicely. We first discuss the method toString, which shall always be
overridden.

toString Method
When invoked, the default implementation of the object class method toString
would print out the class name and hexadecimal representation of the hash code of
the object invoking toString appended to a @ sign. For example for Listing 10.27, if
we write a main method in a test class and execute the code such as below:

Child My_Child = new Child ( );


System.out.println (My_Child); Default toString from Object class
is called. The default toString only
the output could be of type: prints class name and hash code in
hexadecimal.
Child@7ced01

Two things are clear from the above code snippet. One is that overloaded println
method would automatically invoke the toString method for an object passed to it as
argument! Since Child class in Listing 10.27 does not override the Object class
toString method, the above code snippet simply prints the class name followed by
the hash code for the Object My_Child as 7ced01. It is always desirable for
debugging as well as for some default output purposes that the toString method
provides some useful information about the class. For example in our Customer
class from Listing 4.7, which has a print method, we can also override the toString
method to provide alternate printing functionality for a Customer type object. We
basically add the following toString method to the Customer class in Listing 4.7
(Listing 10.28).

Lecture Inheritance Page 87 of 112


public String toString()
{
return "The customer name = "+ name+"\n"+
"The customer phone number is: "+ phone_num +"\n"+
"The customer credit rating is: "+ credit_rating+"\n"+
"The customer address is : "+ address+"\n"+
"The customer city is : "+ city+"\n"+
"The customer zip code is: "+ zip_code+"\n"+
"The Cutomer credit card number is: " + credit_card_num;
}//Listing 10.28 Comment [p55]: Listing 10.28, Table 10.2,
Figure 10.40B
With introduction of above method in Customer class when the code below is
executed in the main, the toString method is implicitly invoked, printing the String
returned by the toString method to the console (Figure 10.41).

Customer Cust1 = new Customer ("22334455","John Doe",


9142367789L, 'A',"1122 Pine Avenue", "Georgia", 90509);
System.out.println (Cust1);

FIG. 10.41 Comment [p56]: Listing 10.28, Figure 10.41,


Table 10.2
Generally toString method should always be overridden for classes that have some
values to print. For example all Java wrapper classes, String, StringBuffer have the
toString method overridden. It is also important that values and fields displayed in
the toString method have a direct getter available, so that the client of the class can
clearly see as to how the values or class data have been added to the String returned
by the toString method. A good description of what the toString method returns
must be provided in the documentation of the class, with advisement, whether
parsing the String returned by toString method for the values of object fields is
appropriate or not.

Overriding equals and hashCode methods


As per Java contract, the Object class methods equals and hashCode
are either overridden as a pair or not overridden at all. When an object is
added to a data structure called hash table, then a hash code is needed to specify its
location in the hash table. However general rule guiding whether to override

Lecture Inheritance Page 88 of 112


hashCode and equals depends upon the mutability/immutability of objects of a
class.

Hash tables could have two types of data members. If objects are immutable, then it
does not matter as to how many identical copies of an immutable object exist (in the
program memory) – only one of them must be added to the hash table. This is
because the object will never change; therefore its retrieval from hash table must
depend upon its state soon after its constructor constructs it. On the other hand if
object of a class is mutable then it must be added to hash table based only on its
memory address or a hash value related to its memory address. This is because the
mutable objects can change after adding to hash table, thus only sure way to
retrieve such an object from the hash table is to search it based on its memory
address.

Java Object class method equals only compares memory addresses and returns true
when two references being compared point to same memory location. For example
the boolean value of variable are_same in code snippet in the main below would be
true.

class MyClass
{
private int data;
public setData(int val)
{
data = val;
}
public int getData( )
{
return Data;
}
}
public class TestMyClass Since MyClass does not
override equals method,
{ the Object class Equals
public static void main(String [] args) method is called.
{
MyClass Temp1 = new MyClass ( );
MyClass Temp2 = Temp1;
boolean are_same = Temp1.equals (Temp2);
}
}

Lecture Inheritance Page 89 of 112


The reason are_same would be true is because Temp1 and Temp2 point to the same
object on heap. Moreover, since MyClass does not override the equals method
inherited from the Object class, in the statement:

boolean are_same = Temp1.equals (Temp2);

it invokes the Object class equals method, which simply compares the memory
addresses stored in the references Temp1, and Temp2, which in this case happen to
be the same value.

The class MyClass is not immutable, as it does not satisfy the following properties –
all of which are required of an immutable class:
1. The class must be declared final, so another class never extend it.
2. It shall have no methods that can alter the value of its data members after
the constructor has constructed its instance. In other words the immutable
class has no mutators.
3. If a member method returns an Object of the class, then it shall always
return a new Object, not the one that was passed to the member method,
modified by the member method and returned after modification.
Since class MyClass is mutable, there is no point to override the default hashCode
method for it as that returns the memory address where the object is located on the
heap. That hash code is good enough to use, in order to place the object in the hash
table. Therefore the general rule for deciding whether to override both equals and
hashCode methods is that if the class is immutable then they both must be
overridden, otherwise neither of them must be overridden. Java library follows this
rule rather well. For example String in Java is immutable, therefore String class
overrides both equals and hashCode methods. This ascertains that String objects
that evaluate equal in contents, their hashCode methods return the same value. On
the other hand StringBuffer is mutable, and even if contents of two StringBuffer
objects were same, they would still give different hash Code values (Listing 10.29).
00001 public class TestEquals
00002 {
00003 public static void main(String[] args)
00004 {
00005 String Str1 = new String("John");
00006 String Str2 = new String("John");
00007
00008 if(Str1 == Str2)
00009 System.out.println("String " + Str1 +" and String " +
00010 Str2+ " are located at the same memory location.");
00011 else
00012 System.out.println("String " + Str1 +" and String " +
00013 Str2+ " are located at different memory locations.");
00014
00015 if(Str1.equals(Str2))
00016 System.out.println("String " + Str1 +" and String " +

Lecture Inheritance Page 90 of 112


00017 Str2+ " are identical in contents.");
00018 else
00019 System.out.println("String " + Str1 +" and String " +
00020 Str2+ " are different in contents.");
00021
System.out.println("Hash code for " + Str1 + " = " + Str1.hashCode()+"\n"
00023 +"Hash code for " + Str2+ " = "+ Str2.hashCode());
00024
00025 StringBuffer SB1 = new StringBuffer("Mary");
00026 StringBuffer SB2 = new StringBuffer("Mary");
00027
00028 if(SB1 == SB2)
00029 System.out.println("String Buffer" + SB1 +" and String Buffer " +
00030 SB2+ " are located at the same memory location.");
00031 else
00032 System.out.println("String Buffer " + SB1 +" and String Buffer " +
00033 SB2+ " are located at different memory\n locations.");
00034
00035 if(SB1.equals(SB2))
00036 System.out.println("Tested with equals method: String Buffer" + SB1
00037 +" and String Buffer" + SB2+
00038 " are identical in contents.");
00039 else
00040 System.out.println("Tested with equals method: String Buffer "
00041 + SB1 +" and String Buffer " + SB2+ "\n"+
00042 " are different as equals method returns false.");
00043
00044 System.out.println("Hash code for " + SB1 + " = " + SB1.hashCode()+"\n"
00045 +"Hash code for " + SB2+ " = "+ SB2.hashCode());
00046
00047
00048 }
00049 }
//Listing 10.29 Comment [p57]: Listing 10.29, Figure 10.41,
Table 10.2
Figure 10.42 gives the output for the Listing 10.29. Two String objects Str1 and
Str2, both containing string “John” are declared using the String class constructor,
which uses operator new (L10.20#5-6)13.

13
Understand that if one assigned values to Str1 and Str2 as follows, then both Str1 and Str2 would
point to same memory location.
String Str1 = “John”;
String Str2 = “John”;
This is because compiler is allowed to place all literal strings at one memory location and make all
direct assigned String references with same content to point to same memory location. In this case
both == operator and equals method would yield the same result.

Lecture Inheritance Page 91 of 112


FIG. 10.42 Comment [p58]: Listing 10.29, Fig. 10.42,
Table 10.2
Since all constructor calls are made at run time, the Strings Str1 and Str2 are
created at different memory locations on heap. When one checks the Str1, and Str2
using the operator equal equal (==) (L10.20#8-14), then else block of if/else structure
is executed. The result printed by first line of Figure 10.42 (F10.42#1) indicates that
Str1 and Str2 are located at different memory locations.

Then Str1 and Str2 are compared using the equals method (which is overridden in
the String class) (L10.20#15-20). The equals method of String class is called, which
is coded to compare the contents of Str1 and Str2. The result is expected. The call
Str1.equals (Str2) returns true, and the output (F10.42#2) prints that Str1 and Str2
are identical in contents. Finally the hash codes printed for both Str1 and Str2 are
identical as well (F10.42#3-4).

Situation may turn out different for the StringBuffer objects whose class does not
override Object class equals and hashCode methods. We create two StringBuffer
objects SB1 and SB2, both containing string “Mary” (L10.20#25-26). Then we check
the addresses stored in SB1 and SB2 using the == operator (L10.20#28-33). This
result is identical to the one for Strings Str1 &Str2. Use of operator new always
creates the objects at new memory locations on heap. Thus output line (F10.42#5-6)
prints that SB1 and SB2, both containing StringBuffers “Mary” are located at
different memory addresses. The major difference compared to the String example
comes when we use the equals method to compare the objects SB1 and SB2
(L10.20#35-42). While using equals with Str1 and Str2 returned true, the expression
SB1.equals (SB2), evaluates to false, resulting in output (F10.42#7-8), which is same
as the result using == operator. Finally we see that the values returned by method
hashCode are different for SB1 and SB2 (F10.42#9-10), even though both have same
contents (“Mary”). This is because the StringBuffer class also does not override the
method hashCode, thus it calls the Object class hashCode, which only returns the
memory address of the object. Conclusions:
1. The equals method of Object class only compares memory addresses of
objects and not their contents.

Lecture Inheritance Page 92 of 112


2. The hashCode method of Object class returns the memory address of the
object.
3. String class overrides both equals and hashCode thus two identical string
objects yield the same hashCode, irrespective of their location in the
memory.
The above example clarifies the criteria that must be followed in overriding equals
and hashCode methods. Override then as a pair for classes that are immutable,
otherwise leave them alone.

It is required that properly overridden equals method has the following five
properties:
1. It is reflexive – meaning that for a reference x, x.equals (x) must
return true.
2. It is symmetric – meaning that for any reference values x and y,
y.equals (x) must return true only if x.equals (y) also returns true.
3. It is transitive – meaning that for reference values x, y, and z; if
x.equals(y) returns true and y.equals(z) returns true,
then x.equals (z) must return true.
4. It is consistent – meaning that for any values of x and y multiple
invocations of x.equals (y) must return true or false, provided that
objects x and y are not modified between the calls to the method
equals.
5. For a null reference value, the x.equals (null) must return false.

We shall develop an example of proper overriding of equals method, after we have


developed the requirements for overriding hashCode method as well. They are
followings.

Overriding method hashCode


A hash-based collection may become corrupt if one only overrides the equals
method and not the hashCode method as well. The reason is that in the absence of
overridden hashCode method, the Object class hashCode method is called, which
only returns the memory address of an object. In that case, two Objects, which are
identical will map to two different locations in the hash table. When retrieving a
value object attached with a certain key, Java depends upon the value of the hash
code for the same key being the same every time. However, if the value of the hash
code were merely the memory address of the object, one may not be able to locate it
in the hash table, as this address could be different each time. One thus need to
override the hashCode method. However, a good hashCode method must:
• Provide the same hash code for the two objects that are equal. For example
if: x.equals (y) is true, the also it must be that
x.hashCode ( ) = y.hashCode ( ). This does not necessitate that two different
objects cannot have same hashCode. This provision only necessitates that
identical objects have the same hash code. We saw this being followed in our

Lecture Inheritance Page 93 of 112


Listing10.29, where when Str1.equals(Str2) evaluated to true, then the hash
code returned by Str1.hashCode ( ) and Str2.hashCode ( ) were identical!
• Provide an even distribution of the hash code values in the range zero to the
Integer.MAX_VALUE, the latter being a constant in the java.lang.Integer
class.
• Returns the hash value fast since the method is called each time a key value
pair is placed in the hash table and also when the objects are searched with
their keys.
• Have a simple code.
Obviously some of these requirements conflict with each other and one need to come
up with a good compromise. Table 10.3 provides a strategy for the reasonable
compromise for writing a good hashCode method.
Data Type as Instance Hash code Multiply
class member Name with a
prime
number14
PrimitiveData15 variable new X
PrimitiveData(variable).hashCode( )
String Str Str.hashCode ( ) Y
A Class Type CLS CLS.hashCode ( ) Z
Final hash code value = Σ X * (new Data (variable).hashCode ( ) +
Y*Str.hashCode( ) + Z*CLS.hashCode ( );
Table 10.3 Comment [p59]: Listing 10.29, Fig. 10.42,
Table 10.3
Basically the immutable class data members are used to provide final hash code for
one of its object. If the data member is a primitive then its wrapper object is created
and its hashCode method is called to get a number. This number multiplied by a
prime number becomes one component of final hash code. The process is repeated
for all String and other Object data members – each one calling its own hashCode
method and the returned value multiplied by a prime number. All such components,
when added would provide a good hashCode for the object overriding the hashCode
method.

Now we show an example of Fraction class (Listing 10.30) that is immutable and has
two data members (both long data types) representing numerator and denominator
of a fraction. We also show codes to override both equals and hashCode methods for
class Fraction.

14
A prime number is the one, which is not factorable into other numbers. First few prime numbers
are 2, 3, 7, 11, 13, 17, 19 etc.
15
PrimitiveData could be int, float, short, char or any other Java primitive type.

Lecture Inheritance Page 94 of 112


00002
00007 public final class Fraction
00008 {
00012 private final static int P1 = 263 ;
00016 private final static int P2 = 149;
00020 private int numerator;
00024 private int denominator = 1;
00027 public Fraction ( )
00028 {
00029 numerator = 0;
00030 denominator = 1;
00031 }
00035 public Fraction (int n)
00036 {
00037 this (n, 1);
00038 }
00043 public Fraction (int n, int d)
00044 {
00045 if(Math.abs(d) == 0)
00046 {
00047 System.out.println("Denominator value zero is not allowed."+
00048 " Denominator is being set to one.");
00049 numerator = n;
00050 denominator = 1;
00051 this.cleanup();
00052 }
00053 else
00054 {
00055 int thisGcd = gcd (Math.abs(n), Math.abs(d));
00056 numerator = n/thisGcd;
00057 denominator = d/thisGcd;
00058 this.cleanup();
00059 }
00060 }
00061
00066 public String toString ( )
00067 {
00068 return (numerator+ "/" + denominator);
00069 }
00070
00074 public double toDouble ( )
00075 {
00076 double n = numerator; // convert to double
00077 double d = denominator;
00078 return (n / d);
00079 }

Lecture Inheritance Page 95 of 112


00080
00085 public Fraction add (Fraction f2)
00086 {
00087 int val1 = (numerator * f2.denominator) +(f2.numerator * denominator);
00088 int val2 = (denominator * f2.denominator);
00089 return new Fraction(val1,val2);
00090 }
00095 public Fraction multiply(Fraction other)
00096 {
00097 // A/B * C/D = (A*C)/(B*D)
00098 return new Fraction(this.numerator*other.numerator,
00099 this.denominator*other.denominator);
00100 }
00105 public Fraction divide(Fraction other) {
00106 // A/B / C/D = A/B * 1/(C/D) = A/B * D/C = (AD)/(BC)
00107 return new Fraction(this.numerator*other.denominator,
00108 this.denominator*other.numerator);
00109 }
00113 public Fraction negate()
00114 {
00115 // -(A/B) = (-A)/B
00116 return new Fraction(-this.numerator, this.denominator);
00117 }
00118
00123 public Fraction subtract(Fraction other)
00124 {
00125 return add(other.negate());
00126 }
00127
00133 public static int gcd (int x, int y)
00134 {
00135 if(y==0)
00136 {
00137 return x;
00138 }
00139 else
00140 {
00141 return gcd(y,x%y);
00142 }
00143 }
00147 public int getNumerator()
00148 {
00149 return this.numerator;
00150 }

Lecture Inheritance Page 96 of 112


00154 public int getDenominator()
00155 {
00156 return this.denominator;
00157 }
00161 public boolean equals(Object Obj)
00162 {
00163 boolean result = false;
00164
00165 if(Obj instanceof Fraction)
00166 {
00167 if(Obj == this)
00168 result = true;
00169 else
00170 {
00171 Fraction Temp = (Fraction)Obj;
00172 result =
00173 numerator*Temp.denominator == denominator*Temp.numerator;
00174 }
00175 }
00176 else
00177 result = false;
00178
00179 return result;
00180 }
00184 public int hashCode()
00185 {
00186 return (new Integer(this.numerator).toString().hashCode())*P1 +
00187 (new Integer(this.denominator).toString().hashCode())*P2;
00188 }
00193 protected void cleanup()
00194 {
00195 // If the denominator is negative, multiply both parts
00196 // by -1 to make it positive without changing the value
00197 // of the fraction.
00198 if (this.denominator < 0)
00199 {
00200 this.denominator = -this.denominator;
00201 this.numerator = -this.numerator;
00202 }
00203 }
00204
00205 }
//Listing 10.30 Comment [p60]: Listing 10.30, Fig. 10.42,
Table 10.3

In Listing 10.30, we override the method equals (L10.30#161-179). Method tests


whether the Object Obj passed to it is an instance of Fraction or not (L10.30#165).

Lecture Inheritance Page 97 of 112


If this run time test evaluates to false then return value result is set to false
(L10.30#177). If Obj is indeed an instance of Fraction, then we test whether Obj is a
reference to itself or not, if yes then result is set to true. Otherwise the result is set to
the boolean value
numerator*Temp.denominator == denominator*Temp.numerator.
The above expression would only return true, when two fractions are indeed
identical in content.

In overriding hashCode method, first we wrap two int data members in Integer
Objects and then get their String representation, which in turn gets their own hash
codes by calling String class hashCode method. Each component is multiplied by a
different prime number (P1, and P2). The numbers thus obtained are summed and
the sum returned as a hash code. Figure 10.43 gives the results of only testing equals
and hashCode methods as per the driver program in Listing 10.31.
00001 public class DriverFraction
00002 {
00006 public static void main(String[] argv)
00007 {
00008 //main2()
00009 testEqualsAndHashCode();
00010
00011 }
00012 public static void testEqualsAndHashCode()
00013 {
00014 final Fraction F1 = new Fraction(-1,2);
00015 //Test for reflexivity
00016 System.out.println("Testing for reflexivity.");
00017 System.out.println("Fraction F1 = " + F1);
00018 System.out.println("F1.equals(F1) evaluates to " + F1.equals(F1));
00019 //Test for symmetry
00020 System.out.println("Testing for symmetry.");
00021 final Fraction F2 = new Fraction(200, -400);
00022 System.out.println("Fraction F2 = " + F2);
00023 System.out.println("F1.equals(F2) evaluates to " + F1.equals(F2));
00024 System.out.println("F2.equals(F1) evaluates to " + F2.equals(F1));
00025 //Test for transitivity
00026 System.out.println("Testing for transitivity.");
00027 final Fraction F3 = new Fraction(-800, 1600);
00028 System.out.println("Fraction F3 = " + F3);
00029 System.out.println("F1.equals(F2) evaluates to " + F1.equals(F2));
00030 System.out.println("F2.equals(F3) evaluates to " + F2.equals(F3));
00031 System.out.println("F1.equals(F3) evaluates to " + F1.equals(F3));
00032 System.out.println("Hash code for F1 = " + F1.hashCode());
00033 System.out.println("Hash code for F2 = " + F2.hashCode());
00034 System.out.println("Hash code for F3 = " + F3.hashCode());
00035 final Fraction F4 = new Fraction(-800, 1559);

Lecture Inheritance Page 98 of 112


00036 System.out.println("Fraction F4 = " + F4);
00037 System.out.println("Hash code for F4 = " + F4.hashCode());
00038 System.out.println("F4.equals(F3) evaluates to " + F4.equals(F3));
00039 System.out.println("Testing for null object.");
00040 System.out.println("F4.equals(null) evaluates to " + F4.equals(null));
00041 }
00042
00043 public static void main2()
00044 {
00045 System.out.println("Test 1 ");
00046 Fraction f1 = new Fraction(2,3);
00047 System.out.println("Fraction(2,3) produces "+f1);
00048 Fraction f2 = new Fraction(6,8);
00049 System.out.println("Fraction(6,8) produces "+f2);
00050 System.out.println("Sum = "+f1.add(f2));
00051
00052 System.out.println("Test 2 ");
00053 f1 = new Fraction(-2,3);
00054 System.out.println("Fraction(-2,3) produces "+f1);
00055 f2 = new Fraction(6,-8);
00056 System.out.println("Fraction(6,-8) produces "+f2);
00057 System.out.println("Sum = "+f1.add(f2));
00058
00059 System.out.println("Test 4 ");
00060 f1 = new Fraction(1,0);
00061 System.out.println("Fraction(1,0) produces "+f1);
00062 f2 = new Fraction(2);
00063 System.out.println("Fraction(2) produces "+f2);
00064 System.out.println("Sum = "+f1.add(f2));
00065
00066 System.out.println("Test 5 ");
00067 f1 = new Fraction();
00068 System.out.println("Fraction() produces "+f1);
00069 f2 = new Fraction(210,-12);
00070 System.out.println("Fraction(210,-12) produces "+f2);
00071 System.out.println("Sum = "+f1.add(f2));
00072
00073 System.out.println("Test 6 ");
00074 f1 = new Fraction(11,15);
00075 System.out.println("Fraction(11,15) produces "+f1);
00076 Fraction f3 = new Fraction(f1.getNumerator(),f1.getDenominator());
00077 System.out.println("Fraction(3) produces "+f3);
00078 System.out.println("Sum = "+f1.add(f3));
00079 System.out.println("Sum as double = "+f1.add(f3).toDouble());
00080
00081

Lecture Inheritance Page 99 of 112


00082
00083
00084 }
00085 public static void main1()
00086 {
00087 /* Test all four contructors and toString. */
00088 Fraction f0 = new Fraction();
00089 Fraction f1 = new Fraction(3);
00090 Fraction f2 = new Fraction(12, 20);
00091 System.out.println("\nTesting constructors and toString():");
00092 System.out.println("The fraction f0 is " + f0.toString());
00093 System.out.println("The fraction f1 is " + f1); // toString is implicit.
00094 System.out.println("The fraction f2 is " + f2);
00095 /* Test Fraction.gcd function (static method). */
00096 System.out.println("\nTesting Fraction.gcd:");
00097 System.out.println("The Fraction.gcd of 2 and 10 is: " + Fraction.gcd(2,
10));
00098 System.out.println("The Fraction.gcd of 15 and 5 is: " + Fraction.gcd(15,
5));
00099 System.out.println("The Fraction.gcd of 24 and 18 is: " + Fraction.gcd(24,
18));
00100 System.out.println("The Fraction.gcd of 10 and 10 is: " + Fraction.gcd(10,
10));
00101 System.out.println("The Fraction.gcd of 21 and 400 is: " + Fraction.gcd(21,
400));
00102 }
00103 }
//Listing 10.31
The results of Figure 10.43 show that equals method passes the tests of reflexivity,
symmetry, transitivity, and non-nullity. Also the Fractions with identical contents
(F1, F2, F3) give the same hash code.

Lecture Inheritance Page 100 of 112


FIG. 10.43

Overriding the clone method


We shall discuss overriding clone method from Object class after we have discussed
exception handling, as it requires that as a background.

Method finalize
Although Java permits Object class method finalize to be overridden, it should
almost never be overridden.

Questions
1. What would be printed by the following code? Explain your answer.
class A
{
int i = 1;

Lecture Inheritance Page 101 of 112


int f( ) { return i; }
}
class B extends A {
int i = 2;
int f ( ) { return -i; }
}
public class override_test
{
public static void main(String args[]) {
B b = new B ();
System.out.println(b.i);
System.out.println(b.f( ));
A a = (A) b;
System.out.println(a.i);
System.out.println(a.f( ));
}
}
2. What is true about overriding super class methods (Mark all correct
answers).
A] A method declared final in super class could be overridden.
B] It is not necessary to override abstract method in the super class in order to
instantiate the sub class using operator new in the client code.
C] static methods in the super class can be overridden, just the way non-static
methods can be overridden.
D] Keyword super is used to call the method from super class inside a sub class
method.
E] Answers A, B, and C are false, whereas answer D is correct.

3. A class cannot be instantiated in the client code:


A] If it is an abstract class.
B] If all of its constructors are private and no methods are available to return an
instance of the class (no “factory” method available).
C] If its an inner class and is declared private.
D] If the class is declared final.
E] Answers A, B, and C are true, whereas answer D is false.

For True False questions decide whether they are true or false, and also explain
the reason for your answers.
4. (T/F) A class can be declared abstract and final at the same time.
5. (T/F) A method cannot be declared abstract and final at the same time.
6. (T/F) A method cannot be declared abstract and static at the same time.
7. (T/F) Outer class can be declared static.
8. (T/F) An outer class and a stand-alone interface can be declared private.
9. (T/F) An outer class and stand-alone interface cannot be declared protected.
10. (T/F) A method can be declared private and abstract at the same time.
11. (T/F) A method cannot be declared protected and abstract at the same time.

Lecture Inheritance Page 102 of 112


12. (T/F) An inner class can be declared private and abstract.
13. (T/F) An inner class cannot be declared private, abstract and static at the
same time.
14. (T/F) An interface enclosed in a class can be declared private or protected.
15. (T/F) Classes can be declared inside any if the followings: static initialization
blocks, stand-alone initialization blocks, static methods, non-static methods,
constructors, interfaces, and inside classes.
16. (T/F) Interfaces can be declared inside: other interfaces, inside classes only.
17. (T/F) Interfaces can be declared inside any if the followings: static
initialization blocks, stand-alone initialization blocks, static methods, non-
static methods, constructors, interfaces, and inside classes.
18. (T/F) The keyword abstract can be used in declaring an interface, though it is
not necessary to do so.
19. (T/F) The keyword abstract must be used in declaring method names inside
an interface.
20. (T/F) Interface methods can be declared protected.
21. (T/F) Interface methods can be declared private.
22. (T/F) Interface can declare private and protected variables.
23. (T/F) Even if a variable declared inside an interface were not explicitly
declared final, it would be considered final.
24. (T/F) Even if a method declared inside an interface were not explicitly
declared final, it would be considered final.
25. (T/F) Even if a variable declared inside an interface were not explicitly
declared static, it would be considered static.
26. (T/F) Even if a method declared inside an interface were not explicitly
declared static, it would be considered static.
27. (T/F) In Java, words abstract and final can never appear together as
modifiers for class, and methods.
28. (T/F) A class with no access modifier (means no word public in class
declaration) is only visible in its package (called package-private).
29. (T/F) The sub class inherits a private variable declared in the super class.
However sub class has direct access to it.
30. (T/F) The sub class inherits a private method declared in the super class,
however it is not usable in the sub class.
31. (T/F) The sub class can override a method declared private in the super class
but in process of doing so it cannot make it protected or public.
32. The following Java keyword is used in invoking the super class constructor:
[A] this [B] super [C] instanceof [D] super.className
[E] None of above.
33. A programmer makes the following call inside the constructor of class
ConfusedProgrammer. Why would the call inside the constructor give
compile error? How would you explain to programmer that this call is
illegal?

Lecture Inheritance Page 103 of 112


public class ConfusedProgrammer
{
public ConfusedProgrammer ( )
{
this = method1 ( );
}

public static ConfusedProgrammer method1( )


{
ConfusedProgrammer Temp = new ConfusedProgrammer ( );
return Temp;
}
}

34. The confused programmer says that since he/she can make the following
constructor call:

ConfusedProgrammer Temp1 = (ConfusedProgrammer) new Object( );

then the following call is also legal.

ConfusedProgrammer Temp2 = (ConfusedProgrammer) super ( );

In your own words explain to the confused programmer that why the above call
is illegal.

35. A class declared with no modifier (for example with no keyword public in
front of class declaration) can:
[A] Be extended in its own package.
[B] Can be extended from inside any other package as long as it is imported
properly.
[C] All of above.
[D] None of above.

36. A field declared protected inside a stand-alone class MyClass (declared


public) is accessible by using dot operator:
[A] Inside the client classes that lie in the same package in which the class
MyClass lies.
[B] Inside the classes that extend MyClass, irrespective of location and package
of extending classes.
[C] All of above.
[D] None of above.

Lecture Inheritance Page 104 of 112


Appendix A10.1: Alternate implementations of inner classes
Important question however, is that what would happen if the inner class
WindowClosing is made a non-static class. In Listing 10.17, a whole bunch of extra
code will be needed to achieve the same results if the nested class WindowClosing is
made non-static. This code is shown for the class ColseableWindow2 in Listing
10.18.

Instance of class
CloseableWindow2 is
now needed because
with out it the inner
class WindowClsoing
cannot be
instantiated.

Instance.new
is required to
call the
constructor for
inner class

Listing 10.17

Note that when an inner class is non-static then an instance of outer class will be
needed, before an instance of inner class can be created. Also, note the syntax of the
constructor call for the inner class:

Lecture Inheritance Page 105 of 112


CloseableWindow2.WindowClosing Object_WindowClosing
= Instance.new WindowClosing( );
The operator new cannot be called directly. Rather it has to be dotted
with the instance of outer class to signify as to which object is it for
which the inner class instance is being created. The reference
specification also requires that we show data-type as
CloseableWindow2.WindowClosing, to provide the exact identification
of the outer and inner class pairing.

Even more code would be needed if the Frame type class variable My_Window is
made non-static in the Listing 10.17. Affect of this are shown in the Listing 10.18
below.
import java.awt.*;
import java.awt.event.*;
public class CloseableWindow3
{
private Frame My_Window ; A constructor to instantiate the object
Frame is now needed. Otherwise the inner
public CloseableWindow3( ) class WindowClosing will not know as to
{ which My_Window to dispose.
this.My_Window = new Frame();
}

private class WindowClosing extends WindowAdapter


{
public void windowClosing(WindowEvent event)
{
CloseableWindow3 Temp = new CloseableWindow3();
Temp.My_Window.dispose( );
System.exit(0); Before the dispose can be called
} on My_Window, we need an
} object of type CloseableWindow3
to establish a binding between the
public static void main(String [] args) outer class and inner class objects.
{
CloseableWindow3 Instance = new CloseableWindow3( );
Creation of My_Window
also needs an object of
Instance.My_Window.setBounds(10,10,600,600);
type ClosingWindow3.
Instance.My_Window.setBackground(Color.blue);
Instance.My_Window.setVisible(true);

CloseableWindow3.WindowClosing Object_WindowClosing =
Instance.new WindowClosing();

Instance.My_Window.addWindowListener(Object_WindowClosing);

Lecture Inheritance Page 106 of 112


}
} Listing 10.18

It is important to note that Listings 10.16, 10.17and 10.18 all accomplish almost
the same results. What is then the advantage of the Listing 10.18, where neither the
object Frame (My_Window), nor the inner class (WindowClosing) is static? Well
now, we can have more than one window in our program if we wanted to. This is
shown in Listing 10.19 for WindowClsoing4, where we create two windows one
with background blue and other with yellow background.
import java.awt.*;
import java.awt.event.*;
public class CloseableWindow4
{
private Frame My_Window ;
public CloseableWindow4()
{
this.My_Window = new Frame();
}
private class WindowClosing extends WindowAdapter
public void windowClosing(WindowEvent event)
{
CloseableWindow4 Temp = new CloseableWindow4();
Temp.My_Window.dispose();
System.exit(0);
}
}
public static void main(String [] args)
{
CloseableWindow4 Instance = new CloseableWindow4();
Instance.My_Window.setBounds(10,10,600,600);
Instance.My_Window.setBackground(Color.blue);
Instance.My_Window.setVisible(true);
CloseableWindow4.WindowClosing Object_WindowClosing =
Instance.new WindowClosing();
Instance.My_Window.addWindowListener(Object_WindowClosing);
display1();
} Method display has the
same code as the main
public static void display1( ) method, except the
{ window is smaller and
CloseableWindow4 Instance = new CloseableWindow4(); yellow in color and its
Instance.My_Window.setBounds(100,100,100,100); origin is located
Instance.My_Window.setBackground(Color.yellow); differently.
Instance.My_Window.setVisible(true);
CloseableWindow4.WindowClosing Object_WindowClosing =
Instance.new WindowClosing(); Listing 10.19

Lecture Inheritance Page 107 of 112


Instance.My_Window.addWindowListener(Object_WindowClosing);
}
}
One thing one would notice is that when in executing the program in Listing 10.19
one tries to close any of the window, both Windows are closed at the same time.
That is because when we click on Window closing (x) icon, though the method
WindowClosing is called only for one object, the method System.exit (0) is executed
anyhow, which results in program termination as a whole.

Lecture Inheritance Page 108 of 112


Lecture Inheritance Page 109 of 112
Lecture Inheritance Page 110 of 112
Lecture Inheritance Page 111 of 112
Lecture Inheritance Page 112 of 112
Chapter 11 Multidimensional Arrays And Searching And Sorting

Chapter to be written ☺
CS 3: Java
Chapter 12: Exception Handling in Java
Author: Satish Singhal Ph. D.
Version 1.02

Mathematics defines two types of functions, total functions and partial functions. In
total functions the value of the function is defined for all values of the variables or
arguments provided to the function. In case of partial functions, there are domains
of variable values, where the function behavior becomes indeterminate.

Similar to mathematical concept of total and partial functions, Java has methods,
which can be categorized as total methods and partial methods. The total methods
are such that there is no restriction on the variables passed to the method at run
time, as method would handle all errors related to the data passed to it. This is akin
to a total mathematical function being defined for all values of the variables. A
partial Java method on the other hand “requires” user to refrain from passing
certain variable values as arguments, as the method is not designed to handle such
values. If a forbidden value were passed to a partial Java method then error
condition would result. A simple example of a partial method is a method called
divide (Listing 12.1), which takes two integers num and den as arguments and
returns the result num/den. The pre-condition to be followed in using this method is
that user never passes a zero value for den to the method1.
public class DivideProblem1
{
/*
• pre-condition: The value of den passed to the method shall never be zero.
• Returns the integer result after dividing argument num by argument den.
*/
public static int divide (int num, int den)
{
return num/den;
}
}//Listing 12.1
The method divide in Listing 12.1 has undefined result for den equal to zero and
would require error handling when user violates the pre-condition. Traditional
language like C could pass an extra argument, a pointer to a partial method like
divide to carry the results of the division of num and den. The method could return
a zero if pre-condition is violated. In that case the method would not alter the value
of the pointee of the pointer passed to it. If denominator is non-zero then the method

1
It just so happens that Java would crash the program if a zero value for den were passed.

Java Exception Handling Page 1 of 49


could return a value of one and store the result of division in the pointee of the
pointer passed to it. Listing 12.2 shows the details.
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
/////////////////////////////////////////////////////////////////
int divide(int num, int den, int * result)
{ Pointee of pointer result is
if(den == 0) unaltered for zero value
return 0;
of denominator.
else
{
*result = (num/den);
return 1;
}
}
//////////////////////////////////////
void main( )
{ Caller method first checks
int * result = (int*) malloc(sizeof(int)); the return value from the
int num = 5; divide method, and then
int den = 0; prints appropriate message.

if(!divide(num ,den , result))


printf ("The illegal denominator of value = %d has been passed to the method divide",den);
else
printf("\nThe division %d//%d = %d\n",num,den,*result);

num = 25;
den = 5;

if(!divide(num,den,result))
printf("The illegal denominator of value = %d has been passed to the method divide",den);
else
printf("\nThe division %d//%d = %d\n",num,den,*result);
}//Listing 12.2
Figure 12.1 shows the results of Listing 12.2.

FIG. 12.1

Java Exception Handling Page 2 of 49


In Listing 12.2, the method divide tests if the denominator is zero, in which case the
method returns a zero, and the pointee of int pointer result is left unaltered.
However, if denominator is non-zero, then the pointee of pointer result is set equal
to the result of division, and it is printed in the caller method.

Due to security considerations, Java does not allow pointers to primitives, and for
the same reason all wrappers to primitives are also immutable. Therefore technique
used in C programming for error handling (where an error code is returned) cannot
be used in Java without elaborate measure, such as designing a method header as
given below.

boolean divide (int num, int den, StringBuffer result)

In a divide method like above, if den is not zero, then method would return a true,
and the value num/den would be appended to (an initially empty) StringBuffer
object result. Using the algorithm similar to the one shown in main method in
Listing 12.2, the caller method can correctly parse the result of the division.

The use of C like technology for error handling is tedious, as it requires the client to
write extra code for error checking. Therefore inventor of Java and other Object
Oriented Languages designed a technology, which allows the methods to return an
error condition to the caller method without using the traditional error code return
mechanism. This technology is called exception handling/error handling. Side bar
12.1 provides few examples of error or exception conditions.

Sidebar 12.1
• In an integer arithmetical division, user provides a zero value
for the denominator.
• In a file input, the wrong file name or non-existent disk drive is
provided.
• When program expects input of a numeric, a string composed
entirely of alphabets is entered.
• When entering a person’s name in the customer database, only
digits are entered.
• Disk drive has a physical crash during the data read/write
process.
• Programmer makes a method call using an object reference,
which is a null pointer.
• The program tries to access an out of bounds array index.

Java Exception Handling Page 3 of 49


So far we have been using words error and exception as if they are same thing. Java,
however, makes a subtle difference between them and designs group of classes
accordingly.

Error is a program condition, which when manifested, is generally not correctable


by adding a piece of code in a class or in the client code. For example if during
execution of a Java program, the JVM breaks down, then user code cannot handle
such error, and JVM would shut down the program after informing user of the
error.

On the other hand exceptions are conditions that are to some degree controllable,
and in some cases correctable by adding an exception handling code in the classes
and/or in the client program. In this chapter we elucidate exception handling by
examples and discuss error handling. Diagram in Figure 12.2 shows Java’s top-level
design of classes for error/exception handling.

FIG. 12.2
At the top of hierarchy (derived from class java.lang.Object) is the class Throwable,
which also implements the interface serializable. Figure 12.2 shows all the
methods/constructors provided and overridden in the class Throwable. The two
subclasses that extend Throwable are java.lang.Error and java.lang.Exception.

By now you already have some experience with messages that appear during your
program execution as a result of Java virtual machine informing you, of error

Java Exception Handling Page 4 of 49


incurred during the program. We show an example in Listing 12.3 where a class
called SomeExceptions shows the Error message generated by JVM, when the user
attempts division by zero.

Listing 12.3
The above program will give expected results if user enters a non-zero denominator.
However, Java crashes the program when a zero denominator is entered and all the
code from the point of division by zero and on is skipped. The message on the
standard output is shown below in Figure 12.3.

FIG. 12.3
Java virtual machine crashes the program and points to the line number where it
found the division by zero error. It tells us that a division by zero was attempted at
the line number 15 in the file SomeExceptions.java in the method main. (Java refers
to methods as threads).

Java Exception Handling Page 5 of 49


This type of error checking mechanism, which is in-built in Java, is absent2 in C++
and C, where programmer is responsible for all error checking. Java virtual
machine accomplishes the error checking in Listing 12.3 by throwing (returning) an
object of class java.lang.ArithmeticException, which if uncaught will end the
program. This process is called exception throwing. Another name for the same
process is exception raising. There are two points that we would like to make based
on the Listing 12.3 (Sidebar 12.2).

Sidebar 12.2
• Some exception and error handling is in-built in
java. All user has to do is to learn to use it.
• Java accomplishes the error checking and exception
handling by instantiating an object of a Java class,
which closely relates to the error (or exception) and
then throwing that object at the error location.

We shall see shortly, what the mechanism of “throwing” an object encompasses. But
before we learn to throw objects to recover from errors, we would like to learn, as
how to handle thrown exceptions. This is done by putting the error causing code
inside a block after the keyword try (referred to as a try block), and then catching
any exceptions thrown by that code in a block called catch. The syntax of try – catch
blocks is shown as follows (Figure 12.4).
try
{
//One or more program statements that may throw an exception

} Ex should be of type
catch(Exception Ex) Exception or its sub type.
{
//Zero or more statements that execute after thrown object is caught

}
FIG. 12.4
If an exception condition takes place inside the try block, then an exception object is
returned, and control of program is immediately transferred to the first statement
in the catch block and all the statements inside try block, after the exception
throwing statement are skipped. The catch block is also called an “exception

2
C++ has a limited implementation of automatic exception handling.

Java Exception Handling Page 6 of 49


handler”. The try and catch blocks are generally, used as a bonded pairs – at least
one catch block following a try block3. The catch block acts almost like a method
call, in the sense that it takes an object of type Exception as argument and then
executes the code inside the catch block. You may surmise a pair of try and catch
block as the try block returning a value of type Exception, and passing it to the
catch block immediately following it. Understand that an attempt to write a lone try
or catch block or changing their prescribed order would be a compile error. To
show the above mechanism we modify the code in main of the Listing 12.3 and run
the program again (Listing 12.4– We only show the modified version of main.
public static void main(String[] args)
{
int numerator = 0;
int denominator = 1;
String Input =
JOptionPane.showInputDialog("Please enter the numerator!");
numerator = Integer.parseInt(Input);
Input =
JOptionPane.showInputDialog("Please enter the NON ZERO - denominator!");
denominator = Integer.parseInt(Input);
try
{
JOptionPane.showMessageDialog(null, "The result of division is = "
+ numerator/denominator);
System.out.println("The result of division is = " +numerator/denominator);
}
catch(Exception e)
{
JOptionPane.showMessageDialog(null,
"A Zero denominator has been entered.");
}
System.exit (0);
}
Listing. 12.4
When user enters a zero value of denominator, the second statement inside the try
block is skipped and control transfer to the catch block, where a pop-up message is
displayed. The behavior of Listing 12.4 is different from 12.3 in the sense that now
user gets a more descriptive message shown through a JOptionPane shown in
Figure 12.5 and the program exits gracefully without a cryptic message that JVM
would have produced.

3
When the code inside the try block throws a “un-checked exception”, the try clause, if needed, may
be followed by a finally clause (missing a catch block). Missing a catch block immediately after a try
block is, however, a non-standard practice. We shall discuss finally clause shortly.

Java Exception Handling Page 7 of 49


FIG. 12.5
Sidebar 12.3 summarizes some rules for using try-catch blocks for exception
handling in Java.

Sidebar 12.3
1. Existence of a lone try or catch block is a compile error.
There shall be no other code between the try catch blocks
(works similar to if/else structure).
2. One or more catch blocks may follow a try block. Java will
match the type of object (Exception) thrown in the try block
with the objects in the arguments of various catch blocks,
and wherever it finds the first best match, it will execute the
code in that catch block.
3. In the try block, once the exception is thrown, the code after
that point is skipped and java proceeds to execute the first
matching catch block.
4. The object thrown by the code in try block must be of type
java.lang.Exception. (Throwing the objects of classes Throwable and of
type Error is syntactically correct, but there is no added value in doing so).

Java Exception Handling Page 8 of 49


Types of Exceptions in Java
Java neatly divides the exceptions in two categories:
1. Exceptions that would be checked by the Java compiler (compile time
exceptions).
2. Exceptions that would be thrown by Java Virtual Machine (JVM) at run
time (also called run time exceptions or un-checked exceptions).
Compile time exceptions are also called checked exceptions. Compiler checks the
Java code to ascertain that if the method called throws a checked exception then the
client of that method is forced to call that method only inside a try block. Compiler
does not require the code that could throw a run time or un-checked exceptions to
be placed in the try block. The objects of type java.lang.Error, and
java.lang.RuntimeException form the un-checked exception objects. Figure 12.6
expands further on Figure 12.2, and shows schematically, the class hierarchy of
checked and un-checked exception classes.

FIG. 12.6
All classes that are of type RuntimeException or Error form the un-checked
exception classes, whereas the remaining classes form the checked exception types.

Listing 12.5 shows as how both checked exceptions, and run time exceptions can
manifest, or be handled. The example in Listing 12.5 is a toy example used just for
illustration purpose.

Java Exception Handling Page 9 of 49


public class ExceptionTypes
{ Throws clause required
private ExceptionTypes ( ){ } because body of method1
/** throws an object, which
* Method method1 throws an exception of type needs to be broadcast.
* Exception, which is a checked exception.
*/
public static int method1(int val ) throws Exception
{
System.out.println("From method1, that throws an Exception object");
If(val == 0)
throw new Exception("From method method1");
return 1;
}
/**
* Method method2 throws an exception of type
* RuntimeException, which is an un-checked exception.
*/
public static int method2(int val ) //throws clause optional
{
System.out.println ("From method2, that throws a RuntimeException object");

If(val == 0)
throw new RuntimeException("From method method2");

return 1;
}

public static void main (String[] args)


{
//uncommenting the line below would cause a compile error
//int val1 = method1(0);

//However, the below will compile.


int val2 = method2 (0);
//The call above must be commented out to execute the try catch block below.

Java Exception Handling Page 10 of 49


//call to method1 requires a try-catch block
try
{
int val3 = method1 (0);
}
catch (Exception ex)
{
System.out.println (ex);
}
}
}//Listing 12.5
Listing 12.5 shows two methods, method1 and method2. Inside method1, there is a
statement:
Syntax of a throw
statement
throw new Exception ("From method method1");

The above statement uses the Java reserved word throw followed by the call to the
constructor of Java class java.lang.Exception. This results in returning an object of
type Exception, with the string “From method method1” as being part of the thrown
object. method2 also has a throw statement, which throws an object of type
RuntimeException. Understand that during execution, method1 or method2, could
only do one of the two things: either perform a normal return, which would be
return an integer value of one, or return an exception object following the word
throw.

Let us scrutinize the header of method1 below.

Compile error would be caused if


throws clause is missing.

public static int method1( int val ) throws Exception //throws clause required

Since method1 throws an exception of type java.lang.Exception (which is a checked


exception), its header must broadcast that with the clause throws ClassName
after the argument list. Skipping the throws clause in the header of methods that
throw a checked exception would be a compile error. Reverse is also true. If a
method broadcasts a checked exception to be thrown, then such exception or its
super type must be thrown. A method can throw more than one exception, in which
case they are listed after the keyword throws separated by comma. For example a

Java Exception Handling Page 11 of 49


method that throws three exceptions Exception1, Exception2, and Exception3 (all
checked exceptions), would require a header similar to the one given below:

[Access specifier] return_type methodName ([Argument List]) throws


Exception1, Exception2, Exception3, ………………..

Also clearly understand the difference between reserved words throw and throws.
The word throw is used preceding the instantiation or name of the exception object
to be thrown. On the other hand, the word throws is used as the first word to
broadcast the exception(s) that a method would throw. The word throws is never
used inside a method body and word throw is never used next to the method
header after the argument list.

A compile error would occur, if caller method (main method in this case) tries to call
a method that throws a checked exception with out placing such call in a try block
followed by a catch block that can process the thrown exception. Therefore un-
commenting the statement
This call in Listing 12.5 main
method would be a compile error.
int val1 = method1 (0);

in main would be a compile error. However, the method2 throws an object of type
RuntimeException. Call to methods that throw an object of type4 RuntimeException
is exempted from both requirements – that is to broadcast the exception being
thrown (in the method header), and to place the method call statement in a try
block. Therefore the call below would compile, though the program execution would
terminate right after this call is completed.
Int val2 = method2 (0); This call will compile because method2 throws a
run time exception. However, the program
execution would terminate after the method call.

Last eight lines of the program show the correct technique to call method1 where
pair of try catch block is used to and call to method1 is placed in the try block.

Figure 12.7 shows the compiler and JVM messages and outputs for different calls to
methods method1 and method2 in Listing 12.5.

4
Recall that the word type means that the object could be an instance of that particular class or any
of its subclasses. For example an object of “type” RuntimeException would be either an object of
RuntimeException class or of any of its subclasses.

Java Exception Handling Page 12 of 49


FIG. 12.7A
When the call to method1 is un-commented in the first code line in main (listing
12.5), then compiler flags that call and gives the above compile error message
(Figure 12.7A). What compiler is saying here is that either the main method (inside
which the method1 is being called) must catch the exception thrown by the method1
(by using try catch blocks), or it must declare in its method header to throw the
same object. This brings us to the point in Chapter eight, where we declared the
header of main method as follows:

public static void main(String [ ] args) throws IOException

We made the main method throw an exception of type IOException because we


were calling the method read or readLine inside the main to get user inputted data
from the keyboard. You would recall that these are the methods in BufferedReader
class, which can be used to read a character or a line from the keyboard input.
Table 12.1 gives the headers of these methods and the hierarchy of class
IOException.
public int read( )throws IOException
public String readLine( ) throws IOException
java.lang.Object
java.lang.Throwable
java.lang.Exception
java.io.IOException
Table 12.1
The above table shows that the methods read and readLine throw an exception of
type IOException that is derived from the class Exception and is not of type
RuntimeException (or of type java.lang.Error). Therefore IOException is a checked
exception and the methods that throw an object of this type must either be called
inside a try block or the caller to these methods itself must throw IOException or its
super class object. Therefore using the clause throws IOException next to the
header of main method gave us an exemption from placing calls to methods read
and readLine inside a try block. Were we to remove the clause throws IOException
from the header of main method, we would need to call the methods read and
readLine using the syntax similar to the one we used to call the method1 in last eight
line of Listing 12.5 Or Figure 12.4). We shall illustrate that shortly in a detailed
example.

Java Exception Handling Page 13 of 49


In Listing 12.5 if we comment out the first line (call to method1) but keep the call to
method2 then output generated is shown by Figure 12.7B.

FIG. 12.7B
The call to method2 with out using the try block compiles and runs since method2
throws an unchecked exception. The first line of method2 prints a statement on the
console. However, the program terminates since an exception is thrown and it is not
handled in the way to recover from this error. This is the general characteristic of
all Java programs. When a Throwable object is not caught (or is not catch-able) in
ways that program can recover from such error, then the program terminates.

Finally if we only keep the last eight lines of code in Listing 12.5, where the call to
method1 is placed inside a try block followed by the catch block, we see the output
shown in Figure 12.7C.

FIG. 12.7C
The output first prints the statement from the method1, and then it executes the
catch block, where the toString method for object ex (passed to catch block) is called
and string returned is printed. The toString method of Exception class prints the
qualified class name (java.lang.Exception) and appends the colon and the message
passed to the constructor when the thrown object was instantiated. Notice that the
part of last output line “From method method1” came from the string that was
passed during the following constructor call in method1.

throw new Exception("From method method1");

The formal parameter in the catch clause must match the “type” of actual exception
object thrown from the code inside the try block. For example in Listing 12.5,
writing the catch block as below would result in a compile error.

Java Exception Handling Page 14 of 49


catch(RuntimeException ex)
{
System.out.println(ex);
}

The reason for this compile error is that compiler can determine that
RuntimeException is a subclass of Exception and it is in violation of laws of
inheritance to pass a super class object, when a sub class object is expected.
However a catch block such as below would not be a compile error as when a super
class object is expected by a block or method, a sub class object can always be
passed at the run time.

catch(Throwable ex)
{
System.out.println(ex);
}

Table 12.2 gives some examples of un-checked and checked exceptions commonly
encountered. A verbal description of some of them was given in sidebar 12.1.
Exception throwing Exception class object thrown Type of the
code Object thrown
int val = NumberFormatException1 RuntimeException
Integer.parseInt(“Hello”);
int [ ] arr = new int [5]; ArrayIndexOutOfBoundsException1 RuntimeException
arr[10] = 10;
String Str = null; NullPointerException1 RuntimeException
Str.length ( );
Vector V= new Vector ( ); NoSuchElementException1 RuntimeException
V.firstElement( );
Object I = new Integer(5); ClassCastException1 RuntimeException
Double Dbl = (Double)(I);
BufferedReader BR = null; FileNotFoundException2 Exception
try (checked
{ exception)
BR = new BufferedReader Assume that no drive
(new with letter G exists.
FileReader("G:\\text.txt"));
}
catch(Exception ex)
{
System.out.println (ex);
}

Java Exception Handling Page 15 of 49


1- All are subclasses of class RuntimeException, not requiring the placement of
exception causing code in the try block.
2- Subclass of Exception but not the sub class of RuntimeException or of Error.
Table A12.1.1, in appendix A, shows the complete inheritance hierarchy of all of the
exception classes in column two of this table.
Table 12.2

Based on discussion so far, Java exception handling principles dictate that class
designers and clients:
• are required to provide exception handlers for checked
exceptions. The methods throwing checked exception must
broadcast them in the method header.
• are not expected to provide any handlers for the exceptions of
type java.lang.Error, since recovery from them is generally not
possible.
• may provide exception handlers for exceptions of type
java.lang.RuntimeException, if programmer from the design of
program, can conclude that such handler would provide adequate
program recovery. The broadcasting of thrown unchecked
exceptions in the method header is optional. However, it is a good
programming practice to do so.

Multiple catch clauses


Java allows programmer to place multiple catch clauses following a single try block.
Reverse however, is never true. A catch block can only be preceded either by a
single try block or by another catch block. Multiple catch blocks improve the
granularity of exception handling and pinpoint the error location precisely, which in
turns helps recovery from run time errors. Figure 12.7 shows the syntax of multiple
catch blocks following a try block.

Java Exception Handling Page 16 of 49


try
{
//statements;
}
catch (exceptionType1 identifier1)
{
// zero or multiple statements;
}
catch (exceptionType2 identifier2)
{
// zero or multiple statements;
}
//More catch blocks as needed
//Fig.12.7
We design a class that would have code and methods to prompt user for the name of
an input file and simply print its contents to the console. All input and output,
involving user would be standard I/O type. Let us define the steps in our overall
strategy.
1. Set a boolean variable done to false.
2. Inside a do while loop do the followings:
3. Prompt user for input file name by displaying a message on
console.
4. Accept user input for file name from the keyboard.
5. Create a File class object using the string entered in step four.
6. Create a FileReader object from the File object created in step
five.
7. Test if file has the read permission – if not then display the related
message and set done (step one) to false.
8. Ascertain that file is not hidden. If hidden then set done to false.
9. Ascertain that file has some data in it. If file is empty then set
done to false.
10. Prompt user to provide the size of input buffer.
11. Accept the user-inputted string.
12. Parse the String entered in step 11 into an integer.
13. Create a BufferedReader object by calling the constructor that
would take the FileReader object created in step six and buffer
size in step 12.
14. Pass the object created in step 13 to method readAndPrintFile

Java Exception Handling Page 17 of 49


15. Set done to true
16. Handle all exceptions.
17. Post-test the loop condition.
The step 16 requires that we take an inventory of steps one to 14 and tabulate as to
which steps can throw an exception and what kinds would those be? Table 12.3
shows the step number, which method or constructor would be used in that step,
and what exception can they throw and their type.

Step Class and Name of the Exception Type of


Number method/constructor used thrown Exception
(Checked or
unchecked)
4 BufferedReader/readLine IOException checked
5 File/Constructor that takes NullPointerException unchecked
file name string as
argument
6 FileReader/Constructor FileNotFoundException checked
that takes File object as
argument
7 File/canRead SecurityException unchecked
8 File/isHidden SecurityException unchecked
9 File/length SecurityException unchecked
10
11 BufferedReader/readLine IOException checked
12 Integer/parseInt NumberFormatException unchecked
13 BufferedReader/constructor IllegalArgumentException unchecked
that takes FileReader and
integer as buffer size as
arguments
Table 12.3
All the exceptions listed in the column three of Table 12.3 are already defined by
Java for us. They are either checked exceptions or unchecked exceptions. In order
to place the catch blocks so that all exceptions are “reachable”, we must look at the
inheritance hierarchy of all of them. Table 12.4 provides this information.

Java Exception Handling Page 18 of 49


Exception Names Inheritance Hierarchy
java.lang.Object
java.lang.Throwable
java.lang.Exception
java.lang.RuntimeException
IllegalArgumentException, and
NumberFormatException
java.lang.IllegalArgumentException

java.lang.NumberFormatException

java.lang.Object
java.lang.Throwable
java.lang.Exception
NullPointerException java.lang.RuntimeException

java.lang.NullPointerException

java.lang.Object
java.lang.Throwable
java.lang.Exception
SecurityException
java.lang.RuntimeException
java.lang.SecurityException

java.lang.Object
java.lang.Throwable
java.lang.Exception
IOException and
java.io.IOException
FileNotFoundException
java.io.FileNotFoundException

Table 12.4

Reachable vs. Unreachable Exceptions


When arranging the multiple catch blocks to handle exceptions, Java requires that a
subclass exception be caught first, before a super class exception is caught. For
example based on the hierarchy of exception classes in Table 12.4 it is required that
for the checked exceptions the catch blocks be arranged in the following order
(Figure 12.8A).

Java Exception Handling Page 19 of 49


try
{
//code
}
catch(FileNotFoundException ex)//sub class
{
//code
}
catch(IOException ex)//super class
{
//code
}
//Fig. 12.8A
Notice that the catch blocks for exceptions are arranged in the order (from top to
bottom) that is exact reverse of their inheritance hierarchy (See last row and last
column of Table 12.4). If that were not the case and we were to change the order to
the one given in the Figure 12.8B, then last catch block becomes “unreachable” code
as a super class catch block (IOException in this case) would also catch the subclass
exception (FileNotFoundException).
try
{
//code “Unreachable” catch blocks
} as the first block also
catch(IOException ex) catches exceptions of type
{ FileNotFoundException.
//code
}
catch(FileNotFoundException ex) Compile error!
{
//code
}
//Fig. 12.8B
Java would issue a compile error when such “unreachable” code (Figure 12.8B) is
encountered. Similarly Figure 12.8C shows as how to arrange the handlers for
unchecked exception classes.

Java Exception Handling Page 20 of 49


try
{
//code
}
catch(NumberFormatException ex)//sub class
{
//code
}
catch(IllegalArgumentException ex)//super class
{
//code
}
//Fig. 12.8C
This is so because the IllegalArgumentException is the super class of
NumberFormatException. Therefore, enforcing the “reverse inheritance hierarchy”
rule for the placement of exception handlers, the handler for
NumberFormatException precedes its super class IllegalArgumentException. Notice
that the handlers for the remaining Exceptions, NullPointerException, and
SecurityException have only one requirement, that they be placed before the super
class of all exceptions – Exception (if used). Their placement with respect to other
unrelated classes is unimportant. Also since the checked and unchecked exceptions
are unrelated with respect to their inheritance hierarchy, their relative order of
placement is also unimportant. We follow this arbitrary order, in which we place
the unchecked exception handlers first and then place the checked exception
handlers afterwards. Figure 12.8D shows the overall placement of all exception
handlers in our forthcoming listing.
try{
//code}
catch(NumberFormatException NFEx)//Sub class of IllegalArgumentException
{
//code}
catch(IllegalArgumentException IllegalEx)//unchecked exception
{
//code}
catch(NullPointerException NPex)//unchecked exception
{
//code}
catch(SecurityException SC)//unchecked exception
{
//code}

Java Exception Handling Page 21 of 49


catch(FileNotFoundException FX)//checked exception - subclass of IOException
{
//code}
catch(IOException ex)//checked exception - subclass of Exception
{
//code}
catch(Exception ex) //Super class of all exception classes
{
//code}
//FIG. 12.8D
We place the last catch clause to catch any remaining exception that our code may
throw. A handler with Exception as its formal argument would catch any exception
that were not caught by other handlers preceding it. Listing 12.6 shows the source
code for the class ReadDataFile, which codes the algorithm described earlier and
uses the exception handling strategy developed in Figure 12.8D.
00001 import java.io.*;
00002
00003 public class ReadDataFile
00004 {
00005 private ReadDataFile(){}
00006
00009 public static void main (String[] args)
00010 {
00011 BufferedReader KB = new BufferedReader
00012 (new InputStreamReader(System.in));
00013 String Input = new String();
00014 boolean done = false;
00015
00016 do
00017 {
00018 try
00019 {
00020 System.err.println
00021 ("Please type the name of data input file and then press enter key.");
00022 Input = KB.readLine();//readLine can throw IOException
File FL = new File(Input);//File class constructor can throw NullPointerException
00024 FileReader FR = new FileReader(FL);//Can throw FileNotFoundException
00025 //check for length, hidden status, and read permission.
00026 //Violation of any of them would cause SecurityException to be thrown
00027 if(FL.canRead())
00028 {
00029 if(!FL.isHidden())
00030 {

Java Exception Handling Page 22 of 49


00031 if(FL.length() != 0)
32 {
33
00033 System.err.println("Please specify the size of read buffer");
00034 Input = KB.readLine();
00035 int buf = Integer.parseInt(Input);
00036 BufferedReader FReader = new BufferedReader(FR, buf);
00037 readAndPrintFile(FReader);
00038 done = true;
00039 }
00040 else
00041 {
00042 System.err.println("The file has no data in
it.");
00043 done = false;
00044 }
00045 }
00046 else
00047 {
00048 System.err.println("The file is hidden.");
00049 done = false;
00050 }
00051 }
00052 else
00053 {
00054 System.err.println("The file does not have read permission");
00055 done = false;
00056 }
00057
00058 }//end of try block
00059 catch(NumberFormatException NFEx)//unchecked exception
00060 {
00061 NFEx.printStackTrace(System.err);
00062 System.err.println("Non-numeric buffer size has been entered.");
00063 }
00064 catch(IllegalArgumentException IllegalEx)//unchecked exception
00065 {
00066 IllegalEx.printStackTrace(System.err);
00067 System.err.println("Illegal buffer size has been eneterd.");
00068 done = false;
00069 }
00070 catch(NullPointerException NPex)//unchecked exception
00071 {
00072 NPex.printStackTrace(System.err);
00073 System.err.println("Null file name or null string has been entered.");
00074 done = false;

Java Exception Handling Page 23 of 49


00075 }
00076 catch(SecurityException SC)//unchecked exception
00077 {
00078 SC.printStackTrace(System.err);
00079 done = false;
00080 }
catch(FileNotFoundException FX)//checked exception - subclass of IOException
00082 {
00083 FX.printStackTrace(System.err);
00084 done = false;
00085 }
00086 catch(IOException ex)//checked exception - subclass of Exception
00087 {
00088 ex.printStackTrace(System.err);
00089 System.err.println("Input reading error.");
00090 done = false;
00091 }
00092 catch(Exception ex)
00093 {
00094 System.err.println("Unknown error/exception has occurred.");
00095 done = false;
00096 }
00097 }while(!done);
00098 }
00101 public static void readAndPrintFile(BufferedReader BR)
00102 {
00103 String Data = null;
00104 int count = 0;
00105 try
00106 {
00107 System.err.println("Printing your file to screen now.");
00108 System.err.println("
00109 while((Data = BR.readLine()) != null)
00110 {
00111 System.err.println(Data);
00112 if(++count %7 == 0)
00113 {
00114 try
00115 {
00116 System.err.println("Press enter to continue printing.");
00117 System.in.read();
00118 }
00119 catch(IOException ex)
00120 {
00121 System.err.println("Keyboard input error.");
00122 }

Java Exception Handling Page 24 of 49


00123 }
00124 }
00125 }
00126 catch(IOException ex)
00127 {
00128 System.err.println("File reading error.");
00129 }
00130 System.err.println("
00131 System.err.println("Done printing.");
00132 }
00133 }
//Listing 12.6
In Listing 12.6 we use the object System.err to print message to console, as in some
cases where file processing is involved, the System.out may fail to print the message
on the console. On the other hand the System.err.println is always able to print
message to the console. For example if a code snippet below (in the main method of
Class1) is run from the command line with the following command:

System.out.println ("Can be directed to a file.");


System.err.println ("Cannot be directed to a file.");
>java Class1 > file

then the message “Cannot be directed to a file." Would print to console,


whereas the first message would be redirected to the file. Therefore to ascertain that
user attention is drawn to messages from exception handlers, then it is best to use
System.err.println/print methods.

The algorithm for Listing 12.6 discussed earlier is implemented as follows. User
input for the input file name is taken from the standard input (L12.6#22). Since
readLine method can throw an IOException, a catch block is included (L12.6#86-
91). The user inputted string is passed as an argument to the File class constructor
to create a File object FL (L12.6#23). This File class constructor can throw a
NullPointerException, for which a handler is placed (L12.6#70-75). The File class
constructor throws a NullPointerException, when a null string is passed to it as
argument. Then the File object FL is passed to the constructor of FileReader class to
create a FileReader object FR (L12.6#24). This constructor can throw a
FileNotFoundException, and we add a handler for that as well (L12.6#81-85).

We need to ascertain further that:


• File has read permission
• File is not hidden
• And file is not empty.
We use the File Object FL and File class methods canRead, isHidden, and length for
these authentications. However, depending upon whether the file has read
permission or not, these three methods can throw an object of class

Java Exception Handling Page 25 of 49


SecurityException, for which we add a handler (L12.6#76-80). A system of enclosing
if/else blocks filters down to the last block (L12.6#31-39), by when the following
facts have been established:
• There is no error reading from keyboard.
• A non-null file name has been provided and file exists.
• File has read permission, is not hidden and has data in it.
The user is prompted to provide an integer value for the size of the read buffer
(L12.6#33). The user input is parsed and stored into int variable buf, and then
FileReader object FR created earlier and buffer size buf are passed to the
constructor of BufferedReader class to create an object Freader (L12.6#36). The
integer parsing process can throw a NumberFormatException, and BufferedReader
constructor used can throw an IllegalArgumentException. Therefore the handlers
for both of them are added (L12.6#59-69). If no exceptions are thrown up to code
line L12.6#36, then the object Freader is passed to method readAndPrintFile to read
the file and print it to console.

Code inside exception handlers


Inside each exception handler we add the code of the following type:

catch (ExceptionType Ex)


{
Ex.printStackTrace (System.err);
System.err.println (“Message”);
done = false;
}
All exception classes inherit the overloaded method printStackTrace, and Table 12.5
gives its various versions along with the method getMessage.
public void printStackTrace()
Prints this Throwable and its backtrace to the standard error stream. This method
prints a stack trace for this Throwable object on the error output stream that is the
value of the field System.err. The first line of output contains the result of the
toString() method for this object. Remaining lines represent data previously
recorded by the method fillInStackTrace().
public void printStackTrace(PrintStream s)
Prints this Throwable and its backtrace to the specified print stream.
Parameters: s - PrintStream to use for output
public void printStackTrace(PrintWriter s)
Prints this Throwable and its backtrace to the specified print writer.
Parameters: s - PrintWriter to use for output
public String getMessage()
Returns the detail message string of this Throwable.
Returns: the detail message string of this Throwable instance (which may be null).
Table 12.5

Java Exception Handling Page 26 of 49


The method printStackTrace first gives message, which is the string returned by its
toString method. We saw example of that in the catch block in Listing 12.5, where
the toString method prints the full name of the Exception class followed by a colon
and the message passed to the constructor (or a default message) of the thrown
object. The fillInStackTrace method records the stack trace information in a
Throwable object, which is also printed by the method printStackTrace. The
method getMessage can also be used. In our opinion, however, it is no more useful
than just calling the toString method of exception object and printing that string
directly. That using method printStackTrace is a better choice would become clear
shortly, when we discuss the output from Listing 12.6.

After printing the message from printStackTrace method, we add any other
optional/clarifying message in the catch block. Finally we set the loop control
boolean variable to false, as the normal loop processing did not take place.

Method readAndPrintFile and nested try catch blocks


The purpose of the method readAndPrintFile is to get a valid BufferedReader
reference to a data file (with data in it) and print its contents to console (L12.6#101-
132). The method uses a EOF controlled loop to read the input file line by line
(L12.6#109-124). Since readLine method can throw an IOException the loop is
placed inside a try block and a handler is added (L12.6#126-129). We add additional
code to ascertain that user has a chance to pause the program after seven lines. This
requires creation of a “nested” try catch block (L12.6#114-122). Notice that there is
no limitation in nesting a try-catch block inside another try block as needed. The
requirement however is that handlers for the nested try block, also must lie inside
the enclosing try block. The nested try block prints a message for the user and
prompts them to press enter key to continue printing the input file to console. The
user input is consumed by the method call System.in.read. Since call to read method
throws IOException, we add the handler for it as well (L12.6#119-122). If execution
of the method ends normally then input file is printed to the console.

Output from Listing 12.6


We test Listing 12.6 by creating as many error conditions as we can. However, all
error conditions are not tested. Figure 12.9 shows the results of our test.

Java Exception Handling Page 27 of 49


1. NullPointer
Exception
thrown/caught

2.
FileNotFoundException
thrown/caught

3.
NumberFormatException
thrown.

4.
IllegalArgumentException
thrown

FIG. 12.9

Java Exception Handling Page 28 of 49


The program prompts user to input a file name, and if user presses control Z keys
on DOS (or control D in Unix), then a null string is entered. The File class
constructor (L12.6#23) throws a NullPointerException and the corresponding catch
block prints the stack trace and displays the message from that block (L12.6#70-75).
The following lines printed by printStackTrace method elucidate the source of
error.

at java.io.File.<init>(Unknown Source)
at ReadDataFile.main(ReadDataFile.java:23)

The first line says that the constructor of class java.io.File threw an exception. (Java
indicates constructors by expression <init>). Second line gives the location of the line
in the class and method, where the exception was thrown.

When user provides a non-existent file name then the FileNotFoundException is


thrown (bubble #2: Figure 12.9). The program prints back the file name provided
and prints the message that file is not found. The stack trace indicates that exception
was thrown by the call to “native5” open method by the object of FileInputStream
class, and propagated thru the constructors of classes FileInputStream and
FileReader classes.

After providing a valid file name the user is prompted to enter the size for the read
buffer. A NumberFormatException is thrown when a non-numeric string is entered
(bubble #3 Figure 12.9). And an IllegalArgumentException is thrown by the
constructor of class BufferedReader when the buffer size entered is zero or negative
(bubble #4 Figure 12.9). Program prints out the file provided when a valid buffer
size is entered. Notice that in this listing we were not able to test throwing of
SecurityException and IOException as special device and file permission conditions
need to be created to throw those exceptions.

finally clause
There are situations when the exceptions are thrown, user is informed of the error
condition, and if program resumption is not possible then in the way of recovery the
program tries to reclaim resources as soon as possible. This reclamation of
resources may be connected to for example:
• Closing output file, so that the data written so far is saved safely.
• Closing the input file safely.
• Closing connections to databases.
• Close a socket or network connection.
• Disposing the graphical components using the program memory..
etc.

5
A native Java method calls an existing method that may have been written another programming
language, residing on the operating system or platform on which the program is being run.

Java Exception Handling Page 29 of 49


Java allows one to put a clause labeled finally after the try catch blocks. The
characteristic of finally block is that as long as System.exit (0) is not called from
inside of any of the preceding try and catch blocks then the code inside the
finally block is always executed! Figure 12.10 shows the syntax of using finally
block.
try
{
//statements;
}
catch (exceptionType1 identifier1)
{
// zero or multiple statements;
}
catch (exceptionType2 identifier2)
{
// zero or multiple statements;
}
//more catch blocks if needed Always executed (As long as
finally the preceding try and catch
{ blocks do not call
System.exit (0).
//code
}
FIG. 12.10
Mostly the finally clause is used after a set of try catch blocks. However Java
allows finally block to be placed right after a try block – missing a catch block
altogether. Therefore the following will compile and could be useful in situations,
where catching an exception does not help the situation and finally block
executes the rescue code (Figure 12.11).
try
{
//statements;
}
finally
{
//code
}
FIG. 12.11
You have perhaps noticed by now that we did not actually close the input file in
the Listing 12.6. In order to safely close the input file in Listing 12.6 we add the

Java Exception Handling Page 30 of 49


following piece of code using a finally clause between the lines 129 and 130
(Figure 12.12).
finally
{ Unless an
try IOException is thrown
{ again, the rescue code
BR.close ( ); closes the file safely!
}
catch(IOException Ex)
{
Ex.printStackTrace(System.err);
System.err.println("File closing error");
}
} Fig.12.12
Notice that in this case the try catch block inside the finally block is needed as
the call to method close would throw an IOException. A finally block can also
contain try catch and finally blocks. Use of finally block is very useful when the
program is writing to an output file and file need to be closed safely, so that user
data are saved in spite of program crash. Similar situation exists when the
program is writing to the database and connection to database is needed to be
closed lest the database gets corrupted upon program crash.

Coping with un-checked exceptions


Generally checked exceptions have a well-defined hierarchy. Thus placing the
catch blocks for them in order reverser of their inheritance hierarchy may locate
their origin rather well. Un-checked exceptions do not always have this
advantage. For example in our Listing 12.6 a NullPointerException can be
thrown when either File class constructor gets a null string (L12.6#35), or a null
string is entered for the buffer size (L12.6#35). Thus in the handler for
NullPointerException, we have to be satisfied with the message that “"Null file
name or null string has been entered." Fortunately, the call to printStackTrace
method would pinpoint the location as to where exception was thrown; still it is
an inconvenient feature to use. For an un-checked exception that can be thrown
at various locations, each such location needs to be isolated in a separate try
block. Such “error-trapping” can be expensive in terms of program overhead,
however in mission critical software applications, it may be a necessity. For
example, very often in databases all fields of stored objects are not required to
be filled6. Let us assume that our database keeps records of student names, and
their GPA. We may end up creating two vectors from the queries made to our
database, that are followings.

6
In relational databases, it is desirable to have primary key, but it is not required.

Java Exception Handling Page 31 of 49


Vector Names = new Vector( );
//Fill Names Vector with student names for a certain class
Vector GPA = new Vector ( );
//Fill GPA Vector with the GPA of students.

If the two vectors Names and GPA are used independently (as if they have
nothing to do with each other) then there is no problem. For example, the Names
vector can print student names and GPA vector can print a list of GPA and find
average GPA, etc. The problem comes when we try operations like below:

int ind = 5;
String Student_Name = (String)Names.elementAt(ind);
double current_gpa =
Double.parseDouble(GPA.elementAt(ind).toString());
System.out.println(“The GPA of student “ + Student_Name
+ “ is = “ + current_gpa);

The code above tries to print the GPA of student at the location index = 5, in the
Names vector. Even after assuming that we have confirmed by calling the size
method to make sure that ind = 5, is a valid element in vector Names, we are naively
assuming that database stores GPA for all students! For example students who are
attending college for the first time may not have a GPA, and database may not
require a number to be stored in that field. As a result the elementAt method called
second time may throw ArrayIndexOutOfBoundsException. Worse yet, knowing
that Vector stores Objects, there is no certainty that element at location index = 5 is
indeed a Double type element. This can happen if some how the vector GPA became
corrupted in the process of adding elements to it. Figure 12.13 shows, as how one
would separate this code into neat pieces for exception handling and error trapping.
//Assume that Vector Names and GPA are already populated with student names
//and GPA respectively. Code tasks to print the GPA of student at index = 5 in
//Names Vector. If all students have GPA then size of both vector must be same.

if(Names.size ( ) != GPA.size ( ))
throw new RuntimeException (“Vectors storing student names and GPA “
+ “have different sizes.”);

String Student_Name = new String( );


int ind = 5;

Java Exception Handling Page 32 of 49


try
{
Student_Name = (String)Names.elementAt (ind); //Line #1
Double Temp = GPA.elementAt (ind); //Line #2
try
{
double current_gpa = Double.parseDouble(Temp); //Line#3
System.out.println(“The GPA of student “ + Student_Name
+ “ is = “ + current_gpa);
}
catch(NumberFormatException Ex)
{
Ex.printStackTrace (System.err);
}
}
catch(ArrayIndexOutOfBoundsException Ex)
{
Ex.printStackTrace (System.err);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
FIG.12.13
In the code shown in Figure 12.13, the error trapping strategy uses combination of
Vector class method calls, throwing un-checked exception, and use of nested try
catch blocks to handle un-checked exceptions. The caller of this code, if they wish,
could use a try catch block also to handle the RuntimeException thrown, when
Vector sizes are unequal. Since we did not ascertain that ind is positive and less than
size, we must use the try catch block when we get the element at the index ind. If an
ArrayIndexOutOfBoundsException would be thrown at line #1 then program would
abort and execute the catch block for it. If Line#1 does not throw an exception then
Line #2 would not either as we have ascertained that size of two vectors are same.
However, to trap the parsing error (in case the GPA vector has non Double element
at location ind), we call the parseDouble method inside another try block, which is
followed by a catch block to handle NumberFormatException. If Line#3 throws the
NumberFormatException, then the program is aborted there and catch block after
it is executed. However, if no exception is thrown on Line #3, then rest of the code
executed error free.

This somewhat contrived example illustrates the strategy for coping from un-
checked exceptions and their use for error trapping. In actual application a better
technique would be to create a Student class, where Name and gpa fields are
populated first, and then use a Vector of Student objects to print record of each
student, rather than trying to use two parallel vectors the way we used here.

Java Exception Handling Page 33 of 49


Designing user defined exception classes
The mechanics of implementing user defined exception classes is quite simple. In
order to design a new checked exception user would inherit the new class from the
java.lang.Exception class or from any of its non-final unchecked exception
subclasses. For new unchecked exception classes one would inherit the new class
from java.lang.RuntimeException class. We show the constructors for Exception
class in Table 12.6.
Constructor Summary for java.lang.Exception class
Exception()
Constructs a new exception with null as its detail message.
Exception(String message)
Constructs a new exception with the specified detail message.
Exception(String message, Throwable cause)
Constructs a new exception with the specified detail message and cause.
Exception(Throwable cause)
Constructs a new exception with the specified cause and a detail message of
(cause==null ? null : cause.toString()) (which typically contains
the class and detail message of cause).
Table 12.6
The constructors for class RuntimeException are exactly same type as they take the
same arguments. Let us assume that we need to design an exception class to
facilitate array processing, over and above what Java already provides for us. For
example when an array reference is passed to a method as an argument – two things
can happen:
• The array reference may be null, in which case the method can throw a
NullPointerException as there is not much processing that method can do
with such null reference.
• Array has a zero size. In this case also no processing is possible. Method can
check the size of array for non-zero value before proceeding further.
However, no standard exception is available that can be thrown if method
receives a zero size array. If method must return a value, then it can simulate
array access using the following code and since the array has a zero length, it
would throw a ArrayIndexOutOfBoundsException.

int [] arr = new int[0]; Will throw


int val = arr[0]; ArrayIndexOutOfBoundsException
since array size is zero and there are
no elements in it.

Client of the method can catch that exception and process it further to know that a
zero array size was passed to the method. The problem with this is that
ArrayIndexOutOfBoundsException is not very informative of the situation that a
zero size array was passed to the method! Therefore what is desirable is to define a

Java Exception Handling Page 34 of 49


new Exception class that would inform user of the fact that a zero size array was
passed to the method. Let us call this exception class as ZeroArraySizeException.
And we design it to be a sub class of RuntimeException – which means that it is of
unchecked type. Listing 12.7A shows this incredibly easy to design exception class.
public class ZeroArraySizeException extends RuntimeException
{
public ZeroArraySizeException()
{
super( );
}

public ZeroArraySizeException(String Message)


{
super(Message);
}

public ZeroArraySizeException(String Message, Throwable Cause)


{
super(Message, Cause);
}

public ZeroArraySizeException(Throwable Cause)


{
super(Cause);
}
}//Listing 12.7A
All one has to do is to implement the four constructors and call super class
constructor inside each! Additional method and fields may be added if further
customization is needed. Let us assume that we are writing a method findMin,
which takes an integer array as argument and returns lowest value stored in it.
Listing 12.7B shows a test class Class1 that contains this method, which in turn uses
the exception class in Listing 12.7A.
00002 public class Class1
00003 {
00004 public static void main (String[] args)
00005 {
00006 int [ ] arr = new int[(int)(10*Math.random( ))];;
00007 boolean OK = true;
00008
00009 if((int)(10*Math.random())%5 == 0)
00010 {
00011 arr =null;
00012 OK = false;
00013 }
00014

Java Exception Handling Page 35 of 49


00015 if(OK)
00016 {
00017 for(int ind = 0; ind<arr.length; ++ind)
00018 arr[ind] = (int)(100*Math.random());
00019
00020 //print the array.
00021 System.out.println("Printing your array.");
00022 for(int ind = 0; ind<arr.length; ++ind)
00023 System.out.print(arr[ind] + " ");
00024 System.out.println();
00025 }
00026
00027 //get and print the smallest value
00028 int min = 0;
00029 try
00030 {
00031 try
00032 {
00033 min = findMin(arr);
00034 System.out.println("The smallest element in the array printed above is "
00035 + min);
00036 }
00037 catch(NullPointerException Ex)
00038 {
00039 Ex.printStackTrace(System.err);
00040 }
00041 }
00042 catch(ZeroArraySizeException Ex)
00043 {
00044 Ex.printStackTrace(System.err);
00045 }
00046
00047 }
00048
00049 public static int findMin(int [] arr)
00050 {
00051 if(arr == null)
throw new NullPointerException("findMin:The array passed to method is a null "
00053 + " reference.");
00054
00055 if(arr.length == 0)
throw new ZeroArraySizeException("findMin: The size of the array passed to"
00057 +" \nthe method is zero.");
00058
00059 int min = arr[0];
00060

Java Exception Handling Page 36 of 49


00061 for(int ind=0; ind<arr.length; ++ind)
00062 if(arr[ind]<min)
00063 min = arr[ind];
00064
00065 return min;
00066 }
00067 }
//Listing 12.7B
The method findMin (Listing12.7B#49-66) takes an integer as argument. The
method returns the smallest number in the array. However, the array reference
passed to the method may be null. Therefore the method examines array arr for null
value. If arr is null then the method throws a NullPointerException
(Listing12.7B#51-53). Then the method checks if arr has a zero length, and if true, it
throws a ZeroArraySizeException object (Listing12.7B#55-57) that we designed in
Listing 12.7A. Method uses the standard algorithm to find the smallest value and
returns it provided none of the exceptions are thrown.

In order to test the method findMin, we create an array of random length in main
method (Listing12.7B#6). During some invocations, method Math.random would
supply a zero number, and zero length arrays would be created. We also set the
array arr to a null value randomly (Listing12.7B#9-13), in which case we set the
boolean flag OK to false. If OK is not set to false, then we have a non-null array,
which we fill with random numbers and print it soon after (Listing12.7B#15-25).
Call to method findMin could throw either ZeroArraySizeException or
NullPointerException. Since these two exceptions are unrelated, the order in which
they are thrown is unimportant. However, since in method findMin the
NullPointerException is thrown first, we handle it first in a nested try catch block
(Listing12.7B#31-40). (Understand that client may not have the information as to
which exception is thrown first by the method findMin). Then outer try catch block
handles ZeroArraySizeException. Figure 12.4 shows the results from several run of
the main method in Listing 12.7B.
Printing your array.
66 97 65 56 57 96
The smallest element in the array printed above is 56

Printing your array.


17 56 74 11 90 45 65 73
The smallest element in the array printed above is 11

Printing your array.

ZeroArraySizeException: findMin: The size of the array passed to


the method is zero.
at Class1.findMin(Class1.java:56)
at Class1.main(Class1.java:33)

Java Exception Handling Page 37 of 49


Printing your array.
50 90 70 89 5 97 41
The smallest element in the array printed above is 5

Printing your array.


30 80 48 84 64 15 99 29 35
The smallest element in the array printed above is 15

Printing your array.


35 1 73
The smallest element in the array printed above is 1

Printing your array.

ZeroArraySizeException: findMin: The size of the array passed to


the method is zero.
at Class1.findMin(Class1.java:56)
at Class1.main(Class1.java:33)

java.lang.NullPointerException: findMin:The array passed to method is a null


reference.
at Class1.findMin(Class1.java:52)
at Class1.main(Class1.java:33)
//FIG. 12.14
When the null or zero size arrays is not passed to the method findMin, it returns a
normal value, which is the lowest value in the array. Otherwise it returns
exceptional values thru either thrown NullPointerException or
ZeroArraySizeException. The method such as findMin is an example of total
method (function) that we discussed in first few pages of this chapter as it has a well
defined behavior for all inputs provided to it and has no pre-condition for its use.
Most methods used by client can be made into total methods by judicious use of
exceptions. There is an alternate code for method findMin shown by Figure 12.15.
public static int findMin(int [] arr)
{
int min = 0;
try
{
min = arr[0];
}
catch(ArrayIndexOutOfBoundsException Ex)
{
throw new ZeroArraySizeException("findMin: The size of the array passed to"
+" \nthe method is zero.",Ex);
}

Java Exception Handling Page 38 of 49


for(int ind=0; ind<arr.length; ++ind)
if(arr[ind]<min)
min = arr[ind];

return min;
}//FIG. 12.15
In alternate code we do not explicitly check for arr being null or having zero size.
We simply attempt to set min equal to arr [0]. If array size is zero then
ArrayIndexOutOfBoundsException would be thrown. In catch block we throw the
new exception ZeroArraySizeException, so that user gets the precise information
about the nature of exception thrown. Functioning of both methods is similar. The
first version is logically easier to understand, whereas the second version is more
compact. In second version both, NullPointerException and
ArrayIndexOutOfBoundsException are thrown implicitly by JVM. First one is
thrown when a null arr is passed and script operator [ ] are applied to the null
reference. Second one is thrown when program tries to access the first element in a
zero length array.

Checked versus unchecked exceptions


A harder software engineering choice is to decide whether to design the user defined
exception class to be an unchecked exception or checked one. There is one school of
thought, which includes author Bruce Eckel, who has come out totally in favor of
unchecked exceptions. In fact new Microsoft language C# does not have checked
exceptions. Other experts, such as Barbara Liskov7 from MIT, prefer a judicious
mixture of both.

Liskov view point is to use unchecked exceptions if the client can easily enforce the
pre-conditions dictated by the method being called. This may happen if
confirmation techniques are available for easy enforcements of pre-conditions. For
example in our Listing 12.7B, the client (main method) can easily check if the array
passed to the method findMin is a null pointer or a zero size array (in fact the first
version of findMin just does that). Then exception condition would arise only
occasionally thru programming slips. For example in Java it is quite easy to avoid
ArrayIndexOutOfBoundsException as arrays carry their length.

There are situations, however, when techniques to confirm whether the arguments
used for the method would meet pre-condition or not may not exist or may be as
expensive or more expensive to use than using a compile time exceptions. In such
situations use of checked exceptions would be cost effective. For example let us
assume that a piece of software searches for a key in an array using a method,
whose header is given below.

public int search(int [ ] arr, int key)

7
Program Development in Java by Barbara Liskov, John Guttag Addison Wesley 2001

Java Exception Handling Page 39 of 49


Method search is supposed to return the index of the array element where key is
found scanning the array in the ascending order, otherwise search returns a sentinel
value for array index = -1. If numerous calls were made to search then each time
checking the return value for its sentinel state before it can be employed in further
data processing would also be very expensive. In such situations using checked
exceptions becomes cost effective in terms of processing time.

Listing 12.8 shows the design of checked exception class


ElementNotFoundException, the test class Class1. Later includes the method search
and its application.
00002 public class ElementNotFoundException extends Exception
00003 {
00004 public ElementNotFoundException()
00005 {
00006 super();
00007 }
00008
00009 public ElementNotFoundException(String Message)
00010 {
00011 super(Message);
00012 }
00013
00014 public ElementNotFoundException(String Message, Throwable Cause)
00015 {
00016 super(Message, Cause);
00017 }
00018
00019 public ElementNotFoundException(Throwable Cause)
00020 {
00021 super(Cause);
00022 }
00023 }
00002 public class Class1
00003 {
00004 public static void main (String[] args)
00005 {
00006 int [] arr = new int[100];
00007
00008 for(int ind = 0; ind<arr.length; ++ind)
00009 arr[ind] = (int)(100*Math.random());
00010
00011 //print the array.
00012 System.out.println("Printing your array.");
00013 for(int ind = 0; ind<arr.length; ++ind)
00014 {
00015 System.out.print(arr[ind] + " ");

Java Exception Handling Page 40 of 49


00016 if(ind%10 == 0)
00017 System.out.println();
00018 }
00019 System.out.println();
00020 //Just check for 10 randomly generated keys
00021 for(int index = 0; index<10; ++index)
00022 {
00023 int key = 0;
00024 try
00025 {
00026 key = (int)(100*Math.random());
00027 int val = search(arr,key );
00028 System.out.println("The value " + key +
00029 " is found in the array at location " + val);
00030 }
00031 catch(ElementNotFoundException Ex)
00032 {
00033 Ex.printStackTrace(System.err);
00034 }
00035 }
00036 }
00037
00038 public static int search(int [] arr, int key)throws ElementNotFoundException
00039 {
00040 //prime read to throw implicit NullPointer and
00041 //ArrayIndexOutOfBoundsException, in case arr is a null
00042 //reference or zero length array.
00043 int value = 0;
00044
00045 try
00046 {
00047 value = arr[0];
00048 }
00049 catch(ArrayIndexOutOfBoundsException Ex)
00050 {
00051 throw new ZeroArraySizeException(
00052 "search: The size of the array passed to"
00053 +" \nthe method is zero.",Ex);
00054 }
00055
00056 boolean found = false;
00057
00058 for(int ind = 0; ind<arr.length && !found; ++ind)
00059 {
00060 if(arr[ind] == key)
00061 {

Java Exception Handling Page 41 of 49


00062 value = ind;
00063 found = true;
00064 }
00065 }
00066
00067 if(!found)
00068 throw new ElementNotFoundException("The element " + key +
00069 " was not found in the array.");
00070
00071 return value;
00072 }
00073
00074
00075 }
//Listing 12.8
Figure 12.16 shows the output from the main method in Listing 12.8 (from Class1).

FIG. 12.16
It may be daunting for traditional programmers to see that we are actually using the
exception throwing mechanism to print a legitimate message that certain key was
not found in the array (Figure 12.16). While this is unconventional, when using

Java Exception Handling Page 42 of 49


checked exceptions, this mechanism is sound and effective. Since the technology
used in the method search in Listing 12.8 never returns an out of bound array index,
such index can be used further for any automatic data processing, since a check for
its non-sentinel state is not required.

Re-throwing or reflecting exceptions


If a method gets a thrown object and it does not have a handler for it, then it would
re-throw that object to its caller. If the thrown object is checked exception type, then
the method getting the object has two choices: either provide a handler for it or
broadcast in its header to throw that object. For example the method search in
Listing 12.8 throws a checked exception of type ElementNotFoundException. Its
caller main method must either provide the handler for it or re-throw this object.
(We use the first choice in main method of Class1). Listing 12.9A shows a system of
five methods calling each other. Here main method calls Func1, and Func1 calls
Func2 and so on, until finally method Func4 throws an unchecked exception of type
ErrType.
public static void main( String [] args)
{
Func1( );
}
public static void Func1( )
{
Func2( );
System.out.println("In method Func1”);
}

public static void Func2()


{
Func3();
System.out.println("In Method Func2”);
}

public static void Func3()


{

Func4();
System.out.println("In Method Func3”);
}

public static void Func4( )


{
throw new ErrType( );
System.out.println("In Method Func4");
}
//Listing 12.9A

Java Exception Handling Page 43 of 49


Figure 12.17A shows the mechanism for the propagation of this exception thru
various method calls.

FIG. 12.17A
Since none of the methods in Listing 12.9 have a handler for the thrown object
ErrType, it propagates from its thrower Func4 to Func3, to Func2, to Func1, and
finally to the main method where the program would crash. One can see that in re-
throwing an exception, no explicit throw statement is needed. Exceptions
automatically propagate thru the hierarchy of method calls – until they find a
handler or eventually crashing a program if no handler were found. This
propagation hierarchy would terminate, as soon any pf the method in the path of
hierarchy provides a handler. For example we change the code in Func1 as

try{
Func2( );
}
catch(ErrType Ex){ /*code*/ }
System.out.println("In method Func1”);

The re-throw from Func3, to Func2, to Func1 would continue as it did in Figure
12.17A. However, since Func1, now has a handler, the propagation stops there and

Java Exception Handling Page 44 of 49


program no longer crashes. Figure 12.17B shows the change in propagation
hierarchy compared to Figure 12.17A.

FIG. 12.17B
Notice that the program in Listing 12.9A would not have an output because all
output statements are after the call that throws an exception – and exception never
gets caught. However if we alter the code in Func1 to provide a handler (as shown
earlier), the output statement from Func1 would be executed.

To re-throw or to provide a handler


Decision whether a method should provide a handler for explicit or implicit
exceptions thrown to it depends upon as to where in the call sequence is the best
place to process the thrown object. The call sequence we see in Figure 12.17 can be
likened to software layers communicating thru each other. The lowest layer where
the exception occurs is Func4, and top layer where program begins is the main
method. In this sense the main method is the client of all other layers (Func1, Func2,
Func3, and Func4). Certainly if Func4 threw a checked exception, the client would
need to handle it. Situation is not so clear for unchecked exceptions, which client
may or may not choose to handle. The most important consideration here is that if
designer of class decides to change the implementation of class API, any design
change should not break the older client code. For example if exception ErrType

Java Exception Handling Page 45 of 49


were an unchecked exception and main method decides to provide a handler for
thus altering the code in main as below.

try
{
Func1 ( );
}
catch (ErrType Ex){/*code*/}

Now if at some later date the designer of Func4 changes the method design and
decided to throw some exception other than ErrType, then it would break the client
code. This can also happen if design of other layers (Func1, Func2 etc.) changes to
throw some other exception. Therefore the guiding criterion in deciding to re-throw
or handle an exception is to ascertain that changes do not break the client code.

Case Study1: Designing class methods with exceptions to obey class


invariants
In chapter four we discussed the concept of invariants and we showed the partial
code for a bank account class. Let us state the invariant for BankAccount class
again and redesign it – this time using Java defined exceptions to maintain the class
invariant. We define a simple invariant for BankAccount class that at no time the
minimum balance for the account holder shall go down below $25.00, and of course
methods to make withdrawal and deposit must work correctly. (to complete).

CaseStudy2: Improved IOManagement class


(to complete)

Questions
1. (T/F) A try block can be used with out the use of subsequent catch block.
2. (T/F) A catch block can be used without use of try block preceding it.
3. (T/F) try catch blocks must be used as a pair.
4. A method throwing a checked exception must throw an object, which is of
type:
A] Throwable but not of type RuntimeException
B] RuntimeException
C] Exception
D] Throwable
E] All of above.
5. A method throwing an un-checked or run time exception must throw an
object of type? (Select correct answer from the list given for question #4).

Java Exception Handling Page 46 of 49


6. (T/F) The header of a method throwing a checked exception must broadcast
the exception being thrown.
7. (T/F) The header of a method throwing an un-checked exception must
broadcast the exception being thrown.
8. (T/F) The header of a method throwing an un-checked exception may
broadcast the exception being thrown.
9. (T/F) The call to the method throwing a checked exception must be placed in
a try block.
10. (T/F) The call to the method throwing an un-checked exception must be
placed in a try block.
11. (T/F) The call to the method throwing an un-checked exception may be
placed in a try block.
12. Explain that why the return value from the method alwaysReturnFalse
(shown below) would always be false no matter what boolean value is passed
to the method. (Note: This code will compile with a warning).
public static boolean alwaysReturnsFalse (boolean flag)
{
while(flag)
{
try
{
return true;
}
finally
{
break;
}
}
return false;
}

Java Exception Handling Page 47 of 49


Appendix
Appendix A12.1
Class Inheritance hierarchy
NumberFormatException java.lang.Object
java.lang.Throwable
java.lang.Exception
java.lang.RuntimeException

java.lang.IllegalArgumentException

java.lang.NumberFormatException

ArrayIndexOutOfBoundsException java.lang.Object
java.lang.Throwable
java.lang.Exception
java.lang.RuntimeException

java.lang.IndexOutOfBoundsException

java.lang.ArrayIndexOutOfBoundsException

NullPointerException java.lang.Object
java.lang.Throwable
java.lang.Exception
java.lang.RuntimeException

java.lang.NullPointerException

Java Exception Handling Page 48 of 49


NoSuchElementException java.lang.Object
java.lang.Throwable
java.lang.Exception
java.lang.RuntimeException

java.util.NoSuchElementException

ClassCastException java.lang.Object
java.lang.Throwable
java.lang.Exception
java.lang.RuntimeException
java.lang.ClassCastException
FileNotFoundException java.lang.Object
java.lang.Throwable
java.lang.Exception
java.io.IOException

java.io.FileNotFoundException

Table A12.1.1

Java Exception Handling Page 49 of 49


Java Object Serialization
• What is serialization?
• Wh is seriali
Why serialization
ation important?
• How is it done?
• S
Some examplesl off java
j Serialization
S i li ti
What is Serialization?
• So far you have been used to writing the details of
java objects into text files,
files by breaking up the
object details into ASCII format.
• Then to read such objects back,
back you would need
to “re-build” object from the ASCII text files by
reading them as bytes of characters.
• Serialization allows one to write Java objects to
files directly as a byte stream and also read them
from such files directly.
What is Serialization?
• Serialized objects can also be transmitted over the
network to other computers and then this other
computer will receive and use the object sent over
a network as if it was its own local object.
j
• The above is done in the Java technology called
Remote Method invocation or RMI, where
objects from one machine can be passed as
arguments to a method being invoked on another
machine.
hi
What is Serialization?
• Process of writing an object to a file as an object
is called “serialization”
serialization .
• Process of reading an object from a file and
adding it in a program memory or object pool is
called de-serialization.
• Se
Serialization
o w writes
es a live
ve objec
object into
o a file.
e.
• De-serialization reads a object from a file and
makes it alive in the program.
p g
Serialization allows Lightweight
Object Persistence!
• Object persistence means that Object‘s lifetime is
not dependent on whether a program is in
execution process or not. The object persists in
between the invocations of a program.
p g
• The above is always true of objects living in a
database, where the database as a server is ready
to serve the object at any time.
• By writing a java object to a file in the “object
form” ( as opposed to text form) and be able to
read it back, one creates the affect of persistence.
How do we make an Object
Serializable?
• Java has an interface called “Serializable”
• Serializable
Seriali able interface has no methods or static
constants in it.
• Serializable interface thus acts like a flag for the
objects that need to be serialized.
• The objects to be serialized must implement the
interface “Serializable”.
Java Serializable Interface
Serializable Interface
Simple Serialization Syntax
import java.io.*;

public class MyClass implements serializable


{
//class code here
}
What is the next Step?
• Objects become serializable by implementing the
interface “Serializable”
Serializable .
• In order to perform the process of serialization/de-
serialization i.
serialization, i e.
e to write them as objects to a file
and read them back, help is needed from few other
java classes.
• These classes are:
j p
• ObjectOutputStream
• ObjectInputStream
• Other Sub
Sub-classes
classes of OutputStream Class
For example to write an Object to
a File? ( step 1)
• We create a FileOutputStream object as follows:
FileO tp tStream File_Handle
FileOutputStream File Handle
= new FileOutputStream(“myoutput.dat”);
• The
Th object
bj t we plan
l tot write
it will
ill be
b written
itt to
t the
th
file myoutput.dat on the default drive.
• Then
Th we pass theth object
bj t File_Handle
Fil H dl as an
argument to the an OutputStream object as follows:
ObjectOutputStream Out =
new ObjectOutputStream (File_Handle );
For example to write an Object to
a File? ( step 2)
• The ObjectOutputStream class has a method called:
writeObject which takes the serializable object to
writeObject,
be written to a file as an argument.
• Therefore we simply write statements such as
Out.writeObject(“String Object”);
Out writeObject(new Integer(5));
Out.writeObject(new
Out.writeObject(new Double(5.5));
• The above syntax allows the objects “String
String
Object”, object form of integer 5 and double 5.5 to
be written to the file myoutput.dat
For example to write an Object to
a File? ( step 3)
The reason strings, Integer and Double can be written
as objects to a file are because they all implement
the serializable interface!
Object De-serialization
• The serialized objects written to a file can be made
alive in a program memory by the process of de-
serialization.
• The steps in de
de-serialization
serialization are similar to the one
one’ss
that were used for serialization.
• We ddiscuss
scuss thee steps
s eps in thee de-serialization
de se o pprocess.
ocess.
• De-serialization needs help from the following java
classes:
• Class FileInputStream
• Class ObjectInputStream
• Sub classes of ObjectInputStream
Object De-serialization
•Step –1 Prepare to read the file containing
serialized objects.
j
• Bind the data input file with an object of class
FileInputStream,
p as follows:
• FileInputStream In_Handle = new
FileInputStream(“myInput.dat”);
• The data file used for input is myInput.dat at the
default location (or in same folder in which java file
is). Otherwise the full path is needed.
• In_Handle object is now needs to be bonded with an
object
bj off type ObjectInputStream.
bj
Object De-serialization
•Step –2 Bind the object of type FileInputStream
with an object
j of type
yp ObjectInputStream.
j p
• ObjectInputStream Input = new
ObjectInputStream(In Handle);
ObjectInputStream(In_Handle);
• The object Input can now read the objects from the
input
p file “myInput.dat”.
y p
• Reading is done by a method of class
ObjectInputStream.
j p
• The method is readObject ( ).
• Stepp 3 shows the syntax.
y
Object De-serialization
•Step –3 Read the file by using the method
readObject
j ()
• Object obj1 = Input.readObject( );
• Note that method readObject ( ) returns an object.
You may have to convert it to the specific type by
casting it properly. For example if first object in the
file is of type user defined class MyClass, then one
can read the object from the file as follows:
MyClass Inst_My_Class1 =
(MyClass) Input.readObject( );
• Examples are shown in file MyClass.java.
CS 3: Java
Chapter 15: Graphical User Interface
Author: Satish Singhal Ph. D.
Version 1.0
We introduced the basic concept of asynchronous programming and graphical user
interface (GUI) in chapter ten. We showed that:
a. Widgets or components such as Label can be painted on a Canvass, such as
Frame or JFrame.
b. The widgets and containers (for example Frame) may be given additional
intelligence by registering them with appropriate listeners.
c. Listeners stay on stand by to listen to the messages from operating system
and they execute methods called event handlers when operating system fires
the window events when user either presses a relevant key on the keyboard
or uses the mouse or other tracking devices.

We can broadly divide the GUI components into the following categories:
1. Widgets or components: These are the GUI units such as buttons,
labels, textboxes, scroll lists, menu items etc. The widgets are atomic
in the nature that they cannot contain other widgets1. All widgets
derive from Java class java.awt.Component.
2. Containers: These are the GUI units, which contain either the widgets
or other containers. For example a Frame or JFrame is a container.
All usable containers derive from Java class java.awt.Container.
Because the class Container derives from class Component, we may in
one sense also consider every container as a component as well.

We mentioned in chapter ten that Java provided two graphics package – AWT
(abstract windowing toolkit) in Java 1.1, and swing package in Java 1.2. The AWT
package was quite limited because it used the peer widgets/containers from an
operating system in order to create a Java widget/container. The AWT component
as a result had different look and feel based on the platform running the Java
program. Swing package introduced vast variety of so called lightweight
components, which did not depend upon the operating system and had same look
and feel irrespective of the operating system running a Java program. In chapter
ten we showed one example of creating a simple Swing window, which had the
intelligence to close by clicking on the close (X) button. In this chapter, first we show
some simple yet interesting swing applications, and then discuss layouts in detail.
One brief point about layouts, however, is in order here.

1
Widgets such as buttons, however, can contain pictures and images.

Graphical User Interface (Singhal) Page 1 of 41


Unlike Visual Basic, which allows one to place Widgets and containers inside a
container in any manner, Java does not allow one to place GUI components at will.
One must choose a layout, which specifies as to how the GUI components will be
placed inside a container. The simplest layout is called flow layout given by class
java.awt.FlowLayout. A layout dictated by the class FlowLayout places widgets and
containers inside a container left to right, in order they are added, much the same
way the words are added to a line and lines to the paragraph. More sophisticated
layouts are available, which we shall discuss, soon after we finish the discussion of
basics of Swing components. We have discussed a general procedure of adding
widgets to the containers in chapter ten. In this chapter we amplify the same
procedure using various examples. We summarize this general procedure as
follows:
1. Declare and instantiate the component or container to be shown in GUI.
2. Declare nested class or classes either implementing listeners or extending
adapters, needed to impart intelligence to GUI units. The event-handler
methods in nested classes are coded as per program needs.
3. Set the layout for the main window, which would contain GUI units.
4. Register the active GUI units with the appropriate listeners.
5. Add the GUI units to the main window as per the layout chosen in step three.
6. Make the main window visible.
We show a simple example of adding some buttons showing in a window to illustrate
these steps (Listing 15.1). However, one must understand that in the spirit of
modularization (which vastly simplifies debugging), one may wish to write classes
customizing various GUI components that would eventually become part of main
GUI. In Listing 15.1, we plan to show two types of Java buttons. One button is a
plain button, where as the other is a bit fancy in the sense that it contains a picture
on it. Also when user rolls the mouse or other tracking device over the fancy button,
the picture changes to another one. When pressed, both buttons pop up a message
box.

Swing Button Application Example


In an actual enterprise Java application, one would need to customize all Swing
widgets to the forms that may fit the need and image of the enterprise. In that sense,
if we wish to create a fancy button, we may wish to customize Swing JButton class to
our specifications. The simplest method of doing that is to design our own button
class by extending the class javax.swing.JButton. Figure 15.1 shows the inheritance
hierarchy of JButton class.
java.lang.Object
java.awt.Component
java.awt.Container
javax.swing.JComponent
javax.swing.AbstractButton
javax.swing.JButton
FIG. 15.1
In chapter ten we saw that the class JFrame derived from class Frame. We do not
see such symmetry here as the class JButton does not derive from class Button. You

Graphical User Interface (Singhal) Page 2 of 41


would see this variation often as some Swing components derive from similar
sounding AWT components directly, while others do not. In order to create our
fancy button, we write our class MyButton, which derives from the class JButton
(Listing 15.1A).
00001 import javax.swing.*;

00007 public class MyButton extends JButton


00008 {
00009 private static Icon Pic1 = new ImageIcon ("Krishna.jpg");
00010 private static Icon Pic2 = new ImageIcon ("RadhaKrishna.jpg");
00013
00014 public MyButton( )
00015 {
00016 super ("Fancy Button", Pic1);
00017 this.setRolloverIcon (Pic2);
00018 }
00019 }
Listing 15.1A
At the start we need some image on our fancy button. The class MyButton derives
from class javax.swing.JButton, therefore we need to import the package
javax.swing (L15.1A#1). Class JButton has a constructor (Figure 15.2) that can take
a String and an object of type javax.swing.Icon as arguments.
public JButton(String text, Icon icon)
Creates a button with initial text and an icon.
Parameters:
text - the text of the button
icon - the Icon image to display on the button
FIG. 15.2
Interface Icon is implemented by the class javax.swing.ImageIcon, and the
constructor for the class ImageIcon can take a filename String of a jpg or gif type
image as its argument (Figure 15.3).
public ImageIcon(String filename)
Creates an ImageIcon from the specified file. The image will be preloaded by
using MediaTracker to monitor the loading state of the image. The specified
String can be a file name or a file path. When specifying a path, use the
Internet-standard forward-slash ("/") as a separator. (The string is
converted to an URL, so the forward-slash works on all systems.) For
example, specify:
new ImageIcon("images/myImage.gif")
The description is initialized to the filename string.
Parameters:
filename - a String specifying a filename or path
FIG. 15.3

Graphical User Interface (Singhal) Page 3 of 41


Therefore we create two Icon type static objects Pic1 and Pic2, which track to
filenames Krishna.jpg, and RadhaKrishna.jpg (L15.1A#9-10). Our purpose in
creating these objects is that when user sees an object of type MyButton, it would
have the picture Krishna.jpg on it, and when they roll the mouse over it, the image
would change to the picture RadhaKrishna.jpg. Both files, Krishna.jpg and
RadhaKrishna.jpg would need to be in the same folder in which the class MyButton
is. If located in a different folder then the filename path specification discussed in
Figure 15.3 must be followed.

Our derived class MyButton is simple in design in the sense that except two static
Icon type data members, it only has a constructor in it. The constructor (L15.1A#14-
18) first calls the super class constructor (Figure 15.2), and then calls the method
setRolloverIcon (Figure 15.4), which is inherited from the super class
javax.swing.AbstractButton.
public void setRolloverIcon(Icon rolloverIcon)
Sets the rollover icon for the button.
Parameters:
rolloverIcon - the icon used as the "rollover" image
FIG. 15.4
The code on lines (L15.1A#16 - 17) ascertains that when an object of type MyButton
is created, then the button shows up with String “Fancy Button” and the image
contained in object Pic1. Then if user rolls the tracking device or mouse on the
button, the image changes to the one contained in the object Pic2.
Question15.1: Explain that why would you get a compile error if the line #9 in
Listing 15.1A is changed to the one given below?
private Icon Pic1 = new ImageIcon ("Krishna.jpg");

Question 15.2: Rewrite the constructor for class MyButton in a manner that user of
this class can pass the following three objects as constructor arguments and still
achieve the same results as Listing 15.1 would achieve. The three objects are: a
String with the button title, and two Icon type objects containing the original image
and the roll over image.

Customizing the JFrame


The enterprise for which the Java application is designed, may also wish to
customize the look and feel of the windows in their applications. This customization
may include choosing the height and width of window, its title and its color. Listing
15.1B shows our customized class MyWindow that extends the class JFrame.

Graphical User Interface (Singhal) Page 4 of 41


00001 import javax.swing.*;
00002 import java.awt.*;
00006 public class MyWindow extends JFrame
00007 {
00011 private static final int width1 = 800;
00015 private static final int height1 = 800;
00019 private Color Def_Color = Color.cyan;
00023 private static String Def_Title = "Enterprise Window";
00027 private int def_width = width1;
00031 private int def_height = height1;
00035 public MyWindow()
00036 {
00037 super(Def_Title);
00038 Container Cont = getContentPane();
00039 Cont.setBackground(Def_Color);
00040 setSize(def_width, def_height);
00041 }
00045 public MyWindow(String Title, int width, int height, Color Cl)
00046 {
00047 super(Title);
00048
00049 if(Cl == null)
00050 throw new NullPointerException("Null Color value passed"+
00051 " to the constructor: MyWindow CTOR");
00052 Container Cont = getContentPane();
00053 Cont.setBackground(Cl);
00054
00055 if(width<=0 || height<=0)
00056 throw new IllegalArgumentException ("Illegal value of window width" +
00057 " or height is passed: MyWindow CTOR");
00058 setSize(width, height);
00059 }
00060 }
Listing 15.1B
The class MyWindow has default and explicit constructors. The class defines the
values of default window properties, which would be created if the argument-less
constructor were called. The class data members used by the argument-less
constructor are: Def_Title, Def_Color, def_width, and def_height. The explicit
constructor, when called by the client of class MyWindow allows the client to
customize all window properties. Thus the explicit constrictor takes the window
title, width, height, and its color as arguments.

When client provides the parameters to a method or constructor, it is necessary to


inform the client about the errant values passed. Therefore runtime exceptions are

Graphical User Interface (Singhal) Page 5 of 41


thrown in the explicit constructor in order to inform the client of errant parameters
that were supplied. Object of RuntimeException class, the NullPointerException or
IllegalArgumentException is thrown if either the Color value Cl is null or the values
of width or height provided is zero or negative (L15.1B#49-51 & L15.1B#55-57).
Special checked exception classes may be designed and used if program must
recover from the errant values supplied to the constructor2.

Question 15.3: Design two exception classes derived from java.lang.Exception,


which are named IllegalColorException and IllegalWindowSizeException. The
object of IllegalColorException could be thrown if a null value of Color object is
passed to a constructor or method argument. An object of
IllegalWindowSizeException would be thrown if a zero or negative value of window
size is passed. (See chapter 12 or relevant exception handling chapter in your
textbook or Java reference book).

Question 15.4: Rewrite the explicit constructor for class MyWindow using the
exception classes written in question 15.3.

Question 15.5: Rewrite the client code in Listing 15.1C when client uses the explicit
constructor written in question 15.4 (and MyWindow class including this
constructor).

In order to set the title, the explicit constructor calls the super class constructor. In
Swing windows, which are of type JFrame, the title and menu-bar of the window are
separate from the lower portion into which the content can be written. Therefore
calling the method getContetPane returns the Container type object (Cont) for this
window (L15.1B#38 & 52). The returned object Cont is used for properties such as
changing the background (L15.1B#39 & 53). Finally the size of this window is set to
the width and height passed to the constructor (L15.1B#40 & 58).

Using the Customized MyButton and MyWindow classes


Having customized the JButton and JFrame type of objects as MyButton and
MyWindow, we can create a window of type MyWindow containing MyButton and
other simple Swing components. This is done in the last portion of Listing 15.1 in the
class ButtonsInMyWindow (Listing 15.1C).
00001 import java.awt.event.*;
00002 import java.awt.*; 1. Declaration
00003 import javax.swing.*;
00007 public class ButtonsInMyWindow
00008 {
00012 private MyButton Button1;
00016 private JButton Button2;
00020 private static Color Window_Background = Color.cyan;

2
Recall that program can recover from checked exceptions but generally not from Runtime or
unchecked exceptions.

Graphical User Interface (Singhal) Page 6 of 41


private static String Title = "My Window with Plain button and Fancy Button";
00028 private static int height = 800;
00032 private static int width = 800;
00036 private MyWindow Win;
00040 private class CloseWindow extends WindowAdapter
00041 {
00045 public void windowClosing(WindowEvent Evt)
00046 {
00047 Win.dispose();
00048 System.exit(0);
00049 }
00050 }
00054 private static class ButtonHandler implements ActionListener
00055 {
00059 public void actionPerformed( ActionEvent e )
00060 {
00061 JOptionPane.showMessageDialog( null,
00062 "You pressed: " + e.getActionCommand());
00063 }
00064 }
00065

2. Instantiation
00069 public ButtonsInMyWindow()
00070 {
00071 Button1 = new MyButton();
00072 Button2 = new JButton("Plain Button");
00073 Win = new MyWindow(Title,width,height, Window_Background);
00074 //Win = new MyWindow();
00075 //Win = new MyWindow(null, 800,800, Color.green);
00076 //Win = new MyWindow("Test Window", -800,800, Color.green);
00077 //Win = new MyWindow("Test Window", 800,-800, Color.green);
00078 //Win = new MyWindow("Test Window", 800,800, null);
00079 Win.addWindowListener(new CloseWindow());
00080 Font FText1 = new Font("SansSerif",Font.BOLD|Font.ITALIC,60);
00081 Button1.setFont(FText1);
00082 Button2.setFont(FText1);
00083 Button1.setForeground(Color.red);
00084 Button2.setForeground(Color.blue);
00085 Button1.setBackground(Color.blue);
00086 Button2.setBackground(Color.yellow);
00087 Container Cont = Win.getContentPane();
00088 Cont.setLayout(new FlowLayout());
89 ButtonHandler Handler = new ButtonHandler();
90 3. Registration
00090 Button1.addActionListener(Handler);

Graphical User Interface (Singhal) Page 7 of 41


91 Button2.addActionListener(Handler);
4. Adding to the
container part of window
00092 Cont.add(Button2);
92 Cont.add(Button1);
93
00094 Win.show();
00095 }
00099 public static void main(String[] args)
00100 {
00101 ButtonsInMyWindow Temp = new ButtonsInMyWindow();
00102 }
00103 }
Listing 15.1C
The purpose of Listing 15.1C is to show a window of type MyWindow containing a
plain JButton type object and a customized MyButton type of object in a simple
flow layout form. The Table 15.1 gives the summary and purposes of various data
members, nested classes, and the constructor used in class ButtonsInMyWindow.

Field Summary for class ButtonsInMyWindow


private MyButton Button1
The button of type MyButton, which has customized
picture on it.
private Button2
javax.swing.JButton Simple JButton to show on MyWindow.

private static int height


The height in pixel chosen for the MyWindow object.
private Title
static java.lang.String The title chosen for the MyWindow object.

private static int width


The width in pixel chosen for the MyWindow object.
private MyWindow Win
The MyWindow object which will have user defined
color, height, width, and title.
private Window_Background
static java.awt.Color The Color chosen for the MyWindow object.

Constructor Summary for class ButtonsInMyWindow


ButtonsInMyWindow()
Default constructor for class ButtonsInMyWindow. Constructor instantiates an
object of type MyWindow and adds to it the buttons of type JButton and

Graphical User Interface (Singhal) Page 8 of 41


MyButton, as well as provides the "intelligence" to these buttons.

Nested Class Summary for class ButtonsInMyWindow


private ButtonsInMyWindow.ButtonHandler
static class
The nested class implementing the interface ActionListener. The
event handler actionPerformed is activated when the user presses on the
JButton type object, which has been registered with the class
ButtonHandler.
private ButtonsInMyWindow.CloseWindow
class
Nested class extending the WindowAdapter class, to dispose the
resources used by MyWindow type object. The event handler
windowClosing is activated when user either pressed the mouse to close
the window or presses alt + F4 on the keyboard.
Table 15.1

Data members
Button1 and Button2 respectively are objects of type MyButton and JButton
(Listing 15.1C#12 & 16). Four static variables Window_Background, Title, height,
and width define the Color, String for window title, height and width in pixel for the
window that user wishes to create (Listing 15.1C#20, 24, 28, &32). Finally a
reference Win of type MyWindow is declared (Listing 15.1C#36).

Nested Classes
Since we need to provide intelligence to the button objects, we define a nested class
ButtonHandler (Listing 15.1C#54-64) that implements the interface
java.awt.event.ActionListener. This interface only has one method public void
actionPerformed (ActionEvent e), which is invoked when a registered button is
pressed. It is important to understand the code inside the event handler
actionPerformed (Listing 15.1C#59-63). When the button registered with action
listener ButtonHandler is pressed, a JOptionPane message dialog is popped on user
screen that displays the String “You Pressed” and the title of the button. The code
portion: e.getActionCommand executes the corresponding method whose
description is given in Figure 15.5.
public String getActionCommand()
Returns the command string associated with this action. This string allows a
"modal" component to specify one of several commands, depending on its state. For
example, a single button might toggle between "show details" and "hide details".
The source object and the event would be the same in each case, but the command

Graphical User Interface (Singhal) Page 9 of 41


string would identify the intended action.
Returns:
the string identifying the command for this event
FIG. 15.5

The nested class CloseWindow (Listing 15.1C# 40-50) extends the class
java.awt.event.WindowAdapter and overrides the method windowClosing whose
details are given in Figure 15.6.

public void windowClosing(WindowEvent e)


Invoked when the user attempts to close the window from the window's
system menu. If the program does not explicitly hide or dispose the window
while processing this event, the window close operation will be cancelled.
FIG. 15.6
Inside the method windowClosing we call the method dispose (Figure 15.7). Method
dispose releases all the native resources used by the JFrame object Win (Listing
15.1C# 47).
public void dispose()
Releases all of the native screen resources used by this Window, its
subcomponents, and all of its owned children. That is, the resources for these
Components will be destroyed, any memory they consume will be returned to
the OS, and they will be marked as undisplayable.
The Window and its subcomponents can be made displayable again by
rebuilding the native resources with a subsequent call to pack or show. The
states of the recreated Window and its subcomponents will be identical to
the states of these objects at the point where the Window was disposed
(not accounting for additional modifications between those actions).
Note: When the last displayable window within the Java virtual machine
(VM) is disposed of, the VM may terminate. See AWT Threading Issues
for more information.
FIG. 15.7
Finally the call to method exit of System class releases any other program resources
and ends the program (Listing 15.1C# 48).

Constructor
In Class ButtonsInMyWindow (Listing 15.1C# 69-95), the constructor does almost
all the work. First the constructor instantiates the Button1 by calling the default
constructor for the MyButton class (Listing 15.1C#71). Then the Button2 that is of
type JButton is instantiated (Listing 15.1C#72). The explicit constructor for the
MyWindow class is called to instantiate a JFrame type object (Listing 15.1C#73).
The parameters passed to the constructor in line 73 customize the window to be

Graphical User Interface (Singhal) Page 10 of 41


created to the user-defined specifications. The commented lines 74 to 78 are the code
lines to test the proper functioning of exception handlers in the explicit constructor
for the class MyWindow. The method addWindowListener called by the object Win
takes an object of type CloseWindow and registers the object Win with the event
handler windowClosing. The Figure 15.8 gives the details of method
addWindowListener.

public void addWindowListener(WindowListener lstn)


Adds the specified window listener to receive window events from this
window. If lstn is null, no exception is thrown and no action is performed.
Parameters:
lstn - the window listener
See Also:
removeWindowListener (java.awt.event.WindowListener), getWindowListeners()
FIG. 15.8

Customizing Fonts, foreground and background colors


Java graphical objects that can use strings can have the fonts for the strings
customized to user specifications. The objects of class java.awt.Font are used for this
purpose. Figure 15.9 gives the details of the constructor of Font class called to
customize the Font object FText1 created on line 80.
public Font(String name, int style, int size)
Creates a new Font from the specified name, style and point size.
Parameters:
name - the font name. This can be a logical font name or a font face name. A
logical name must be either: Dialog, DialogInput, Monospaced, Serif, or
SansSerif. If name is null, the name of the new Font is set to the name
"Default".
style - the style constant for the Font The style argument is an integer bitmask
that may be PLAIN, or a bitwise union of BOLD and/or ITALIC (for
example, ITALIC or BOLD|ITALIC). If the style argument does not
conform to one of the expected integer bitmasks then the style is set to
PLAIN.
size - the point size of the Font
Since:
JDK1.0
See Also:
GraphicsEnvironment.getAllFonts(),
GraphicsEnvironment.getAvailableFontFamilyNames()

Graphical User Interface (Singhal) Page 11 of 41


FIG. 15.9
The method setFont (inherited from class Container) called on a widget or
Container sets the fonts for the text to be displayed on objects Button1 and Button2
(Listing 15.1C# 81-82). Similarly the method setForeground inherited from class
Component sets the color of the fonts displayed on Button1 and Button2 (Listing
15.1C# 83-84). Java provides a default grey background color to widgets and
containers. One may however, change the background color by calling the method
setBackground, also inherited from class Component. This is done for Button1 and
Button2, setting a blue background for the former and yellow for the latter (Listing
15.1C# 85-86).

Overall Intelligent Widget Creation


Four bubbles in Listing 15.1C show the overall process of creating intelligent
widgets. The intelligent widgets need to be Declared (bubble #1), Instantiated
(bubble #2), Registered with the event handlers (bubble #3), and Added to a
Container (bubble #4). We can abbreviate the whole process by word DIRA, where
D stands for declare, I for instantiation, R for registration and A for addition to the
container. DIRA must be done for each intelligent widget in a GUI. Understand that
some widgets, such as JLabel may not need all parts of DIRA. Code lines 12, 16, 71-
72, 90-91, and 92-93 do the DIRA process for Button1 and Button2. The layout for
object Win is set to FlowLayout (Listing 15.1C# 88) and finally the JFrame Win is
displayed by calling the method show (Listing 15.1C#94).

Execution of Listing 15.1


When the main method of class ButtonsInMyWindow is executed it instantiates an
object of this class. The result is a GUI shown in Figure 15.10A.

Graphical User Interface (Singhal) Page 12 of 41


FIG. 15.10A
The GUI shows two buttons in a window that has cyan background with the title
and size same as the parameters passed to the constructor on line (Listing
15.1C#73). The first button is a plain button that is an object of class JButton. The
second button, placed in a flow layout is a fancy button that has a picture of Krishna
dancing on a snake (Krishna.jpg). When mouse or other tracking device is rolled
over the fancy button the image on it changes to the one shown in Figure 15.10B.

Graphical User Interface (Singhal) Page 13 of 41


FIG. 15.10B
The default image Krishna.jpg is replaced by the image RadhaKrishna.jpg. Pressing
the “Plain Button” and “Fancy Button” displays the dialog boxes shown in the
Figures 15.10C & D respectively.

FIG. 15.10C

FIG. 15.10D

Graphical User Interface (Singhal) Page 14 of 41


Question 15.6. The code given below accomplishes the same output, as the code
given in Listing 15.1. Describe as to why for enterprise applications the software
design of code given below is inferior?
////////////////////////////
00003 import java.awt.*;
00004 import java.awt.event.*;
00005 import javax.swing.*;
00006
00007 public class ButtonsInMyWindow extends JFrame {
00008 private JButton Button1, Button2;
00009
00010 public ButtonsInMyWindow()
00011 {
00012 super( "My Window with Plain button and Fancy Button" );
00013
00014 Container Cont= getContentPane();
00015 Cont.setLayout( new FlowLayout() );
00016
00017 // create buttons
00018 Button1 = new JButton( "Plain Button" );
00019 Icon Pic1 = new ImageIcon( "Krishna.jpg" );
00020 Icon Pic2 = new ImageIcon( "RadhaKrishna.jpg" );
00021 Button2 = new JButton( "Fancy Button", Pic1 );
00022 Button2.setRolloverIcon( Pic2 );
00023 Font FText1 = new Font("SansSerif",Font.BOLD|Font.ITALIC,60);
00024 Button1.setFont(FText1);
00025 Button2.setFont(FText1);
00026 Button2.setForeground(Color.red);
00027 Button1.setForeground(Color.blue);
00028 Button2.setBackground(Color.blue);
00029 Button1.setBackground(Color.yellow);
00030 Cont.add( Button1 );
00031 Cont.add( Button2 );
00032
00033 // create an instance of inner class ButtonHandler
00034 // to use for button event handling
00035 ButtonHandler Handle = new ButtonHandler();
00036 Button2.addActionListener( Handle );
00037 Button1.addActionListener( Handle );
00038
00039 Cont.setBackground(Color.cyan);
00040 setSize(800, 800);
00041 show();
00042 }
00043

Graphical User Interface (Singhal) Page 15 of 41


00044 public static void main( String args[] )
00045 {
00046 ButtonsInMyWindow Win = new ButtonsInMyWindow();
00047
00048 Win.addWindowListener (
00049 new WindowAdapter() {
00050 public void windowClosing( WindowEvent e )
00051 {
00052 System.exit( 0 );
00053 }
00054 }
00055 );
00056 }
00057
00058 // inner class for button event handling
00059 private class ButtonHandler implements ActionListener {
00060 public void actionPerformed( ActionEvent e )
00061 {
00062 JOptionPane.showMessageDialog( null,
00063 "You pressed: " + e.getActionCommand() );
00064 }
00065 }
00066 }
Listing 15.2

Layout Managers
We briefly talked about one Java layout manager called FlowLayout. Layout
managers define the pattern in which either the widgets or containers can be placed
on a Java Container. Figure 15.11 shows a general classification of layout managers
available in java.awt package.

Graphical User Interface (Singhal) Page 16 of 41


FIG. 15.11
Notice that all the boxes on the lowest level of above chart are classes in java.awt
package. Of these the four, FlowLayout, BorderLayout, GridLayout, and
GridBagLayout – all can be used either for placing widgets or containers into
containers. On the other hand the CardLayout is usable only for placing containers
inside containers. Swing package adds four more layout managers, which are briefly
described in Table 15.2.

Swing Layout managers Description


BoxLayout A layout manager that aligns components along the X- or
Y- axis of a panel. It attempts to use the preferred width
and height of components during the layout process.

OverlayLayout Arranges components one on top of another, aligning the


base point of each component in a single location.

Graphical User Interface (Singhal) Page 17 of 41


ScrollPaneLayout A layout manager specific to scrolling panes.

ViewportLayout A layout manager specific to view ports within scrolling


panes.

Uses the concept of springs and struts to place widgets


and containers. This layout is best used when one is using
SpringLayout an IDE, such as NetBeans, where IDE will fill the
guarded code using the SpringLayout. For hand coding
the use of GridBagLayout is preferred.
Table 15.2

Some AWT Layout Managers


First we discuss simpler AWT layout managers, so that we can proceed with more
interesting examples of Java graphics applications. We first revisit the FlowLayout.

FlowLayout
As discussed earlier, in flow layout we add the widgets and containers to the
container being painted much the same way in which words are added to a line and
lines to a page in a word processor, i. e. starting from left to right and top to bottom.
Table 15.3 shows the summary of fields, constructor and methods for the class
called MyFlowlayout that gives a demonstration of the typical example of the use of
FlowLayout manager.

Field Summary For Class MyFlowlayout Properties of


private Buttons MyWindow
Array of JButtons object Win
javax.swing.JButton[]

private static int FIVE


Constant controlling the number of buttons shown.
private static int height
The height in pixel chosen for the MyWindow object Win.
private Title
static java.lang.String The title chosen for the MyWindow object. Win.
MyWindow
(Listing private static int width
15.1) The width in pixel chosen for the MyWindow object Win.
private MyWindow Win
The MyWindow object which will have user defined color,
height, width, and title.
private Window_Background
The Color chosen for the MyWindow object Win.

Graphical User Interface (Singhal) Page 18 of 41


static java.awt.Color

Constructor Summary For Class MyFlowlayout


MyFlowlayout()
Default constructor for class MyFlowlayout. Constructor instantiates an
object of type MyWindow and adds to it the buttons of type JButton as well as
provides the "intelligence" to these buttons.

Method Summary For Class MyFlowlayout


static void main(java.lang.String[] args)
Main method - displays the object of type MyFlowlayout.
private setSwingLookAndFeel()
void Sets the look and Feel of Swing GUI.

Table 15.3
The class MyFlowlayout has seven data members, four of which (Title, height,
width, and Window_Background) are required for the object Win, which would be
the container for the array of JButtons called Buttons. The integer constant FIVE
gives the number of JButtons that would be displayed on the container Win. The
only constructor for the class MyFlowlayout instantiates the button and window
objects and gives the intelligence to JButton objects as well as adds them to the GUI
to be displayed. The method setSwingLookAndFeel sets the look and feel of the GUI
to be displayed to conform to default Swing standards. The inner class
ButtonHandler remains same as Listing 15.1.

The Listing 15.3 shows the source code for the class MyFlowlayout.
00001 import java.awt.event.*;
00002 import java.awt.*;
00003 import javax.swing.*;
00007 public class MyFlowlayout
00008 {
00012 private static final int FIVE = 5;
00016 private JButton [ ] Buttons;
00020 private static Color Window_Background = Color.cyan;
00024 private static String Title = "My Window with Plain buttons";
00028 private static int height = 800;
00032 private static int width = 800;
00036 private MyWindow Win;
00042 private static class ButtonHandler implements ActionListener
00043 {
00047 public void actionPerformed( ActionEvent e )
00048 {

Graphical User Interface (Singhal) Page 19 of 41


00049 JOptionPane.showMessageDialog( null,
00050 "You pressed: " + e.getActionCommand());
00051 }
00052 }
00053
00059 public MyFlowlayout()
00060 {
00061 Win = new MyWindow(Title,width,height, Window_Background);
00062 Win.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
00063 setSwingLookAndFeel();
00064 Font FText1 = new Font("SansSerif",Font.BOLD|Font.ITALIC,20);
00065 Container Cont = Win.getContentPane();
00066 Cont.setLayout(new FlowLayout(FlowLayout.LEFT));
00067 //Cont.setLayout(new FlowLayout(FlowLayout.RIGHT));
00068 //Cont.setLayout(new FlowLayout(FlowLayout.CENTER));
00069 //Cont.setLayout(new FlowLayout());
00070 ButtonHandler Handler = new ButtonHandler();
00071 Buttons = new JButton[FIVE];
00072
00073 for(int ind = 0; ind<Buttons.length; ++ind)
00074 {
00075 Buttons[ind] = new JButton("Button " + (ind+1));
00076 Buttons[ind].setFont(FText1);
00077 Buttons[ind].setForeground(Color.blue);
00078 Buttons[ind].setBackground(Color.yellow);
00079 Buttons[ind].addActionListener(Handler);
00080 Cont.add(Buttons[ind]);
00081 }
00082 Win.show();
00083 }
00087 private void setSwingLookAndFeel()
00088 {
00089 //Removes the previous decoration
00090 Win.setUndecorated(true);
00091 //Sets the Swing look and feel decoration
Win.getRootPane().setWindowDecorationStyle(JRootPane.FRAME);
00093 }
00097 public static void main(String[] args)
00098 {
00099 MyFlowlayout Temp = new MyFlowlayout();
00100 }
00101 }
//Listing 15.3
In this Listing we use an object of our pre-defined class MyWindow (Listing 15.1B)
as a container in which we place five JButton type objects in a flow layout pattern.

Graphical User Interface (Singhal) Page 20 of 41


The Listing defines the static and non-static class data members (L15.3#12-36) and
the inner class ButtonHandler (L15.3#42-52).

Inside the constructor (L15.3#59-83), first we call the explicit constructor for class
MyWindow to instantiate the object Win (L15.3#61). In Java 1.4 and above the
method setDefaultCloseOperation can be called on a JFrame type object to close it
with out needing to register it with a WindowListener type object. This is done for
the object Win on line 62. Figure 15.12 describes the details of the method
setDefaultCloseOperation.
public void setDefaultCloseOperation(int operation)
Sets the operation that will happen by default when the user initiates a
"close" on this frame. You must specify one of the following choices:

• DO_NOTHING_ON_CLOSE (defined in WindowConstants): Don't do


anything; require the program to handle the operation in the
windowClosing method of a registered WindowListener object.
• HIDE_ON_CLOSE (defined in WindowConstants): Automatically hide the
frame after invoking any registered WindowListener objects.
• DISPOSE_ON_CLOSE (defined in WindowConstants): Automatically hide
and dispose the frame after invoking any registered WindowListener
objects.
• EXIT_ON_CLOSE (defined in JFrame): Exit the application using the
System exit method. Use this only in applications.

The value is set to HIDE_ON_CLOSE by default.


Note: When the last displayable window within the Java virtual machine
(VM) is disposed of, the VM may terminate. See AWT Threading Issues
for more information.
Parameters:
operation - the operation which should be performed when the user closes the
frame
Throws:
IllegalArgumentException - if defaultCloseOperation value isn't one of the above
valid values
SecurityException - if EXIT_ON_CLOSE has been specified and the SecurityManager
will not allow the caller to invoke System.exit
See Also:
Window.addWindowListener(java.awt.event.WindowListener), getDefaultCloseOperation(),
WindowConstants, Runtime.exit(int)
FIG. 15.12

Graphical User Interface (Singhal) Page 21 of 41


Passing the constant EXIT_ON_CLOSE as an argument to the static method
setDefaultCloseOperation allows exiting the application using the exit method of
class System. The look and feel of Swing windows title bar is different from the
standard Window bars (Figure 15.13).

FIG. 15.13A Windows Title bar

FIG. 15.13B Swing Title bar


The method setSwingLookAndFeel first removes the windows look and feel
(L15.3#90) by calling the method setUndecorated (Figure 15.14) and passing to it a
boolean value true.
public void setUndecorated(boolean undecorated)
Disables or enables decorations for this frame. This method can only be
called while the frame is not displayable.
Parameters:
undecorated - true if no frame decorations are to be enabled; false if frame
decorations are to be enabled.
Throws:
IllegalComponentStateException - if the frame is displayable.
Fig. 15.14
Then it calls the method setWindowDecorationStyle (Figure 15.15) of class
javax.swing.JRootPane and passes to it the argument JRootPane.FRAME to set the
Swing look and feel shown in Figure 15.13B.
public void setWindowDecorationStyle(int windowDecorationStyle)
Sets the type of Window decorations (such as borders, widgets for closing a
Window, title ...) the JRootPane should provide. The default is to provide no
Window decorations (NONE).
This is only a hint, and some look and feels may not support this. This is a
bound property.
Parameters:
windowDecorationStyle - Constant identifying Window decorations to provide.
Throws:
IllegalArgumentException - if style is not one of: NONE, FRAME, PLAIN_DIALOG,
INFORMATION_DIALOG, ERROR_DIALOG, COLOR_CHOOSER_DIALOG,
FILE_CHOOSER_DIALOG, QUESTION_DIALOG, or WARNING_DIALOG.
Since:
1.4
See Also:
JDialog.setDefaultLookAndFeelDecorated(boolean),
JFrame.setDefaultLookAndFeelDecorated(boolean),

Graphical User Interface (Singhal) Page 22 of 41


LookAndFeel.getSupportsWindowDecorations()
FIG. 15.15
First the layout for the window Win is set to left alignment by passing the constant
FlowLayout.LEFT as an argument to the constructor that creates an object of
FlowLayout type which in turn is passed to the method setLayout (L15.3#66). The
affect of commenting in the other options available for FlowLayout (L15.3#67-69)
will be illustrated soon. The loop (L15.3#73-81) accomplishes the instantiation;
registration and addition to the window of five JButton objects stored in array
Buttons. Finally the window Win is displayed (L15.3#82).

Results of Listing 15.3


Figure 15.16A shows five buttons arranged in flow layout when first button is left
aligned and swing look and feel is used.

FIG. 15.16A
A border drawn in Button 1 indicates that as a default, in flow layout, the left-most
component is in focus. The focused button may be activated either by pressing it by
a mouse or by pressing the space-bar key on the keyboard. Figures 15.16B, and C
show the layout when layout is right aligned or center aligned. This requires
commenting in the code line 67 and 68 respectively.

FIG. 15.16B

FIG. 15.16C
When line 69, using the layout where the constructor of FlowLayout class takes no
argument is commented in, the result is similar to the Figure 15.16C, indicating that
argument-less constructor defaults to center alignment of components.

Graphical User Interface (Singhal) Page 23 of 41


When one uses the Swing Look and Feel (Figure 15.16) the resulting window is
packed with the components in the sense that reducing height and width of window
does not re-align the components in it. For example if one tries to drag the edges of
window in Figure 15.16, the minimum width would be the width to show all five
buttons and minimum height could only be reduced to the height of one button.
Such is not the case when Window Look and Feel is used. For example if we
comment out the call to method setSwingLookAndFeel on line #63 and use the left
alignment of components, the resulting window is shown by Figure 15.17A.

FIG. 15.17A
As displayed, this window is not too different from the Figure 15.16A. However if
one drags the right edge of this window with a mouse and reduces the width then
buttons rearrange themselves, first in the pattern shown by Figure 15.17B and
finally all aligned in one vertical column (Figure 15.17C).

FIG. 15.17B

Graphical User Interface (Singhal) Page 24 of 41


FIG. 15.17C
Therefore it is imperative that to maintain the look and feel integrity of a flow
layout alignment, one must use the swing look and feel. Henceforth we would always
use swing look and feel, thus eliminating the complication of components
rearrangement due to reduction in window size.

Border Layout
In border layout the components are placed east, west, north, south along the four
edges and at the center of the GUI display. Figure 15.18 shows the schematic picture
of border layout.

FIG. 15.18
Listing 15.4 shows an example of using border layout.
00001 import java.awt.event.*;
00002 import java.awt.*;
00003 import javax.swing.*;
00007 public class MyBorderlayout
00008 {
00012 private static final int FIVE = 5;
00016 private JButton [ ] Buttons;
00020 private static Color Window_Background = Color.cyan;
00024 private static String Title = "My Window with Plain buttons";
00028 private static int height = 800;
00032 private static int width = 800;
00036 private MyWindow Win;
00042 private static class ButtonHandler implements ActionListener
00043 {
00047 public void actionPerformed( ActionEvent e )
00048 {
00049 JOptionPane.showMessageDialog( null,
00050 "You pressed: " + e.getActionCommand());

Graphical User Interface (Singhal) Page 25 of 41


00051 }
00052 }
00053
00059 public MyBorderlayout()
00060 {
00061
00062 Win = new MyWindow(Title,width,height, Window_Background);
00063 Win.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
00064 setSwingLookAndFeel();
00065 String [] arr = {BorderLayout.NORTH,BorderLayout.CENTER,
00066 BorderLayout.EAST,BorderLayout.WEST,
00067 BorderLayout.SOUTH,};
00068 Font FText1 = new Font("SansSerif",Font.BOLD|Font.ITALIC,30);
00069 Container Cont = Win.getContentPane();
00070 //Commenting out the line below will still work
00071 //because the BorderLayout is the default layout chosen.
00072 Cont.setLayout (new BorderLayout());
00073 ButtonHandler Handler = new ButtonHandler();
00074 Buttons = new JButton[FIVE];
00075
00076 for(int ind = 0; ind<Buttons.length; ++ind)
00077 {
00078
00079 Buttons[ind] = new JButton("Button " + arr[ind]);
00080 Buttons[ind].setFont(FText1);
00081 Buttons[ind].setForeground(Color.blue);
00082 Buttons[ind].setBackground(Color.yellow);
00083 Buttons[ind].addActionListener(Handler);
00084 }
00085
00086 //order of adding buttons is irerelavant
00087 for(int ind = 0; ind<Buttons.length; ++ind)
00088 Cont.add(Buttons[ind], arr[ind]);
00089 //for(int ind = Buttons.length-1; ind>=0; --ind)
00090 //Cont.add(Buttons[ind], arr[ind]);
00091
00092 Win.show();
00093 }
00097 private void setSwingLookAndFeel()
00098 {
00099 //Removes the previous decoration
00100 Win.setUndecorated(true);
00101 //Sets the Swing look and feel decoration
00102 Win.getRootPane().setWindowDecorationStyle(JRootPane.FRAME);
00103 }
00107 public static void main(String[] args)

Graphical User Interface (Singhal) Page 26 of 41


00108 {
00109 // System.out.println(BorderLayout.NORTH);
00110 MyBorderlayout Temp = new MyBorderlayout();
00111 }
00112 }
//Listing 15.4
In this Listing, the class data members, ButtonHandler class, main method and
method setSwingLookAndFeel are identical to the Listing 15.3. What is different is
the way buttons are labeled and added to the window called Win. Class
BorderLayout has five static string constants accessible as: BorderLayout.NORTH,
BorderLayout.SOUTH, BorderLayout.EAST and so on. In fact a code line in main
such as:
System.out.println (BorderLayout.NORTH);
will print North on standard output. Therefore if wish to label the JButtons placed
on a window in border layout and name the buttons as North, South according to
their location in the display, we can use the corresponding string constants from
BorderLayout class to do so. Therefore we create a string array arr (L15.4#65-67)
where first array member is “North”, second “South”, and so on. The first for loop
arr (L15.4#76-84) instantiates the five JButton objects, sets their font, foreground
and background, and registers them with the event handler by calling the method
addActionListener. We add the buttons to the window Win using another loop
(L15.4#87-88) as we wish to show that in border layout the order in which
components are added to the display is irrelevant.

Figure 15.19 shows the output from the main method of Listing 15.4 in the as
displayed form and packed form.

Graphical User Interface (Singhal) Page 27 of 41


FIG. 15.19A

FIG. 15.19B
As indicated earlier, when the Swing Look and Feel is used the display at minimum
width and height packs all the components in the frame that is visible, with out
allowing the disappearance of any of the components. If the line 72 in Listing 15.4,
which sets the layout, is commented out, even then the output from main method of
Listing 15.4 remains unchanged. This is because the border layout is the default

Graphical User Interface (Singhal) Page 28 of 41


layout for any Java container. Border layout works quite well for using Java panels,
which are objects of class JPanel. We shall discuss the use of panels shortly.

Grid Layout
In grid layout, the components are arranged in a grid, which is controlled, by the
number of rows and columns defined by the user. Figure 15.20 shows the
constructors for the class GridLayout.
public GridLayout()
Creates a grid layout with a default of one column per component, in a single
row.
-------------------------------------------------------------------------------------------------
public GridLayout(int rows, int cols)
Creates a grid layout with the specified number of rows and columns. All
components in the layout are given equal size.
One, but not both, of rows and cols can be zero, which means that any
number of objects can be placed in a row or in a column.
Parameters:
rows - the rows, with the value zero meaning any number of rows.
cols - the columns, with the value zero meaning any number of columns.
-------------------------------------------------------------------------------------------------
public GridLayout(int rows, int cols, int hgap, int vgap)
Creates a grid layout with the specified number of rows and columns. All
components in the layout are given equal size.
In addition, the horizontal and vertical gaps are set to the specified values.
Horizontal gaps are placed at the left and right edges, and between each
of the columns. Vertical gaps are placed at the top and bottom edges, and
between each of the rows.
One, but not both, of rows and cols can be zero, which means that any
number of objects can be placed in a row or in a column.
All GridLayout constructors defer to this one.
Parameters:
rows - the rows, with the value zero meaning any number of rows
cols - the columns, with the value zero meaning any number of columns
hgap - the horizontal gap
vgap - the vertical gap
Throws:
IllegalArgumentException - if the value of both rows and cols is set to zero
FIG. 15.20
The argument-less constructor for class GridLayout places all components in one
row, in which case each component becomes a column in the display. The second

Graphical User Interface (Singhal) Page 29 of 41


constructor takes integer values of rows and columns as arguments and places the
added components accordingly. The last constructor takes four integer arguments,
the first two for rows and columns, and last two for placing horizontal and vertical
gaps between the added components. Listing 15.5 shows an example of grid layout.
00001 import java.awt.event.*;
00002 import java.awt.*;
00003 import javax.swing.*;
00007 public class MyGridlayout
00008 {
00012 private static final int FIVE = 5;
00016 private JButton [ ] Buttons;
00020 private static Color Window_Background = Color.cyan;
00024 private static String Title = "My Window with Plain buttons";
00028 private static int height = 800;
00032 private static int width = 800;
00036 private MyWindow Win;
00042 private static class ButtonHandler implements ActionListener
00043 {
00047 public void actionPerformed( ActionEvent e )
00048 {
00049 JOptionPane.showMessageDialog( null,
00050 "You pressed: " + e.getActionCommand());
00051 }
00052 }
00053
00059 public MyGridlayout()
00060 {
00061 Win = new MyWindow(Title,width,height, Window_Background);
00062 Win.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
00063 setSwingLookAndFeel();
00064 Font FText1 = new Font("SansSerif",Font.BOLD|Font.ITALIC,30);
00065 Container Cont = Win.getContentPane();
00066 //Cont.setLayout(new GridLayout(3,2,5,10));
67 Cont.setLayout(new GridLayout(3,2));
68
00068 //Argument-less constructor creates one row and
00069 //number of columns equal to the components to be added.
00070 //Cont.setLayout(new GridLayout());
00071 ButtonHandler Handler = new ButtonHandler();
00072 Buttons = new JButton[FIVE];
00073
00074 for(int ind = 0; ind<Buttons.length; ++ind)
00075 {
00076 Buttons[ind] = new JButton("Button " + (ind+1));
00077 Buttons[ind].setFont(FText1);
00078 Buttons[ind].setForeground(Color.blue);

Graphical User Interface (Singhal) Page 30 of 41


00079 Buttons[ind].setBackground(Color.yellow);
00080 Buttons[ind].addActionListener(Handler);
00081 //Order in which the components are added is important.
00082 Cont.add(Buttons[ind]);
00083 }
00084
00085 Win.show();
00086 }
00090 private void setSwingLookAndFeel()
00091 {
00092 //Removes the previous decoration
00093 Win.setUndecorated(true);
00094 //Sets the Swing look and feel decoration
00095
Win.getRootPane().setWindowDecorationStyle(JRootPane.FRAME);
00096 }
00100 public static void main(String[] args)
00101 {
00102 MyGridlayout Temp = new MyGridlayout();
00103 }
00104 }
//Listing 15.5
Since we are adding five buttons to the display, we set number of rows to three and
number of columns to two, which will be sufficient to place six (3x2) components on
it (L15.5#67). Figure 15.21A shows the result of executing the main method of
Listing 15.5.

Graphical User Interface (Singhal) Page 31 of 41


FIG. 15.21A
Notice that addition of the components begins from row one and column one. Then
addition continues until the first row is filled and then second row is started. Since
we only placed five components in the window in Figure 15.21A, the last spot in 3rd
row and 2nd column is empty and it shows the background color of the underlying
window. When the constructor on line 66 that uses the four arguments is
commented in then the display changes to the Figure 15.21B.

Graphical User Interface (Singhal) Page 32 of 41


FIG. 15.21B
Since this constructor takes an argument for horizontal gap as five pixels and that
for vertical as ten pixels, we see corresponding gaps between the vertical edges and
horizontal edges of components. The horizontal gap is placed between components
as one moves horizontally in a row, whereas the vertical gap manifests itself when
one moves up or down in a column.

What happens if the number of rows and columns specified in the second
constructor in Figure 15.20 calculates to the number of components spaces less than
the actual number of components added? In that case the number of rows set are
equal to the first constructor argument, whereas the number of columns is increased
to the necessary number that all added components are accommodated in the
display. For example if the constructor call on line 67 is changed to the one below,
then the display shown in the Figure 15.21C results.
Cont.setLayout (new GridLayout(2,1));

Graphical User Interface (Singhal) Page 33 of 41


FIG. 15.21C
Since in the new constructor call, the number of rows got reduced to two, Java
automatically bumps up the number of columns to three, so that all added
components can be displayed. However, if number of rows is set to zero (as per
constructor call similar to below), then the column argument is used and number of
rows is increased to a value that would allow accommodation of all added
components.
When used in Listing 15.5 to
replace line #67, it will create
Cont.setLayout (new GridLayout (0,1)); five rows and one column.

Setting both number of rows and columns equal to zero throws


IllegalArgumentException. Ironically the program will compile and run if both
rows and columns are set to negative values. However, in such case the components
added to the window are not displayed and one only sees that blank window frame.
We shall discuss more examples of layouts after we have shown an example of a
temperature conversion calculator.

Graphical User Interface (Singhal) Page 34 of 41


Temperature Conversion Calculator
Very often when we travel Europe, we need to convert local temperature, which is
reported there in Celsius into Fahrenheit. Here we design a simple Java calculator
that performs such conversions. In designing such application we need to make the
following decisions:
1. What graphical components we need?
2. How many of each such component do we need?
3. In what manner shall we paint these components on our canvass that finally
becomes our application?
4. Which components need the intelligence and what kind of intelligence would
it be?
5. What is the best way to modularize our design in terms of classes, data
members and methods in them?
Table 15.4 discusses the summary of above considerations.
Component or How many? Purpose Intelligence needed
their derived
classes
JTextField Two
JLabel Three
JButton Six
JPanel Five
JFrame One
Table 15.4

Graphical User Interface (Singhal) Page 35 of 41


Action Objects in Java
One has seen that in a typical word processing program, such as Microsoft word,
one can perform an action in several different ways. Figure xxxx below shows that
how one can perform cut, copy and paste action, either using the tool bar buttons or
the edit sub menus. In addition, the same functionality may be achieved by using

FIG. Xxx
accelerator keys. These are the keyboard actions, which perform the same task as
the mouse clicked tool bar, or menu items would. For example once the text is
highlighted in the word document, one may copy it by using the keys Control + C, in
place of performing the copy action using the tool bar or edit submenu.

Typically one provides this single task multi-enablement as follows: The tool bar
button, the menu item would be registered with the same ActionListener type
object, whose actionPerformed method would enable the two widgets to perform the
same function. However, we also wish that if user selected no text to copy then both
tool bar and menu copy options are disabled in unison! On the other hand if user
did select text to copy to system clipboard, then both aforementioned widgets must
enable in unison as well. Imagine what can happen if this synchronous behavior of
tool bar button and corresponding menu item was not present? The copy toolbar
button may be enabled, while the copy menu item may not be. Suffice to say that it
will cause confusion in using the GUI. The typical use of actionPerformed method in
an implemented ActionListener interface is straightforward in ascertaining that
when an event object fires, then all widgets registered with it behave in unison.
However, enabling and disabling of widgets in unison is not so straightforward. One
would actually need to keep a list of widgets, which register with a particular
ActionListener object, which requires extra programming effort. The situations,
where several widgets in a GUI must fire and get enabled and disabled in unison,
the use of Action object facilitates the task greatly.

Graphical User Interface (Singhal) Page 36 of 41


What is an Action Object?
An Action object is the one, which directly or indirectly, implements interface
javax.swing.Action. The Action interface extends interface
java.awt.event.ActionListener, which in turn extends interface
java.util.EventListener. Java has done bit of work for us as it already provides us an
abstract class javax.swing.AbstractAction, which in addition to implementing the
Action interface also implements Cloneable and Serializable. Objects of a class that
derives from an AbstractAction class are called Action objects. Figure xxx gives the
declaration of AbstractAction class indicating the interfaces it implements.
public abstract class AbstractAction
extends Object
implements Action, Cloneable, Serializable
Action interface extends
FIG. xxx ActionListener and
EventListener

The steps similar to the Figure XXX can be taken to synchronize behavior from all
widgets registered with the same action object (Copy_Obj in this case).
1. Define subclass of AbstractAction to implement the
actionPerformed ()

class CopyAction extends AbstractAction More than one


{ constructor may be
CopyAction () provided as needed.
{
super (“Copy”, new ImageIcon( ...image...);
}
public void actionPerformed(ActionEvent e)
{
//do the action here for all widgets registered with CopyAction
}
}

2. Create an object of this class


CopyAction Copy_Obj = new CopyAction ();

3. Install the object Copy_Obj on the components (widgets) that


must behave identically;

JButton Copy_Button = new JButton (Copy_Obj);


JMenuItem Copy_MItem = new JmenuItem (Copy_Obj);

Graphical User Interface (Singhal) Page 37 of 41


4. Control the UI from a single place, will disable the copy button
and the copy menu item
Copy_Obj.setEnabled (false);
FIG. XXX

Step four in Figure xxx shows that one can control the synchronous enablement or
disablement of user interface widgets from a single place, which in this case is the
Action object Copy_Obj. The step three in Figure xxx becomes possible because the
constructors of following widgets can take an Action object as argument thus setting
the property of the widget as supplied by the Action object passed to it (Figure
XXXX). The description of JButton constructor is also given.
JButton(Action a)
JToggleButton(Action a)
JCheckBox(Action a)
JMenuItem(Action a)

public JButton(Action a)
Creates a button where properties are taken from the Action
supplied.
Parameters:
a - the Action used to specify the new button
FIG. XXX
In addition to the constructors of widgets taking an Action object as argument, they
also have method setAction, which can take an Action object as argument. The list
of these methods and detail of one of them are given (Figure XXXX).
JComboBox.setAction (Action a)
JTextField.setAction (Action a)
JButton. setAction (Action a)
JToggleButton. setAction (Action a)
JmenuItem. setAction (Action a)

public void setAction(Action a)


Sets the Action for the ActionEvent source. The new Action
replaces any previously set Action but does not affect
ActionListeners independently added with addActionListener. If
the Action is already a registered ActionListener for the button, it
is not re-registered.

Graphical User Interface (Singhal) Page 38 of 41


A side-effect of setting the Action is that the ActionEvent
source's properties are immediately set from the values in the
Action (performed by the method
configurePropertiesFromAction) and subsequently updated as
the Action's properties change (via a PropertyChangeListener
created by the method createActionPropertyChangeListener.
Parameters:
a - the Action for the AbstractButton, or null
FIG. XXX
Thus for common widgets (JButton, JmenuItem, and JToggleButton) one may
either set their properties by passing the Action object to their constructor or by
using the member method setAction. Also understand that all methods and
constructors that take an object of type Action as argument will also take an object
of type AbstractAction as argument since latter implements the interface Action.

Methods and constants for class AbstractAction


Before we can make an active use of Action objects, we also need to take a look at
the fields, public methods and capabilities available to class AbstractAction (Table
XXX).

Field Summary (The Below are inherited from Interface Action)


static String ACCELERATOR_KEY
The key used for storing a KeyStroke to be used as the accelerator for
the action.
static String ACTION_COMMAND_KEY
The key used to determine the command string for the ActionEvent that
will be created when an Action is going to be notified as the result of residing
in a Keymap associated with a JComponent.

static String DEFAULT


Not currently used.
static String LONG_DESCRIPTION
The key used for storing a longer description for the action, could be
used for context-sensitive help.
static String MNEMONIC_KEY
The key used for storing an int key code to be used as the mnemonic for
the action.

Graphical User Interface (Singhal) Page 39 of 41


static String NAME
The key used for storing the name for the action, used for a menu or
button.
static String SHORT_DESCRIPTION
The key used for storing a short description for the action, used for
tooltip text.
static String SMALL_ICON
The key used for storing a small icon for the action, used for toolbar
buttons.

Constructor Summary for class AbstractAction


AbstractAction()
Defines an Action object with a default description string and default icon.

AbstractAction(String name)
Defines an Action object with the specified description string and a default icon.

AbstractAction(String name, Icon icon)


Defines an Action object with the specified description string and a the specified icon.

Public Method Summary for class AbstractAction


void addPropertyChangeListener(PropertyChangeListener listener)
Adds a PropertyChangeListener to the listener list.

Object[] getKeys()
Returns an array of Objects which are keys for which
values have been set for this AbstractAction, or null if no keys
have values set.
PropertyChangeListener[] getPropertyChangeListeners()
Returns an array of all the PropertyChangeListeners
added to this AbstractAction with
addPropertyChangeListener().
Object getValue(String key)
Gets the Object associated with the specified key.

boolean isEnabled()
Returns true if the action is enabled.

Graphical User Interface (Singhal) Page 40 of 41


void putValue(String key, Object newValue)
Sets the Value associated with the specified key.

void removePropertyChangeListener(PropertyChangeListener listener)


Removes a PropertyChangeListener from the listener list.

void setEnabled(boolean newValue)


Enables or disables the action.

Table XXX
The constructors of class AbstractAction show that any widget whose constructor
takes an Action object (hence an AbstractAction object) as argument can have its
label set to the desired string. Alternately an icon and a string can also be passed as
arguments.

Graphical User Interface (Singhal) Page 41 of 41


Java Applets
•Growth of java and Internet technologies exploded
simultaneously.
simultaneously
•In early days of Internet Java Applets made web
pages alive
i and animated.
i
•Quickly HTML writers and web masters learned to
write Java Applets, sometime even with out learning
rest of the Java language.
•Applets are less popular now, but they played
significant role in making java popular to masses.
Writing Applets
•Basically involves extending the class Applet
(JApplet in swing), from java.applet package.
•Applets
pp are run byy Web browser,, which means that
every web browser actually has a java virtual
machine of its own, which interprets the byte-code of
the Applet class embedded in the web page.
•Applets
pp have some special
p features which makes
their look, feel , and coding different from stand
alone java programs we have written so far.
Testing Applets
• Testing Applets is as important as writing them.
• Three levels of testing.
1. Simple - Testing with appletviewer tool in Sun Java
development environment.
2 Intermediate – Testing with the dominant Internet
2.
browser(unfortunately Internet Explorer these
days).
y)
3. Advanced – Testing with all browsers known to
mankind so far.
far
Testing Applets in CS 3
• We will confine to testing our applets with simple
and intermediate levels only.
only
• Professional work will need advanced testing.
• Main browsers in vogue today:
1 Internet Explorer 4,
1. 4 5,
5 6
2. Netscape 4, 5, 6
3. Opera 4, 5, 6
4 Mozilla 1.0
4. 10
Java Applet Class

Applet
pp Class API Documentation
Numerous Methods
Bare minimum ones are only two!
1. void init( )
Called by the browser or applet viewer
to inform this applet that it has been loaded
into the system.
2. Inherited from super class Container
void paint(Graphics g)
Hello World Java Applet
import java.awt.*;
i
import
t java.applet.*;
j l t*
public class HelloWorldApplet extends Applet{
public void init( ){
setBackground(new Color(250,0,100)); }
public void paint(Graphics g) {
gg.setFont(new
( Font("Ariel",
( , Font.BOLD,, 48));
));
g.setColor(Color.blue);
gg.drawString(
drawString("Hello
Hello to World From El Camino!
Camino!",0,150);
0 150);
}}
How Does it look?
Dissecting the Code
imports

Needs java.awt and java.applet packages


Dissecting the Code -2
Extends the class Applet

public class HelloWorldApplet extends Applet


Dissecting the Code - 3
init( ) method

•Sets the background color in this case


public void init( ) Takes Color object as
argument
{
setBackground(new Color(250,0,100));
}
C ll setBackground
Calls tB k d method
th d
Dissecting the Code - 4
Takes Font object as
paint( ) method argument

•Paints the applet on the frame


public void paint(Graphics g){
g.setFont(new Font("Ariel",
Font( Ariel , Font.BOLD, 48));
g.setColor(Color.blue); Set the color

g.drawString("Hello to World From El Camino!",0,150);}

String to be shown in Applet Location x and y


pixels
Code (HTML File) executed by
the Browser
<html> Needs the Applet tag
<body>
body
<applet code=HelloWorldApplet.class width=750 height=300>
</applet>
</body>
</html>
Needs the java class Applet
information. In this case the Height and
html file and class file in the width
same folder.
Browser Interprets the class file
and runs on client machine!
Security Issues?
1. Low level Security Issues
2 High
2. Hi h Level
L l Security
S it issues
i
Low level Security Issues

•Browser
Browser java virtual machine is not
allowed to run any code that may have an
assembly language instruction
instruction.
•This is because by running the assembly
code the server can get hold of random
chunks of client’s memory – a great
security hazard.
hazard
High level Security Issues
•Before Applet is run, the browser loads a
sec rit manager.
security manager
•If Applet code tries to read a file or write to
a file
fil on client
li machine,
hi the h security
i manager
will shut it down.
•The signed applets can ask client permission
to over-ride the security manager.
•Signed applet must give Server’s contact
information and risk level! With out that
browser will not let it run.
No main( ) method in the Applets
•One can design java virtual machine
to run
r n any
an method first
first.
•In this case the method init ( ) is
called
ll d first!
fi
Lifetime of a java Applet
•init( ) method is called first!
•Then browser calls an applet method called start( )).
•If user moves to another web page then the method stop( ) is
called to free non
non-memory
memory resources that applet may have been
using.
•For example
p if Applet
pp was doing g an animation, and user moves
to another web page, then stop ( ) method will stop the
animation and resources will be freed.
•When user returns to the page, the start ( ) method is called
and applet starts again.
•destroy(
d t ( ) method
th d iis called
ll d tto d
destroy
t th
the applet,
l t when
h all
ll
browser windows are closed!
Why our code did not have those
methods?
•start, stop and destroy methods are called internally by the
virtual machine,
machine so we do not need to include them
them.
•But to show their functioning we can include them
intentionally and show as to how they work.
work
•This is done in the next example.
BasicEventApplet
• In addition to init( ) and paint( ), the following methods are
added intentionally:
1. A constructor
2. start( )
3. stop( )
4 destroy( )
4.
Sequence of Events
• As soon as Applet is started, the constructor is called first.
• Then applet is initialized by calling the init( ) method.
method
• Then applet is started by calling the start( ) method.
• Th paint(
Then i ( ) method
h d paints
i the
h applet.
l
• If other widows cover and uncover the applet, the paint
method is called every time to paint the applet back.
back
Sequence of Events - 2
• If user moves to another web page then stop( ) method is
called to free non-memory resources.
• When user comes back to the applet web page again, the
applet is started again.
• This behavior may differ based on browser, but appletviewer
shows this sequence clearly.
Applets with parameters
• Applets can take parameters embedded in HTML code and
display them or use them in the applet display.
• Shown in the applet based on java file ParameterApplet.java
HTML code to include
parameters

• <APPLET
• CODE="ParameterApplet.class"
CODE "P t A l t l " WIDTH=450
WIDTH 450
HEIGHT=300>
• <PARAM NAME=
NAME="name"
name VALUE=
VALUE="Satish
Satish Prakash
Singhal">
NAME
attribute
• <PARAM NAME="yourHeight" VALUE="5.5">
• </APPLET> U param
Use VALUE
tag attribute
How Applet gets the parameters?
Uses its getParameter( ) method.
String getParameter(String name)
R t
Returns th
the string
t i value
l off the
th named
d parameter
t iin th
the
HTML tag.
For example the call
getParameter("yourHeight")
Will return the
h yourHeight
H i h value
l included
i l d d in
i the
h HTML
code.
CS 3: Java
Chapter 19: Connecting To Databases
Author: Satish Singhal Ph. D.
Version 1.0
One can connect to databases from a Java program through variety of interfaces.
The interface may be a desktop application, a web site, a cell or regular phone, or a
voice activated device. The database may be located locally on the client machine, or
located on a distant machine. In all cases, the computer (or program) requesting a
connection to database is called a client1 and the computer (or program) honoring
the request is called a server. This forms one type of client-server architecture. If
client and server are on the same machine, then there is no communication protocol
needed for the two to connect and communicate. The client-server relationship in
that case is almost similar2 to a person being able to open a browser by clicking on
the hyperlink embedded in their e-mail message. However, if the database were
located on a distant and/or on a different machine the communication would involve
some protocol. For example in a local area network in a company or university, the
computers may be connected by Ethernet protocol. The computers on Internet are
connected by TCP/IP networking protocol. This chapter is devoted, only to the
situation, where a Java program does not have to worry about as to what kind of
communication protocol would be there between the client and server. Later on
when we discuss networking Java application, we would lift this barrier.

Let us talk about databases briefly. A database is a collection of information. In this


generic sense all sources of knowledge can be considered databases. However, for
the sake of application development, we need to be more specific. Four different
kinds of databases are in common use.
1. Flat file database: Example of these is your Microsoft Excel spread sheet,
a simple text file in which you may have stored addresses and phone
numbers. A flat file can also be seen as one data table.
2. Multi-Table non-relational Database: In this case the database may
have more than one table (or more than one file). However, the various tables
are totally unaware of each other’s existence. This may lead to storage of
same data in several tables, and data needs to be changed then one would
need to change it in all tables, as tables have no means to communicate with
each other.
3. Multi-Table Relational Database (RDBMS or Relational Database
Management System): In this case the data tables can be linked in a

1
This is true even if the client program and database server program are located on the same
machine.
2
It is actually a bit more than that, however this simplification is reasonable.

Topic 19 Connecting to Databases (Singhal) Page 1 of 41


manner that if two tables need to store “same” data, then changing it in one
table will automatically change it in the “related” table as well.
4. Object-Oriented Database Management System (OODBMS): In
these type of databases the tables becomes objects, the way one has objects in
the OOP languages. Data tables may then have hierarchy, similar to the
inheritance model used in OOP.

Of four types of databases, the RDBMS are in widest use in enterprise applications.
To remove any ambiguity, let us clarify as to what we mean by a table? A table is a
collection of data, which has rows and columns. For example a typical address book
(Figure 19.1) may have rows where each row indicates the address record for a
person and with in each row, there would be fields or columns storing one type of
information.
Column

Name Street Address City Zip code State


John Doe 1122 Woodwork Drive Forrest Hills 90310 CA
Miss Informed 9000 Knowledge Lane Genius City 07201 MA
……. …………… ………… ……….. ….
FIG. 19.1
Row or
In above flat file database, each row becomes one record, and each column in
record
each record stores same type of information. Thus we can say that data
stored in a column in a database table will all have same “data-type”. For
example in Figure 19.1 Zip Code field only has numbers and not the
alphabets. Thus a column has data homogeneity or a data type. In database
language rows are also called tuples.

A Java program can do the following things with a database:


1. Create and delete tables in the database.
2. Insert new records in data tables or update existing records.
3. Query the database for information and print it.
Depending upon the degree of authorization provided to the client, the database
server may allow him/her to do all of the above or less. For example the DBA
(Database Administrator) would have full access to all database functions, whereas
the users may be limited, only to querying the database or inserting and updating
data. A special database language called Structured Query Language (SQL) is used
by the client to interact with the database. SQL is a declarative language and it has
no control structures. Unfortunately, before we can begin to discuss the techniques
of connecting to databases from a Java program, we must discuss some SQL basics
for those who may not have any background in the subject.

Topic 19 Connecting to Databases (Singhal) Page 2 of 41


SQL Basics
SQL has statements that can be subdivided into the following categories:
1. Data Definition Language (DDL): This part of SQL is used by the DBA to
create and modify tables, views3 and indices.
2. Data Manipulation Language (DML): Used for manipulating the data and
querying the tables in the database.
3. Data Control Language (DCL): Used for controlling the privileges granted to
the users of databases.
One unfortunate fact in the SQL world is that though there is so called “Standard
SQL”, each database vendor has chosen to alter it the way they see fit. Therefore,
when one would need to connect to a database through a Java program, the same
SQL statement may not work with all databases. Thus in writing each database
interface, Java programmer would need to learn the SQL flavor used by that
particular type of database. The SQL presented here was tested with Oracle 8i. We
believe that almost same or slightly modified forms will work with other databases.
Unlike Java, SQL is case insensitive. However, as a matter of convention, the
command parts of the statement or sometime whole statement are typed in
uppercase letters. Table 19.1 gives a brief summary of DDL statements.
DDL statement Type Purpose and use of the statement
CREATE TABLE ……………… Creates a new table with table name,
column names, and data types.
ALTER TABLE……………….. Alters an existing table and relationships
between tables.
DROP TABLE………………… Drops and removes a particular table
from the database
DESCRIBE ……………………… Describes columns and their data types
in a table
Table 19.1
Before we can show the use of DDL statements, we also need to discuss main SQL
data types. For Oracle 8i the data types are divided between following categories:
1. Numeric Data Types: These are the data types that are used for those
columns on which we may surmise doing some arithmetic at some points.
Notice that from that point of view the Zip code in Figure 19.1 shall not be
chosen as a numeric data type as one may never need to do arithmetic,
including the Zip code.
2. String Data Types: All the data types which will are not dates or which do
not need arithmetic on them, and which are not too large4 in number of
characters are deemed as string data types. For example all data types in
Figure 19.1 would be type string.
3. Date Data Types: Any dates from 1 January 4712 B. C. to 31 December 4712
A. D. can be represented as Date data types.

3
Word view has a special meaning in database technology. Its discussion is not in the scope of our
textbook.
4
Granted that term “not too large” is not well defined.

Topic 19 Connecting to Databases (Singhal) Page 3 of 41


4. Large Objects: Any large objects must be stored in several different data
types defined for them. In Oracle, their names are: BLOB, CLOB, NCLOB,
and BFILE. While we discuss some more details of first three data types
further, we do not discuss large objects here, as they are too specialized.

Numeric Data Types


Table 19.2 shows the numeric data types used in Oracle 8i.
Data Name Types Description Example
Data type for integers, Number (5) will
where precision gives the allow storage of
number of digits in the numbers from
Number (precision)
integer. The number -99999 to +99999
may be positive, negative
or zero.
Data types where fixed- NUMBER (9,3)
point arithmetic is needed. May be any of
Precision gives total these:
number of digits (including 999999.999
the fractional part). Scale
123.4
can be positive or negative.
Number (precision, 123
Number Positive value of scale
scale) defines maximum digits on 0.001
the right of decimal point.
If scale is negative then it
defines the maximum
number of digits on the left
of decimal point.
Data type for floating Number
point type numbers with Could be in format
out any limitation of 0.12345E2
Number 1.2345E1
precision and scale. This
matches Java double 12.345
12345E-3
data type.

Topic 19 Connecting to Databases (Singhal) Page 4 of 41


Same as Number. Used FLOAT
when Oracle need to be 12.345
FLOAT No sub types
compliant with ANSI
FLOAT data type
Used as a fixed point
number when
DECIMAL No sub type compatibility with other
data types such as DB2
is required
One character fixed ‘x’ – note that in
length data type Oracle single
Char quote is used for
both character
and string
String length is limited ‘Hello World’
String5
Char ( n) to n characters. n varies
from 1 to 255
Variable length string. As above.
The value of n varies
VARCHAR2 (n)
from 1 to
32K-1
The standard date 01-SEP-00
format (including time) 12:01:00
is DD-MON-YY A.M.
HH:MI:SS A.M. (or
Date No subtype
P.M.) with the 12-hour
clock. MON is the first
three alphabets in the
month
NULL data type in SQL is stored when a
value is not assigned to a field in a record.
NULL No subtype
Null is not same as zero or a blank – as both
of them are concrete values.
Table 19.2

Relationships between tables in RDBMS


In a full-fledged RDBMS class one would learn, that principles of database
normalization require that data storage redundancy be reduced to a minimum. This
sometimes requires that one data table be broken into two or more tables, and then
they can be related to each other as needed. For example – in Figure 19.1 we are
storing Zip code and state in the same table in which we store address. However, in
future, we may wish to add more tables in our database which may store addresses

5
There are other string data types in Oracle, such as NCHAR and LONG, which are not considered
here.

Topic 19 Connecting to Databases (Singhal) Page 5 of 41


of types that are different from the one’s in Figure 19.1. One example of that would
be when user may need to store business and personal addresses in the different
tables. In such case data redundancy would decrease if one would build a separate
table for Zip codes and states. One may then have two tables as shown in Figure
19.2 A and B.
ID # Name Street Address City Zip code
0001 John Doe 1122 Woodwork Drive Forrest Hills 90310
0002 Miss Informed 9000 Knowledge Lane Genius City 07201
….. ……. …………… ………… ………..
FIG. 19.2A: Table storing personal addresses

Zip code State


90310 CA
07201 MA
……….. ….
FIG. 19.2B: Table storing Zip codes and States

Now the Zip code field appears in both tables. However the two tables can now be
related via their common field. Since in Zip code table, no two records would ever
have same value of the Zip code (since no two sates in US have the same zip code),
the zip code field in this table is given a special name called “primary key”. On the
other hand in the first table, we may have addresses of more than one person living
in the same zip code. The relationship between two tables is then called one-to-many
relationship. When a primary key in a related table appears as a column in its
relative table, it is given a special name “Foreign key” in that table. Thus Zip code
field in the table with addresses is the foreign key. Though it is not necessary that all
tables have primary keys, it is undesirable to build a database table with out one.
The existence of primary keys helps build database indices and views to speed up
the search process, in addition to maintaining data integrity and reducing
redundancy. Therefore we added a column in the first table called ID #, which
would be different for each person in our personal address book, thus acting its
primary key. Decomposing the data tables in one or more, selecting proper primary
and foreign keys – are all part of good database design process.

DDL (Data definition language) Basics


Now we describe as how one can build database tables using DDL statements. While
flat files can be created in any order, the rules of building related table requires that
table whose primary key is used as a foreign key in its relative be created first. One
could get around it by using the ALTER statement, but that increases the overall
programming effort. In creating the tables in Figure 19.2, then we create the Zip
code table first using the CREATE statement. In order to create a table, the names
must be selected for the table, its columns and data types be selected for the latter.
Since we know that we would never need to do arithmetic with the column zip code

Topic 19 Connecting to Databases (Singhal) Page 6 of 41


and state, we select VARCHAR2 data type for both. The table name is simply
US_ZIP_CODES and the column names would be ZIP and STATE. The data type
for ZIP field will be VARCHAR2 (5) and for STATE field be VARCHAR2 (2). The
field ZIP will be designated as the primary key. The following syntax is used to
create a table in the database (Figure 19.36).

FIG. 19.3

Using the syntax of Figure 19.3, the following statement will create the table called
US_ZIP_CODES in the database.

6
I sincerely acknowledge Professor Harold Rogler at Santa Monica College, from whose notes this
Figure is taken from.

Topic 19 Connecting to Databases (Singhal) Page 7 of 41


CREATE TABLE US_ZIP_CODES
( Syntax for setting the
ZIP VARCHAR2 (5) NOT NULL, ZIP column as primary
STATE VARCHAR2 (2) NOT NULL, key. The constraint
CONSTRAINT PK_US_ZIP_CODES name is optional but
PRIMARY KEY (ZIP) desirable.
);

Table 19.3 gives the decisions made about the personal address table and its
columns.

Table Property Value(s)


Property
Table PERSONAL_ADDRESS_BOOK_US
name
Field Name Data type Remarks
ID_NUM VARCHAR2 (4) Primary key. Constraint name:
PK_ AD
NAME VARCHAR2 (30)
Field ADDRESS VARCHAR2 (100)
CITY VARCHAR2 (20)
ZIP_CODE VARCHAR2 (5) References the Foreign key ZIP
from table US_ZIP_CODES.
Constraint name:
FK_USCODES_ZIP
Table 19.3

The following DDL statement would create the table


PERSONAL_ADDRESS_BOOK_US.

CREATE TABLE PERSONAL_ADDRESS_BOOK_US


(
ID_NUM VARCHAR2(4) NOT NULL, Oracle some times cannot
NAME VARCHAR2(30) NOT NULL, handle long names for
CITY VARCHAR2(20) NOT NULL, constraints. Be sure to look up
ZIP_CODE VARCHAR2(5) NOT NULL, documentations.
ADDRESS VARCHAR2(30),
CONSTRAINT FK_USCODES_ZIP
FOREIGN KEY (ZIP_CODE) REFERENCES US_ZIP_CODES (ZIP),
CONSTRAINT PK_AD
PRIMARY KEY ( ID_NUM )
);

Some times we may need to alter the tables after they have been created. The
ALTER statement is used for that. For example we may need to add two more

Topic 19 Connecting to Databases (Singhal) Page 8 of 41


columns to the personal address book table: The date of birth, so that we can send
them a card, and maximum money budgeted for their birthday present. Table 19.4
shows the names and data types for the new fields to be added.
Field Name Data Type
B_DATE DATE
GIFT_LMT NUMBER(4,2)
Table 19.4

The following ALTER statements will add the additional columns to the table
PERSONAL_ADDRESS_BOOK_US.

ALTER TABLE PERSONAL_ADDRESS_BOOK_US ADD


(
B_DATE DATE ,
GIFT_LMT NUMBER(4,2)
);
If you now run the DESCRIBE query on the above table in SQL as follows, you will
get the result shown in Figure 19.4.

SQL> DESCRIBE PERSONAL_ADDRESS_BOOK_US;

FIG. 19.4
The decision whether to choose certain field as non-null depends on if not recording
the value of that field in database will make the record meaningless. For example an
address entry with out person’s name, city and zip code is meaningless and we
might as well wait until those data about person become available. We can afford
not to have street address, and birth date in the beginning as those data can be
added later. Therefore a null value for them, in the interim, is affordable.

The DROP statement deletes the table from the database. The syntax of DROP
statement is simple:

Topic 19 Connecting to Databases (Singhal) Page 9 of 41


>DROP [table name];

DML (Data manipulation language) Basics


Table 19.5 gives the summary of important DML keywords, which start the DML
statements.
DML statement Type Purpose and use of the statement
INSERT Inserts a row or record in the table
SELECT Makes various queries on the database in general or queries
specific to a table.
UPDATE Modifies an existing record in the data table
DELETE Deletes a record from a table
Table 19.5

INSERTing the data into tables


Safe method for inserting the data into the table uses the following syntax:

INSERT INTO TableName


( [ColumnName] [, ColumnName]...[,ColumnName])]
VALUES
(ColumnValue[, ColumnValue]...[,ColumnValue]);

After using the words INSERT INTO one provides the list of columns into which
data are to be entered. The column names are separated by comma. Then after the
word VALUES one provides a comma-separated list of values in the same order in
which column names were provided. The number of columns and values in the
INSERT statement must be equal. If the data table has a primary key, then a record
cannot be inserted unless the value of primary key is specified. This, as you would
recall, that a primary key for a record cannot be null. The data types for values
must match the data types for columns – though some exceptions to this rule may
exist.

Since the Table US_ZIP_CODES has a field that acts as a foreign key to the table
PERSONAL_ADDRESS_BOOK_US, we must populate the former first. An
INSERT statement such as below would insert the Zip code and state values.

INSERT INTO US_ZIP_CODES


(ZIP, STATE)
VALUES
(‘90310’, ‘CA’);

Topic 19 Connecting to Databases (Singhal) Page 10 of 41


Now to insert data for John Doe into table PERSONAL_ADDRESS_BOOK_US we
execute the following SQL statement.

INSERT INTO PERSONAL_ADDRESS_BOOK_US


(ID_NUM, NAME, CITY, ADDRESS, ZIP_CODE, B_DATE, GIFT_LMT )
VALUES
(‘0001’, ‘John Doe’, ‘Forrest Hills’, ‘1122 Woodwork Drive’, ‘90310’,
’11-JAN-66’, 25.00 );

Typically one would create a script to populate database if non-graphical interface


is used. Otherwise a graphical interface to the database will handle all inserts and
data validation. One can enter the values into the database without providing the
column names. However, in such case one must know the order in which columns
are arranged in a record and then one must provide the data in order that maps to
the column sequence from left to right. This is a needless risk not worth taking as it
may corrupt the database.

SELECT statements
Since the biggest application of databases is in making queries on the data stored in
them, SELECT statement is one of the most used SQL statements. Simplest use of
SELECT statement is in getting all the records stored in a table. For example the
statement below may produce an output similar to the Figure 19.5.

SELECT * FROM US_ZIP_CODES;

FIG. 19.5

The use of * after the word SELECT tells the database to get all the records from
the table US_ZIP_CODES. The header of second column is truncated. Very often
the queries are done subject to some constraints. For example we may only be
interested in getting the list of Zip codes stored in the table for California or CA.
The keyword WHERE is used to qualify the query further.

SELECT * FROM US_ZIP_CODES


WHERE STATE = ‘CA’;

The above query would only produce the first line of output from the Figure 19.5.
Wild cards can be added to the queries.
For example a query such as below will produce result shown in Figure 19.6.

Topic 19 Connecting to Databases (Singhal) Page 11 of 41


SELECT NAME, ADDRESS, ZIP_CODE FROM
PERSONAL_ADDRESS_BOOK_US
WHERE NAME LIKE '%oh%';

FIG. 19.6
SELECT statement can use keywords ORDER BY to sort the data based on certain
column of some other criteria. We postpone showing other uses of SELECT till we
discuss them through some concrete Java program examples.

UPDATE statement
UPDATE statement is used to alter the value of a field, other than primary key, of a
record in the data table. If the field to be altered is a foreign key, then the new value
must exist in the related table before an update is done. The Figure 19.7 shows the
syntax of UPDATE statement.

UPDATE TableName Name(s) of column whose value is to be


updated.

SET ColumnName = expression [, …] [,ColumnNameN = expressionN]

The new value for the column. This can be a literal, another
[WHERE condition];
column name, an expression involving literals, strings, and
column names.

Optional WHERE
statement would make
assignments only when
condition is true for a
row!

Notice that after the word SET the column names and their expression list is comma
separated.

Let us imagine that John Doe shown in Figure 19.6 moved to Florida with new
address being ‘1923 Swamp Lane’ ‘Water Falls’, ‘FL’, ‘32003’. Then since Zip code
field in the address book table is a foreign key, first we must ascertain that this new
zip code in Florida exists in the related table for US Zip codes. If not then we insert

Topic 19 Connecting to Databases (Singhal) Page 12 of 41


it using the INSERT statement. The following statement will make the requisite
changes for John Doe’s move to Florida.

UPDATE PERSONAL_ADDRESS_BOOK_US
SET ADDRESS = '1923 Swamp Lane', CITY = 'Water Falls',
ZIP_CODE = '32003'
WHERE ID_NUM = '0001';

In above statement the WHERE clause defines the location of the record to be
updated by specifying the primary key (ID_NUM) for the record. As alluded earlier,
depending upon the WHERE condition, fields for more than one records can be
altered in one UPDATE statement.

DELETE statement
The DELETE statement can remove a record from the data table. The syntax for
DELETE is given below.

DELETE FROM TableName The row or rows for which the


[WHERE condition]; condition is true are deleted. No
deletions are done, if condition is not
true.

Understand that if where clause is skipped then ALL rows from the table with
TableName are deleted. An easier way to delete all rows from a table is to use the
TRUNCATE statement. For example syntax like below will delete all rows from
table called TableName.

TRUNCATE TABLE TableName;

SQL operators
We have already seen one SQL operator equal (=) in use. The SQL operators can be
words as well as mathematical symbols. Table 19.6 gives a list of commonly used
SQL operators.
Operator symbol/word Meaning Example
= Equal WHERE ID_NUM = 0001
> Greater than WHERE AGE> 20
< Less than WHERE AGE><25
>= Greater than or equal WHERE AGE >= 36
<= Less than or equal WHERE AGE <= 99
<> Not equal WHERE AGE <> 55
LIKE Pattern match WHERE NAME LIKE ‘%hn’
IN Matches any of given choices WHERE AGE IN (19, 20, 20)
Table 19.6

Topic 19 Connecting to Databases (Singhal) Page 13 of 41


Notice that in SQL the equal (=) operator is not an assignment operator. Rather it is
a relational operator similar to operator equal equal (==) in Java.

Logistics of connecting to a database


All databases provide a command line interface7 to the user, which depending upon
the authorization level, the user can use to interact with it. However programs
written in modern languages, such as Java, C#, and C++ can simplify user
interaction with the database. Such programs then become a software layer between
the user and the database. The task of this software layer is to be user friendly, yet
to accomplish all tasks that user need to complete using the database. Such software
layer written in Java would have SQL embedded in it. However, since Java alone
cannot compile the code that database can read, it needs another intermediate
software layer to which it can give its embedded SQL to compile. This other
intermediate software layer is called a database driver. Figure 19.7 shows the
various software layers between the user and the database.

FIG. 19.7
Therefore in the process of connecting to a database, a Java program first loads the
driver for the database and then communicates to DB through it. Two Java
packages java.sql and javax.sql provide necessary classes for facilitating the overall
communication with databases. A more popular name for these packages is JDBC
or Java database connectivity. Let us talk a bit more about database drivers. For
various flavors of windows Microsoft introduced a system of database drivers
collectively called ODBC (open database connectivity). One can find these drivers
by using the following procedure in Windows 9X:

7
The database such as Microsoft Access provide graphical interface with some functionality as well.

Topic 19 Connecting to Databases (Singhal) Page 14 of 41


1. Click on start
2. Click on settings
3. Click on control panel8
4. Double click on icon “ODBC Data sources” (32 bit)
5. On User DSN tab, click on “Add”. This will show a popup box similar to
Figure 19.8. This box lists all the ODBC drivers available for various
databases and flat files on windows.

FIG. 19.8
ODBC drivers are written in C programming language. A Java program can in fact
make calls to ODBC driver directly as Java allows native method calls. This
however is complicated, as doing so would require differing codes to load different
drivers (one piece of code to load driver for Access, and another SQL server, or text
file, or Excel spread sheet). Also C has pointers, which are inherently unsafe, thus
compromising Java’s security paradigm. Sun found a solution to this problem, by
including a JDBC to ODBC bridge in its JDBC API. The JDBC:ODBC bridge can
load and communicate with any of the ODBC drivers with out having to worry
about as to which database is being called from your program. Therefore if we use
JDBC:ODBC bridge, then the database driver portion of Figure 19.7 can be
visualized in more detail as shown by Figure 19.9.

8
On Windows 2000, XP, and NT one may need to click on “Administrative Tools” in order to get to
icon ODBC Data Sources.

Topic 19 Connecting to Databases (Singhal) Page 15 of 41


FIG. 19.9
Though in this book we would make exclusive use of JDBC:ODBC bridge, as per
Sun Microsystems, we must warn that this bridge is only for code testing. In actual
production environment, where database is actually being operated in the enterprise
setting, using JDBC:ODBC bridge is not advisable, as it was never designed for
heavy-duty applications. In addition the JDBC:ODBC bridge does not support
multi-threading, thus cannot be used for those applications. There are three other
kinds of database drivers, other than JDBC:ODBC bridge that are available. These
are typified by Sun as:
• Type 2: Driver that is partly written in Java and partly in native code. In
addition to using Java library, one must use some platform specific code to
use these drivers9.
• Type 3: Driver written purely in Java, where database independent protocol
is used to communicate with database through an intermediate software
layer called “Application Server”.
• Type 4: Driver written purely in Java that communicates to database
directly (with out an intermediate application server).

Sun Microsystems maintains a web site where one can get list of available drivers
for various databases at the web address:
http://servlet.java.sun.com/products/jdbc/drivers/index.html
Since the above address may change in time, the generic web address java.sun.com
can be used to search for current database drivers. Knowing some details of
database drivers to use, following steps are taken to connect to the database:

9
Type 1 drivers use JDBC:ODBC bridge API.

Topic 19 Connecting to Databases (Singhal) Page 16 of 41


1. Import the necessary classes
2. Load the database driver
3. Provide the followings for the database: The database URL, username, and
password
4. Get a Connection object to the database
5. Do data processing
Allocate a Statement object
Execute queries using the Statement object
If data retrieval was the purpose of the query, then data is stored in the object
called ResultSet
Process the data from the ResultSet object
Close the ResultSet
6. Close the Statement object
7. Close the Connection object (closes the connection to database).
In above procedure, the Java classes used (in sequence of use) are JdbcOdbcDriver
(step 2), Connection (step 4), Statement (step 5.1), and ResultSet (step 5.3) – all part
of JDBC. However if you search your hard drive, or Java documentation for a file
with name JdbcOdbcDriver.java, you are not going to find one. The reason for that
is because this class is embedded in a dynamic link library (dll) called JdbcOdbc.dll
located in the bin folder of your Java SDK. This is sort of the same approach that
Microsoft uses to provide classes in their dot net development tools. There are two
ways to use JdbcOdbcDriver class to load JDBC:ODBC bridge. One is that we
simply call the constructor for class JdbcOdbcDriver using the syntax below:

new JdbcOdbcDriver( );

This requires an import statement as below:

import sun.jdbc.odbc.*;

Net affect of using the above import and calling the constructor of JdbcOdbcDriver
class is to extract the necessary information from JdbcOdbc.dll and add it to your
program.

There is an alternate approach available, where you do not have to import the
package sun.jdbc.odbc. This approach uses the class named Class in java.lang
package. This class has a static method called forName, which takes a string
containing fully qualified name of a class, makes a constructor call for that class and
returns a Class object for it. You can actually call the static method shown below
(Listing 19.1) from the main method, and output will print java.lang.String.

Topic 19 Connecting to Databases (Singhal) Page 17 of 41


private static void someTest1()
{
Class Str = null;
try
{
Str = Class.forName ("java.lang.String");
}
catch (ClassNotFoundException Cex)
{
System.out.println ("ClassNotFoundException thrown");
}
System.out.println (Str.getName());
}//Listing 19.1
The static method forName takes the string “java.lang.String” as argument, finds
the class String, calls its constructor, and returns a Class object for class
java.lang.String. Then the last statement in Listing 19.1 calls the method getName to
print the name of the class that object Str contains. The method forName must be
called inside a try block as it may throw a checked exception of type
ClassNotFoundException. The main point of this is that forName method will call
constructor of any class whose qualified name is passed to it as a String. Therefore
in order to load a JDBC:ODBC bridge driver, we use this technique as follows:
Argument to forName
Class.forName (“sun.jdbc.odbc. JdbcOdbcDriver”); method must be a fully
qualified class name.
Doing so does not require importing package sun.jdbc.odbc.
However in this cases the call to load database driver must be made inside a try
catch block as the method forName throws an exception of type
ClassNotFoundException, which is a checked exception. Thus the syntax for above
calls would be similar to the one given below.

try
{
Class.forName (“sun.jdbc.odbc. JdbcOdbcDriver”);
}
catch(ClassNotFoundException Cnfex)
{
//code to handle ClassNotFoundException
}
The third step in the procedure is to get URL string, user name and password
strings for the database we are interested in communicating with. The last two
strings are set by the DBA for the user.

Topic 19 Connecting to Databases (Singhal) Page 18 of 41


Database URL String
The database URL string has three or more parts, separated by colon. First part is
simply jdbc, signifying that JDBC, rather than a native method call is being used.
The second part is a sub-protocol, which is either the name of the driver or the
name of the connectivity mechanism. For example on Windows platform one of the
connectivity mechanism (also the one we would use) is odbc. The third portion is the
database identifier. Therefore we may look at the database URL as given below
(Figure 19.10).

FIG. 19.10
The driver being used could determine database identifier name, however it
depends upon how the driver and DB administration software maps the database
file(s) to their physical directory. There are two situations we may face.
1. Database is created through the process, which simultaneously registers it
with the driver.
2. Database exists but it has not been registered with the driver or DB
administration tools.
We show examples for both cases (for Windows 9x) and how the database identifier
is generated. Let us assume that you wish to create a Microsoft Access database
called MyAddressBook, which shall be located on physical drive C. Figures 19.11
show, the process step-by-step.
1. Click on startÆ Settings Æ Control Panel.
2. Double click on ODBC Data Sources10 (32 bit) so that applet shown by
Figure 19.11 A shows up.

On Windows XP, NT and 2000, the ODBC source icon can be reached as follows: Click on start Æ
10

Control Panel Æ Administrative Tools Æ ODBC Source.

Topic 19 Connecting to Databases (Singhal) Page 19 of 41


FIG. 19.11A
3. If User DSN tab is not already selected, then select it.
4. Click on Add button to create and register new database.
5. This will show an applet similar to Figure 19.8. From that applet select
Microsoft Access driver and click on finish button. This will show the dialog
box shown in Figure 19.11B.

Click on create, after filling out the


Data Source Name and brief
description.

FIG. 19.11B
6. In this dialog box fill out (as shown above), the data source name and its
brief description. Then click on create. The data source name and
description is for identifying the database.

Topic 19 Connecting to Databases (Singhal) Page 20 of 41


7. Clicking on the create button will show the new dialog box shown by Figure
19.11C.
3. Click on OK

1. Fill the
database
file name.

2. Choose the directory


where database will locate.

FIG. 19.11C
Here fill out the database file name (bubble #1). Choose the physical directory in
which database will be located. And finally click on OK button. The success of
database creation will be indicated by the confirmation dialog popup message
(Figure 19.11D).

FIG. 19.11D
If we choose database name to be MyAddressBook.mdb and its physical location
on drive C, then clicking on OK in Figure 19.11C will give the message shown in
Figure 19.11D.
8. Close out all dialog boxes by clicking ok in each case.

The database identifier (the last part of database URL string) is then the Data
source name (DSN) that we filled out in Figure 19.11B. For example the
identifier for the database created above is: “Personal Address Book”.

The above process creates a database and registers it with the ODBC driver
simultaneously. If the database already exists but it has not been registered with

Topic 19 Connecting to Databases (Singhal) Page 21 of 41


the ODBC driver then the procedure remains the same up to the step five shown
above. Since the database already exists, then in step six, one clicks on “select”
button (instead of create button). This will show up a different dialog box as
shown in Figure 19.11 E.
Fill out the data
source name
and description.

Click on select button after filling


out the Data source name and
description.

FIG. 19.11E
Repeat steps six for the pre-existing database, and then click on select button
(Figure 19.11E). This makes sense because the database already exists, so we do
not need to create it. Rather we just need to select it to finish the registration
process. This leads to the popup window similar to the one shown in Figure
19.11C. This time however navigate to the physical location on the drive where
database is located and choose it so that its name shows up in the left pane. Then
select it and click ok. For example had you created the database
MyAddressBook independently through Microsoft Access and then try to
register it, then selecting it for registration will lead to the Figure 19.11F below.

FIG. 19.11F

Topic 19 Connecting to Databases (Singhal) Page 22 of 41


Then click ok on all the open dialog boxes until you finish the registration process.
In both cases the database identifier is simply the data source name(DSN) registered
with ODBC. If you are using the Oracle database, the Oracle sat up will have you
choose a database name up front. Just choose that name as an identifier. Therefore
now we can complete the last part of Figure 19.10 to show all components of the
database URL (Figure 19.12).

FIG. 19.12
Thus the URL string for the database created or registered as above will be:
“jdbc:odbc: Personal Address Book”. Notice that URL string does not need to know
the physical drive and file extension of the database as the ODBC driver (after
registration) has both of those registered with it already.

A part of the database URL string will change if you are connecting to the database
across a network. For exact semantics of figuring out sub protocol and database
identifier, you would need to consult the literature that comes with the database.
For example let us say you were connecting to a database on Internet, which has the
following details:
Connection method: jdbc:rmi (Remote method invocation)
Database web URL: 192.168.170.27:1099
Sub protocol: jdbc Portion before colon gives the IP
Database identifier: cloudscape:db address and after the colon gives the
Then the database URL in this case is: port number.

“jdbc:rmi:// 192.168.170.27:1099/jdbc: cloudscape:db”


Program in this case would first try to make a network connection through RMI. If
connection is made, then it uses the last part (jdbc:database name) to connect to the
database on that server. Understand that writers of the driver for the database
determine as to what the URL would be. Therefore at times deciphering the
database URL may become a bit of a project in itself. Better is the documentation
provided by the driver writer, easier would be to figure out database URL.

Topic 19 Connecting to Databases (Singhal) Page 23 of 41


Once we have the database URL string, the user name and password, we would
need an object of type java.sql.Connection, which in affect represents the database
we are connecting to as an object in our program. Connection is a Java interface.
One of the overloaded static methods getConnection of class
java.sql.DriverManager would take URL string, user name, and password and
return to us the Connection object to the database we are seeking. Table 19.7 shows
the three versions of overloaded method getConnection.
Overloaded method getConnection for DriverManager class
static Connection getConnection(String url)
Attempts to establish a connection to the given database
URL.
static Connection getConnection(String url, Properties info)
Attempts to establish a connection to the given database
URL.
static Connection getConnection(String url, String user,
String password)
Attempts to establish a connection to the given database
URL.
Table 19.7

The most commonly used version is the third one which takes database URL, user
name and password as arguments. The details of the third version taken from Java
API are shown in Figure 19.13.
public static Connection getConnection(String url, String user, String password)
throws SQLException
Attempts to establish a connection to the given database URL. The DriverManager
attempts to select an appropriate driver from the set of registered JDBC drivers.
Parameters:
url - a database url of the form jdbc:subprotocol:subname
user - the database user on whose behalf the connection is being made
password - the user's password
Returns:
a connection to the URL
Throws:
SQLException - if a database access error occurs
FIG. 19.13
Notice that method getConnection throws an SQLException, which is a checked
exception. Therefore any call made to getConnection must be inside the mandatory
try block followed by a catch block to handle the exception. Therefore the syntax of
the call to getConnection method would look like as follows:

Topic 19 Connecting to Databases (Singhal) Page 24 of 41


try
{
Connection Con = DriverManager.getConnection (
“database URL string”, “user name string”, “password string”);
}
catch(SQLException Sqex)
{
//code to handle SQLException
}

The version of getConnection method that takes a single string as argument can be
used by folding database URL string, user name, and password – all in one using the
following syntax:

try
{
Connection Con = DriverManager.getConnection (
“database URL string;UID=user name string; PWD=password string”);
}
catch(SQLException Sqex)
{
//code to handle SQLException
}
The getConnection method parses the string passed to it as argument for database
URL, user name and password and either returns a corresponding Connection
object or throws SQLException. Once a Connection object is obtained, the
Statement object can be created for further data processing.

In order to use the above technology effectively, we wish to design a class called
MyConnection in which client usable methods will all be static. We would like this
class to have the intelligence, that it would return to us a Connection object for the
given database URL, user name and password. And in the process it will also take
the input for the type of database driver, other than JDBC:ODBC bridge that we
may wish to use. The class would also have methods to close the database connection
and provide a list of all the drivers loaded. This class can be used to open
connections to as many databases as user wishes to open at the same time. Table
19.8 gives the summary of the design of class MyConnection. A high-level diagram
showing class fields, constructor and methods is given by Figure 19.14.

Topic 19 Connecting to Databases (Singhal) Page 25 of 41


Methods needed
by the client.

FIG. 19.14: All members shown with a lock are private


Methods needed by client are: getMyConnection, closeMyConnection,
getDatabaseMetaData, okToUseBatchOperation, and listLoadedDrivers.
Field Summary For class MyConnection
private Connection Con
Connection object returned by the getConnection method.
private String DB_URL
Database or JDBC URL.
private String DriverPath
The full qualified name for the class driver class.
private String PassWord
Password set for the user by the DBA or by the system.
private Properties Prop
The Properties object set for the class MyConnection, in case one
wishes to use the getConnection method that takes Properties
object as an argument.
private String UserName
The user name set for the user by DBA

Topic 19 Connecting to Databases (Singhal) Page 26 of 41


Constructor Summary For class MyConnection
private MyConnection(String DB_URL, String UserName, String PassWord)
Creates a new instance of MyConnection.

Method Summary For class MyConnection


static void closeMyConnection(java.sql.Connection Con)
Closes the connection to the database whose
Connectionobject is passed to it.
static getDatabaseMetaData(java.sql.Connection Con)
java.sql.DatabaseMetaData Returns the object DatabaseMetaData for the
database to which Connection object is attached.
static java.sql.Connection getMyConnection(java.lang.String URL_Str,
java.lang.String Name, java.lang.String Pword)
The method getMyConnection gets the Connection
object for a certain database.
private void initializeJdbcOdbc()
Takes user input for the type of database driver to be
used.
static void listLoadedDrivers()
Lists the drivers that have been loaded by calling the
static method getMyConnection.
private void makeconnection()
Sets the Connection object to the desired database for
the user by calling the method getConnection of class
DriverManager.
static boolean okToUseBatchOperation(java.sql.Connection Con)
Determines if the batch execution of SQL statements
on the database are acceptable by the database driver.
private void setDriver(java.lang.String Input)
Sets the DriverPath data member to the String passed.
Table 19.8

Listing 19.2A shows the source code implementing the design shown by Table 19.8
and Figure 19.14.

Topic 19 Connecting to Databases (Singhal) Page 27 of 41


00001 /*
00002 * MyConnection.java
00003 *
00004 * Created on October 11, 2004, 3:46 PM
00005 */
00006 import java.sql.*;
00007 import java.io.*;
00008 //uncomment the below if using the constructor of class JdbcOdbcDriver
00009 //import sun.jdbc.odbc.*;
00010 import javax.swing.*;
00011 import java.util.*;
00021 public class MyConnection
00022 {
00026 private String DB_URL;
00030 private String UserName;
00034 private String PassWord;
00038 private Connection Con;
00043 private String DriverPath = "sun.jdbc.odbc.JdbcOdbcDriver";
00049 private Properties Prop = new Properties();
00056 private MyConnection(String DB_URL, String UserName, String
PassWord)
00057 {
00058 this.DB_URL = DB_URL;
00059 this.UserName = UserName;
00060 this.PassWord = PassWord;
00061 }
00071 public static Connection getMyConnection(String URL_Str,String Name,
String Pword)
00072 {
00073 if(URL_Str == null || Name == null || Pword==null)
00074 throw new NullPointerException("getMyConnection: Null String passed");
00075 MyConnection MyCon = new MyConnection(URL_Str,Name,Pword);
00076 MyCon.initializeJdbcOdbc();
00077 MyCon.makeconnection();
00078 return MyCon.Con;
00079 }
00084 private void initializeJdbcOdbc()
00085 {
00086 String Input = JOptionPane.showInputDialog(null,
00087 "JDBC:ODBC bridge will be loaded by default. \nEnter full qualified name "
+ "of driver class if other database\n driver is to be used. Otherwise click cancel.");
00089
00090 if(Input !=null)
00091 {
00092 Input = Input.trim();

Topic 19 Connecting to Databases (Singhal) Page 28 of 41


00093 if(Input.equals(""))
00094 {
JOptionPane.showMessageDialog(null,"Zero length String entered. Default Driver"
00096 +" will be loaded");
00097 }
00098 else
00099 setDriver(Input);
00100 }
00101
00102 try
00103 {
00104 Class Bridge = Class.forName(DriverPath);
00105 }
00106 catch(ClassNotFoundException E)
00107 {
JOptionPane.showMessageDialog(null, "ClassNotFoundException thrown");
00109 E.printStackTrace();
00110 }
00111 }
00116 private void setDriver(String Input)
00117 {
00118 this.DriverPath = Input;
00119 }
00125 private void makeconnection()
00126 {
00127 Prop.setProperty("USER", this.UserName);
00128 Prop.setProperty("PASSWORD", this.PassWord);
00129 try
00130 {
00131 // Con = DriverManager.getConnection(this.DB_URL,Prop);
00132 Con =
DriverManager.getConnection(this.DB_URL,this.UserName,this.PassWord);
00133 //String Str =
this.DB_URL+";UID="+this.UserName+";PWD="+this.PassWord;
00134 //Con = DriverManager.getConnection(Str);
JOptionPane.showMessageDialog(null, "Established connection to Database"
00136 + " " + this.DB_URL);
00137 }
00138 catch(SQLException E)
00139 {
JOptionPane.showMessageDialog(null, "SQLException thrown while connecting to database"
00141 + " " + this.DB_URL);
00142 E.printStackTrace();
00143 }
00144 }

Topic 19 Connecting to Databases (Singhal) Page 29 of 41


00150 public static void closeMyConnection(Connection Con)
00151 {
00152 if(Con == null)
00153 {
00154
00155 }
00156 String Cat = null;
00157 try
00158 {
00159 Cat = Con.getCatalog();
00160 //System.out.println(Cat);
00161 Con.close();
00162 }
00163 catch(SQLException Sqex)
00164 {
00165 JOptionPane.showMessageDialog(null,
00166 "SQLException thrown while disconnecting from the database"
00167 + " "+ Cat);
00168 Sqex.printStackTrace();
00169 }
00170 }
00174 public static void listLoadedDrivers()
00175 {
00176 List drivers = Collections.list(DriverManager.getDrivers());
00177 for (int i=0; i<drivers.size(); i++)
00178 {
00179 Driver driver = (Driver)drivers.get(i);
00180 // Get name of driver
00181 String name = driver.getClass().getName();
00182 System.out.println(name);
00183 // Get version info
00184 int majorVersion = driver.getMajorVersion();
00185 int minorVersion = driver.getMinorVersion();
00186 boolean isJdbcCompliant = driver.jdbcCompliant();
00187 System.out.println("The major version of driver is =
"+majorVersion);
00188 System.out.println("The minor version of driver is =
"+minorVersion);
00189
00190 if(isJdbcCompliant)
00191 System.out.println("The driver is JDBC compliant. ");
00192 else
00193 System.out.println("The driver is not JDBC compliant. ");
00194 }
00195 }
00196

Topic 19 Connecting to Databases (Singhal) Page 30 of 41


00204 public static DatabaseMetaData getDatabaseMetaData(Connection Con)
00205 {
00206 if(Con == null)
00207 {
00208 JOptionPane.showMessageDialog(null,
"getDatabaseMetaData: Null Connection object passed. Program will terminate.");
throw new NullPointerException("getDatabaseMetaData: Null Connection passed");
00211 }
00212
00213 DatabaseMetaData DMMD = null;
00214 try
00215 {
00216 DMMD = Con.getMetaData();
00217 }
00218 catch(SQLException E)
00219 {
00220 JOptionPane.showMessageDialog(null,
00221 "getDatabaseMetaData:SQLException thrown");
00222 System.out.println("getDatabaseMetaData:SQLException thrown");
00223 E.printStackTrace();
00224 }
00225 return DMMD;
00226 }
00227
00235 public static boolean okToUseBatchOperation(java.sql.Connection Con)
00236 {
00237 if(Con == null)
00238 {
00239 JOptionPane.showMessageDialog(null,
"okToUseBatchOperation: Null Connection object passed. Program will terminate.");
00241 throw new NullPointerException("okToUseBatchOperation: Null Connection passed");
00242 }
00243 DatabaseMetaData DBMD = getDatabaseMetaData(Con);
00244 boolean OK = false;
00245
00246 try
00247 {
00248 OK = DBMD.supportsBatchUpdates();
00249 }
00250 catch(SQLException E)
00251 {
00252 JOptionPane.showMessageDialog(null,
00253 "okToUseBatchOperation:SQLException thrown");
00254 System.out.println("okToUseBatchOperation:SQLException thrown");
00255 E.printStackTrace();
00256 }

Topic 19 Connecting to Databases (Singhal) Page 31 of 41


00257 return OK;
00258 }
00259
00260 //end of method listLoadedDrivers
00261 }//end of class MyConnection

//Listing 19.2A
///////////////////////////////////////////////////////
00001 /*
00002 * DataBaseTest1.java
00003 *
00004 * Created on October 16, 2004, 7:14 AM
00005 */
00006 import java.sql.*;
00012 public class DataBaseTest1
00013 {
00014
00016 private DataBaseTest1() {}
00017

00023 public static void main(String[] args)


00024 {
00025 String DB_URL = "jdbc:odbc:Personal Address Book";
00026 // String DB_URL = "xyz";
00027 String UserName = "";
00028 String PassWord = "";
00029 Connection Con =
MyConnection.getMyConnection(DB_URL,UserName,PassWord);
00030 MyConnection.listLoadedDrivers();
00031 MyConnection.closeMyConnection(Con);
00032 }
00033
00034 }
//Listing 19.2B
The main methods for client use in class MyConnection (Listing 19.2A) are the static
methods getMyConnection, closeMyConnection and listLoadedDrivers.

Method getMyConnection (L19.2A #71-79)


Method takes three String arguments, database URL (URL_Str), user name
(Name), and password (Pword). If any of the three strings are null, a
NullPointerException (L19.2A #73-74) is thrown11. If non-null strings are provided
as method arguments, then the private constructor (L19.2A #56-61) is called to
create the MyConnection object MyCon that initializes the class data members

11
In a more advanced version, we may loop user through to get the valid input for the null string
values passed to the method. However that may not work in all situations.

Topic 19 Connecting to Databases (Singhal) Page 32 of 41


DB_URL, UserName, and PassWord. Next the private instance method
initializeJdbcOdbc is called (L19.2A #76). This method takes the user input for a
case if database driver other than JDBC:ODBC bridge is to be used (L19.2A #86-
88). If user clicks cancel on the popup dialog box then code lines 90-100 in Listing
19.2A are not executed and JDBC:ODBC driver is loaded by the subsequent code. If
user wishes to use a different driver then their input is error checked for zero length
string (L19.2A #93-97) in which case the default driver is loaded. If user input is not
a zero length string then setDriver method (L19.2A #99) sets the class string
member DriverPath to the user provided value.

The code line 104 in Listing 19.2A calls the method forName taking the driver path
string as argument and loads the driver. Checked exception
ClassNotFoundException is handled and client is informed if the exception is
thrown.

The last step in the process is to get a Connection object and set the class member
Con to point to it. Private instance method makeConnection is called for this
purpose (L19.2A #77).

There are several ways to make connection to the database. The method
makeConnection (L19.2A #124-142) shows all of them. The code lines for alternate
ways are commented out (L19.2A #130 & 132-133). One version of getConnection
method of DriverManager class takes the three strings – database URL, user name,
and password – as arguments and returns a Connection object (L19.2A #131).
getConnection is an overloaded method whose summary was discussed in Table
19.7. If getConnection throws an SQLException, then it is handled and user is
informed of such exception having been thrown (L19.2A #137-142). If
SQLException is not thrown then connection to database is successful and user is
given a message accordingly (L19.2A #134-135).

Finally the method getMyConnection returns the class level Connection member
Con as an object to interact with the database (L19.2A #78).

Method closeMyConnection (L19.2A #148-163)


Connection to database must be closed to release the system resources. Method close
from interface Connection does that. If user has connections to many databases,
then a call to the method closeMyConnection should be able to tell them as
connection to which database was closed. To accomplish this a call is made to the
method getCatalog (L19.2A #153), which returns a string giving the name of
Connection object (L19.2A #153). Calls to the method close or to method getCatalog
– both can throw an SQLException. If that happens then user is informed
accordingly (L19.2A #159-161).

Method listLoadedDrivers (L19.2A #167-187)


We may wish to find the following details about the loaded database drivers:
• Which drivers have been loaded?

Topic 19 Connecting to Databases (Singhal) Page 33 of 41


• What are their minor and major versions?
• Are the JDBC compliant or not?
Method listLoadedDrivers accomplishes these objectives. The getDrivers static
method of class DriverManager gets an Enumeration object for all the currently
loaded drivers. The list static method from Collections class can take an
Enumeration object as argument and returns an ArrayList object that contains the
element that were in the Enumeration object passed to it (L19.2A #169). A for loop
iterates through the ArrayList called drivers (L19.2A #170-187). The method get
would take an array index as argument and return the Object at that index (L19.2A
#172). However, since we already know that this object must be an object of type
Driver – we cast it to that form. In order to get the driver name, first we call the
method getClass, which returns the Class object for the caller. Then getName
method for a Class object returns a String with the name of the Class object
(L19.2A #174). The name of driver is then printed (L19.2A #175). Methods
getMajorVersion and getMinorVersion from Driver class return integer values
containing major and minor version for a driver respectively. The method
jdbcCompliant for a particular Driver object returns true if the driver is JDBC
compliant, else it returns false. The values obtained for major version, minor
version and fact whether the driver is JDBC compliant are printed (L19.2A #180-
186). This operation is repeated for all drivers in the ArrayList drivers.

Method getDatabaseMetaData
Before we discuss more details, we must define what is metadata? In simplest terms
the metadata are data about data. More precise terms, the metadata are data about
information bearing objects. Database is an object that may have many properties.
One simple property about database that we discussed was the data types it may
support. The client using a database from a Java program may be interested in
finding out all possible data about the database they are using. Java interface
java.sql.DatabaseMetaData has methods that can provide vast amount of
information about a database object. The Connection class has a method
getMetaData which returns an object of type DatabaseMetaData. This returned
object can be used to survey or print various properties of the database the user is
connected to. One simple example of this is that a database may have reserved
words other than the one specified by SQL92 (which is the standard SQL). The
method getSQLKeywords for the object of type DatabaseMetaData can provide one
a comma separated list of these non-standard keywords. We shall see a short
example of that soon. In order to provide the DatabaseMetaData object for a
database pertaining to certain Connection object we simply call the method
getMetaData as per syntax given on line # 216 in Listing 19.2A, where the method
call returns an object of type DatabaseMetaData. A simple example of using this
DatabaseMetaData object would be a call such as below:

Topic 19 Connecting to Databases (Singhal) Page 34 of 41


try
{
DatabaseMetaData DBMD = Con.getMetaData();
System.out.println(DBMD.getSQLKeywords());
}
catch(SQLException Sqex)
{
Sqex.printStackTrace();
}
Here the method getSQLKeywords will get the SQL keywords other than SQL92
used by the database as a comma separated list. Then println method will print then
to console. The output of the above code fragment for Microsoft Access database
using JDBC:ODBC bridge is:
ALPHANUMERIC,AUTOINCREMENT,BINARY,BYTE,COUNTER,CURRENCY,
DATABASE,DATABASENAME,DATETIME,DISALLOW,DISTINCTROW,DOUBLEFLOAT,
FLOAT4,FLOAT8,GENERAL,IEEEDOUBLE,IEEESINGLE,IGNORE,INT,INTEGER1,
INTEGER2,INTEGER4,LEVEL,LOGICAL,LOGICAL1,LONG,LONGBINARY
,LONGCHAR,LONGTEXT,MEMO,MONEY,NOTE,NUMBER,OLEOBJECT,OPTION,
OWNERACCESS,PARAMETERS,PERCENT,PIVOT,SHORT,SINGLE,SINGLEFLOAT
,SMALLINT,STDEV,STDEVP,STRING,TABLEID,TEXT,TOP,TRANSFORM,
UNSIGNEDBYTE,VALUES,VAR,VARBINARY,VARP,YESNO
In above list, notice the word CURRENCY, which is not a SQL92 standard, but is
used in Access database for the currency data type.

Method okToUseBatchOperation(L19.2#235-258)
When we discussed SQL, we showed example of execution of one SQL statement at
a time. Understand that each time you execute just one statement you have to make
a trip to the database back and forth. When large amount of data are to be added to
the database this could be slow and wasteful. Depending upon the type of driver
available a batch operation may be allowed. What that means is that user can add
all the SQL statements in a batch (details later) and then execute all of them at once.
However, before embarking on a batch operation such as this, the database driver
must allow this operation. User can find out about such situation by calling the
method supportsBatchUpdates for the DatabaseMetaData object for the database.
Method okToUseBatchOperation facilitates this for the client. The method takes the
Connection object as argument. Then it calls the static class method
getDatabaseMetaData to get the object of type DatabaseMetaData for this
Connection object. The DBMD object thus returned (L19.2#243) is then used to get
a Boolean value by calling its member method supportsBatchUpdates. If this
method returns true then the batch SQL operations are supported otherwise they
are not. The method returns the value of local variable OK accordingly. Illustration
of use of this method is made later, when we attempt batch SQL updates.

Topic 19 Connecting to Databases (Singhal) Page 35 of 41


Results of Listing 19.2
The simple Listing 19.2B performs the test to connect to a database. The database
URL, user name and password are provided (L19.2B #25-28). The method
getMyConnection from MyConnection class would take the above as arguments and
return a Connection object. However, in the process the private method
initializeJdbcOdbc is called which pops up the following dialog box for the client
(Figure 19.15A).

FIG. 19.15A
If a driver other than JDBC:ODBC bridge is needed then user would enter the
name for that in the dialog box and click OK. Otherwise user would click cancel.
The connection to database is then attempted, and if successful then the
confirmation dialog shown in Figure 19.15B is shown.

FIG. 19.15B
The dialog also informs of the database URL to which the connection is successfully
made. Now one can execute DDL and DML SQL statements with the database to
which the connection is obtained. To do this systematically, however, requires
developing another class called MyStatement, which we discuss next.

Performing DDL and DML SQL operations on the database


Once a Connection object is obtained for a database the Statement object is needed
to perform any DDL or DML operations on it. The Statement object can call

Topic 19 Connecting to Databases (Singhal) Page 36 of 41


various methods from interface12 java.sql.Statement to create tables, alter them or
perform queries on them. We develop class MyStatement to facilitate all these
operations. Figure 19.16 shows a high-level (summary) diagram for this class.

FIG. 19.16

12
One should be aware that there is also a class called Statement in the package java.beans. If both,
the class Statement and interface Statement are to be used, and then one must use their full qualified
names.

Topic 19 Connecting to Databases (Singhal) Page 37 of 41


Database Forms
Forms provide a powerful and convenient interface to the databases. The forms can
typically be used for the following database activities:
1. Add new records.
2. Find details of an existing record.
3. Delete a record.
4. Update fields (other than primary key).
5. Run select queries.
Here we give design details of a database form that is used to perform all but the
activities number three and five in the above list. Figure FYZ1 shows the schematic
layout13 of the form.
Buttons to accept
data from form or
display data.

Text boxes to enter


data or display them.

Text area to print


messages to user from
database or from
program

FIG. FYZ1
In Figure FYZ1 the portion containing buttons on the top is a panel, where pressing
different buttons accomplishes relevant purpose of data entry or display. The
middle panel has the data entry/display text fields and their labels. The lower
portion is a non-editable text area, where the messages are printed for the user from
database or from the program. An improved design may also include the text fields
for entering the user name and password and may show a progress bar to indicate
the task progress. To implement above look and feel, we design the classes with
following scheme. We design a class called ControlPanel, which shows the top part
of GUI with buttons. The responsibilities of this class are discussed in the Table
TYZ1 below.

13
It goes without saying that the best look and feel for a GUI requires a design of its own. Graphical
designer and user should jointly come up with the best GUI design and then communicate that to the
software engineer.

Topic 19 Connecting to Databases (Singhal) Page 38 of 41


Responsibilities of class ControlPanel
• Declares, instantiates, registers with ActionListeners, and add to the JPanel,
the following five JButton type objects:
1. Add
2. Find
3. Update
4. Clear
5. Help
• Does the followings for each button:
1. Set Fonts
2. Set Mnemonic
3. Set border
4. Set tool tip text
Table #TYZ1
Crucial in this application is the design of ActionListeners for the five buttons
described in the table TYZ1 above. Generally the listener objects are added in one
of the following ways:
1. The classes whose objects need them itself implement the ActionListener or
any other interface that is needed.
2. They are added either as an object of inner class or as an anonymous class.
Using either of the above methods would have made the code for class ControlPanel
too bloated. Therefore a rather unconventional technique of stand-alone classes
implementing the listeners was adapted here. The five classes, each corresponding to
one JButton object (described in the table above), each implementing the
ActionListener interface for its button were declared. TableTYZ2 below describes
the responsibilities of these classes:
Class Name Responsibility
AddRecord Instantiates the following objects that are needed to add a record to
the data table: ScrollPanel (that provides the access to all the text
fields in the form), Connection object to create Statement object
related to the database, and a JTextArea object to which any
outputs for the user can be made. Implements the actionPerformed
method to facilitate adding a record to the data table.
FindRecord Prepares the ScrollPanel, Connection, and JTextArea objects,
which in turn are used by the actionPerformed method which is the
event handler for the Find button in the GUI.
UpdateRecord Performs the same function (as above) for the Update button in the
GUI.
ClearFields Prepares the ScrollPanel object and implements the
actionPerformed method to facilitate clearing of all fields in the
database form when user presses the Clear button.
Help Prepares the JTextArea object and implements the
actionPerformed method to handle user pressing help button to get
help in using GUI.

Topic 19 Connecting to Databases (Singhal) Page 39 of 41


Table #TYZ2
Finally we need a class for the middle portion of GUI that has labels and text entry
fields in it. This class called ScrollingPanel has the following responsibility (Table
TYZ3).
Responsibilities of class ScrollingPanel
• Prepares in form of a JPanel object, the middle part of data entry GUI,
which contains the labels for data entry fields on left and fields themselves on
right.
• Assigns borders to all JLabel and JTextField components and tool tip texts
for the latter.
• Sets the colors and fonts, and other characteristics for all displayed
components.
TableTYZ3
After designing the seven classes above, we design the class AddressBookForm
which has the main method, and is the entry point to our application. Table TYZ4
below shows the inheritance and composition relationships (in terms of fields/data
members) for various classes used. In this table, the data members not shown with
full qualified name are the classes local to the application package or they are
primitives.
Class Name Inheritance relationship Data Members
AddressBookForm java.lang.Object • java.sql.Connection
AddressBookForm • ControlPanel
• javax.swing.JTextArea
• ScrollingPanel
• javax.swing.JScrollPane
• java.lang.String
• MyWindow
ControlPanel java.lang.Object Five instances of class
java.awt.Component javax.swing.JButton. One
java.awt.Container for each function shown in
top portion of Figure
javax.swing.JComponent FYZ1.

javax.swing.JPanel

ControlPanel

ScrollingPanel java.lang.Object • Five instances of


java.awt.Component javax.swing.JTextField,
java.awt.Container one for each text entry
field shown in Figure
javax.swing.JComponent FYZ1.
• An array of JLabel with
javax.swing.JPanel five members, one for each
ScrollingPanel text entry field.
• Two JPanel objects, one

Topic 19 Connecting to Databases (Singhal) Page 40 of 41


for labels and other for
text fields.
AddRecord java.lang.Object • java.sql.Connection
AddRecord implements
ActionListener
• ScrollingPanel
• javax.swing.JTextArea
• java.sql.ResultSet
• java.sql.Statement
FindRecord java.lang.Object • java.sql.Connection
FindRecord implements
• ScrollingPanel
ActionListener
• javax.swing.JTextArea
• java.lang.String
UpdateRecord java.lang.Object • java.sql.Connection
UpdateRecord
implements ActionListener
• ScrollingPanel
• javax.swing.JTextArea
ClearFields java.lang.Object ScrollingPanel
ClearFields implements
ActionListener
Help java.lang.Object javax.swing.JTextArea
Help implements
ActionListener
Table TYZ4
We now discuss the classes and their structure further.

ScrollingPanel Class
As discussed earlier, the responsibility of this class is to provide the middle part of
the form that has the text entry fields and their corresponding labels. Understand
that this class does not have the responsibility to provide intelligence to the data
entry fields. That responsibility, coupled with intelligence for buttons lies with
ControlPanel class.

Topic 19 Connecting to Databases (Singhal) Page 41 of 41


CS 23: Advanced Java

Chapter 20 : Multithreading1
Author: Satish Singhal Ph. D.
Version 1.0
When a single program can switch between different (lightweight) processes, it is
said to be a multithreaded program. Each lightweight process running in the
program is called a thread. This definition requires that we understand the concept
of “process” clearly. When an operating system (OS) executes a program, it creates
a process dedicated to it. If you would like to see all such processes running on a
Windows XP computer, then you can press Control + Alt + delete keys, and under
processes tab you would see a picture similar to the Figure 20.1.

Figure 20. 1
The process chart will include the OS (native) processes as well as the ones created
by the applications. Process for an application would create its own stack and heap
memory areas, as well as other components. Threads, which more precisely must be
called “threads of control”, do not create a separate heap. Rather all threads share

1
This chapter discusses multithreading based on Java 1.4. Java 1.5 has additional support for
multithreading in the package java.util.concurrent. At the time of this writing Java 1.5 has been
released only as a Beta version.

Topic 20 Multithreading (Singhal) Page 1 of 52


the same heap. Threads exist in the user’s program, as opposed to the process
which exists at the level of operating system. A schematic view of a two thread
application’s (or program’s) process is shown by Figure 20.2.

Figure 20.2
The above figure shows us a process, as it would be executed by the operating
system. The part of the process which is enclosed in the dotted line box is called a
thread. Each thread has its own stack, stack pointer, and program counter.
However all threads would share the same heap, and may share the resources in the
miscellaneous category. Because more than one thread would share the same heap,
care is required when writing multithreaded applications so that state of heap is not
corrupted by one thread. Program counter simply keeps track of the line number in
the binary code being executed for a certain thread.

Why would one need threads in an application? Imagine that your program is
waiting for user to input some data, or for a server to open a connection. This “wait
time” can be put to better use by attending to some other tasks in the program. An
excellent example of this is when you open a web browser. All the images and other
components in the web page open up simultaneously, controlled by many threads in
the browser process. In this sense it would appear that threads are doing
multitasking. However, threads are lightweight processes as they only give us an
illusion of multitasking. Two threads can be doing some program task
simultaneously or one thread may be inactive, while other is doing something.

Topic 20 Multithreading (Singhal) Page 2 of 52


However, multithreading2 is not multitasking. In multitasking the operating system
time shares central processing unit (CPU) of the computer between various
processes. Based on a scheduling algorithm, OS would attend to one task, while put
the other tasks to sleep preserving their state and letting them hibernate. We shall
come back to some more details regarding scheduling shortly. However, we wish to
show as how to create threads in a Java program.
Creating Threads
You are already aware of at least one thread in each program you have written so
far. Execution always begins with the first line of main method of entry point class.
Main method is one of the threads in every Java program. When we show a
graphical user interface, we may write a code similar to the one given below (Listing
20.1).
public class SimpleSwing {
public static void main(String[] args)
{
System.out.println ("Start of main thread.");
JFrame JF = new JFrame ("Start of Swing Thread");
JF.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JF.setSize(500,500);
JF.setVisible(true);
System.out.println ("End of main thread.");
}
}//Listing 20.1
This program will show a simple window. However, while the window is showing on
the console, the program will print the following two statements:

Start of main thread.


End of main thread.

You would see that even though the end of main has reached, the Window shown by
the program does not shut down. The reason is that window is showing in its own
“thread of control” called a swing thread. Therefore you may surmise each Java
program displaying a swing component to be a multithreaded program. However, at
times we may wish to create other threads of control in a Java program. Now we
describe how to accomplish that.

There are two techniques for creating threads in a Java application.


• Extend the class java.lang.Thread
• Implement the interface java.lang.Runnable
First technique is used if the class which must run as a thread is not already
extending some other class. The syntax is rather simple. Imagine we need to create a
thread called MomThread, which is a stand-alone class. In that case the syntax to
make it a thread object is:
2
Multithreading, sometimes is also called as concurrent programming as many threads work to
utilize application resources concurrently.

Topic 20 Multithreading (Singhal) Page 3 of 52


public class MomThread extends Thread
{
//code. (Minimal code required is to override method called run).
}
On the other hand if a class is already extending another class, then it can be made
thread-able by implementing the interface Runnable as follows:

public class DadThread extends DummyClass implements Runnable


{
//code. (Minimal code required is to implement method called run).
}

The minimal code that is needed in both above thread-able classes is to override the
base class method called run in the MomThread class, and implement the same
name method in the DadThread class. Needless to say that interface Runnable only
has one method called run, which must be implemented by the concrete class
implementing this interface. The class Thread also implements the interface
Runnable. Table 20.1 gives a bird’s eye view of the Thread class architecture.
Method/entity Data types or Methods signatures
type
public data static int MAX_PRIORITY , MIN_PRIORITY ,
members NORM_PRIORITY;
Thread()
Thread(Runnable target)
Thread(Runnable target, String name)
Thread(String name)
Constructors Thread(ThreadGroup group, Runnable target)
Thread(ThreadGroup group, Runnable target, String name)
Thread(ThreadGroup group, Runnable target, String name,
long stackSize)
Thread(ThreadGroup group, String name)
int activeCount()
Thread currentThread()
void dumpStack()
int enumerate(Thread[ ] tarray)
Static methods boolean holdsLock(Object obj)
boolean interrupted()
void sleep(long millis)
void sleep(long millis, int nanos)
void yield()

Topic 20 Multithreading (Singhal) Page 4 of 52


void checkAccess()
int countStackFrames()
void destroy()
ClassLoader getContextClassLoader()
String getName()
int getPriority()
ThreadGroup getThreadGroup()
void interrupt()
boolean isAlive()
Instance boolean isDaemon()
methods boolean isInterrupted()
void join()
void join(long millis)
void join(long millis, int nanos)
void setContextClassLoader(ClassLoader cl)
void setDaemon(boolean on)
void setName(String name)
void setPriority(int newPriority)
void start()
String toString()
Table 20.1
Instantiating and running threads
Instantiation of objects of classes deriving from class Thread is done simply by
calling their constructor, such as:

Thread Mom1 = new MomThread ( );

On the other hand if a class was made thread-able by implementing the interface
Runnable, its object is to be passed to the constructor of class Thread as below.

Thread Dad1 = new Thread (new DadThread ());

Though all thread-able classes3 have a method called run, this method is NEVER
called directly to run a thread. Rather a method name start (from super-class
Thread) is called to execute the code contained in the run method. Therefore the
syntax for executing a thread is as follows:

3
We are calling the classes that can be used as threads as thread-able. However, since all threads
implement the interface Runnable, it is common also to call the Threads as Runnable. On the other
hand the term runnable is also used for threads, only when thread is available to execute its run
method. Therefore we introduce this new term thread-able, which indicates that the Java class either
inherited from Thread or implemented the Runnable interface.

Topic 20 Multithreading (Singhal) Page 5 of 52


Mom1.start ( );
Dad1.start ( );

The reason that run method is not called directly to start a thread execution is
because in that case a thread object no longer acts as a thread of control. Calling
run method directly makes it a sequential and non-threaded call. First we show an
example where we have two (counting the main, actually three threads) almost
independent threads in one program, which means that they are not sharing the
same program data or objects (Listing 20.2). Purpose of this Listing is to show the
syntactic elements of using Java threads.

public class MomThread extends Thread


{
public void run()
{
for ( int count = 0; count < 4; count++)
System.out.println( "Message " + (count+1) + " From: Mom" );
}
}
//Listing 20.2 A
public class DummyClass
{
public DummyClass( ) { }
}
//Listing 20.2 B
public class DadThread extends DummyClass implements Runnable
{
public void run()
{
for ( int count = 0; count < 4; count++)
System.out.println( "Message " + (count + 1) + " From: Dad");
}
}
//Listing 20.2 C
public class TestIndependentThreads
{
public static void main(String[] args)
{
System.out.println ("*********Starting the main thread!!!!");
//Call one of the test methods i.e. test1, test2, test3, or test4
System.out.println ("**********Ending the main thread!!!!");
}
private static void test1()
{
//code

Topic 20 Multithreading (Singhal) Page 6 of 52


}

private static void test2()


{
//code
}
private static void test3()
{
//code
}
private static void test4()
{
//code
}
}
//Listing 20.2 D
The run method of two thread-able classes runs a loop four times and prints a
message from the MomThread or DadThread as the case may be.
We write four test methods called test1, test2, test3, and test4 to show behavior of
the simple multithreaded program of Listing 20.2. In addition we run these
programs on two different computers. The computer 1 being a single threaded
single processor machine, whereas the computer 2 being a hyper-threaded4 single
processor machine. Table 20.2 shows the results from executing various test
methods.

Test method called in main Output on Computer 1 Output on Computer 2


private static void test1(){ Always same as below Some variation of pattern below
Thread Mom1 = new MomThread(); *********Starting the main *********Starting the main
Runnable Dad = new DadThread(); thread thread!!!!
Thread Dad1 = new Thread(Dad); Starting the Mom thread. Starting the Mom thread.
System.out.println( Starting the Dad thread. Starting the Dad thread.
"Starting the Mom thread."); **********Ending the main **********Ending the main
Mom1.start(); System.out.println( thread thread!!!!
"Starting the Dad thread."); Message 1 From: Mom Message 1 From: Mom
Dad1.start(); Message 2 From: Mom Message 1 From: Dad
} Message 3 From: Mom Message 2 From: Mom
Message 4 From: Mom Message 2 From: Dad
Message 1 From: Dad Message 3 From: Mom
Message 2 From: Dad Message 3 From: Dad
Message 3 From: Dad Message 4 From: Mom
Message 4 From: Dad Message 4 From: Dad
private static void test2() Always same. No variation Run #1
{ *********Starting the main *********Starting the main
Thread Mom1 = new MomThread(); thread!!!! thread!!!!
Mom1.setPriority(10); The priority of Mom1 = 10 The priority of Mom1 = 10
System.out.println("The priority of “ + The priority of Dad1 = 2 The priority of Dad1 = 2
” Mom1 = " + Mom1.getPriority()); Starting the Dad thread. Starting the Dad thread.

4
A hyper-threaded CPU acts like two logically CPU in one physical CPU. Therefore it will act almost
like two CPU in one. Details of hyperthreading technology can be searched at www.intel.com

Topic 20 Multithreading (Singhal) Page 7 of 52


Runnable Dad = new DadThread(); Starting the Mom thread. Starting the Mom thread.
Thread Dad1 = new Thread(Dad); Message 1 From: Mom Message 1 From: Dad
Dad1.setPriority(2); Message 2 From: Mom Message 2 From: Dad
System.out.println("The priority of” + Message 3 From: Mom Message 1 From: Mom
“ Dad1 = " + Dad1.getPriority()); Message 4 From: Mom **********Ending the main
System.out.println ( **********Ending the main thread!!!!
"Starting the Dad thread."); thread!!!! Message 2 From: Mom
Dad1.start(); Message 1 From: Dad Message 3 From: Dad
System.out.println( Message 2 From: Dad Message 3 From: Mom
"Starting the Mom thread."); Message 3 From: Dad Message 4 From: Dad
Mom1.start(); Message 4 From: Dad Message 4 From: Mom
}
Run#3
*********Starting the main
thread!!!!
The priority of Mom1 = 10
The priority of Dad1 = 2
Starting the Dad thread.
Starting the Mom thread.
**********Ending the main
thread!!!!
Message 1 From: Mom
Message 2 From: Mom
Message 1 From: Dad
Message 3 From: Mom
Message 2 From: Dad
Message 4 From: Mom
Message 3 From: Dad
Message 4 From: Dad
private static void test3() Result is always same. There is no Slight variation in the type of output
{ variation below.
Thread Mom1 = new MomThread(); *********Starting the main *********Starting the main
Mom1.setPriority(10); thread!!!! thread!!!!
System.out.println("The priority of The priority of Mom1 = 10 The priority of Mom1 = 10
Mom1 = " + Mom1.getPriority()); The priority of Dad1 = 2 The priority of Dad1 = 2
Runnable Dad = new DadThread(); Starting the Mom thread. Starting the Mom thread.
Thread Dad1 = new Thread(Dad); Message 1 From: Mom Starting the Dad thread.
Dad1.setPriority(2); Message 2 From: Mom Message 1 From: Mom
System.out.println("The priority of Message 3 From: Mom Message 2 From: Mom
Dad1 = " + Dad1.getPriority()); Message 4 From: Mom Message 3 From: Mom
System.out.println( Starting the Dad thread. **********Ending the main
"Starting the Mom thread."); **********Ending the main thread!!!!
Mom1.start(); thread!!!! Message 1 From: Dad
System.out.println( Message 1 From: Dad Message 4 From: Mom
"Starting the Dad thread."); Message 2 From: Dad Message 2 From: Dad
Dad1.start(); Message 3 From: Dad Message 3 From: Dad
} Message 4 From: Dad Message 4 From: Dad

private static void test4() *********Starting the main *********Starting the main
{ thread!!!! thread!!!!
Thread Mom1 = new MomThread(); Running (not starting) the Mom Running (not starting) the Mom
System.out.println( thread. thread.
"Running (not starting) the Mom “ + Message 1 From: Mom Message 1 From: Mom
“ thread."); Message 2 From: Mom Message 2 From: Mom
Mom1.run(); Message 3 From: Mom Message 3 From: Mom
System.out.println("The priority of Message 4 From: Mom Message 4 From: Mom
Mom1 = " + Mom1.getPriority()); The priority of Mom1 = 5 The priority of Mom1 = 5
Runnable Dad = new DadThread(); Running (not starting) the Dad Running (not starting) the Dad
Thread Dad1 = new Thread(Dad); thread. thread.
System.out.println ( Message 1 From: Dad Message 1 From: Dad

Topic 20 Multithreading (Singhal) Page 8 of 52


"Running (not starting) the Dad + Message 2 From: Dad Message 2 From: Dad
“ thread."); Message 3 From: Dad Message 3 From: Dad
Dad1.run(); Message 4 From: Dad Message 4 From: Dad
System.out.println("The priority of The priority of Dad1 = 5 The priority of Dad1 = 5
Dad1 = " + Dad1.getPriority()); **********Ending the main **********Ending the main
} thread!!!! thread!!!!
Table 20.2
Before we discuss the results of Table 20.2, let us discuss something called priority
for a thread. You would recall that three public data members of Thread class are:
MAX_PRIORITY, MIN_PRIORITY, and NORM_PRIORITY. Java assigns the
priority to threads bases on a scale of one to ten. Thus constants MIN_PRIORITY,
NORM_PRIORITY, and MAX_PRIORITY, respectively have values zero, five, and
ten. When a thread is created by another thread, then initially its priority is same as
the thread that created it. For example in Listing 20.2D, when the main thread
would call one of the test methods from Table 20.2, it would create threads Mom1
and Dad1. Their priority would be same as that of main thread. The main thread is
always started with normal priority, i.e. a priority of five. The method getPriority of
Thread class can print the current priority of a thread, whereas the method
setPriority can assign a higher or lower priority value, compared to the one assigned
previously. For example in test methods shown in Table 20.2, adding a statement
such as below can print the current priority level for a thread:

System.out.println ("The priority of Dad1 = " + Dad1.getPriority ());

JVM will run a high priority thread as long as it is “runnable”. Once it becomes
non-runnable, then it would run a lower priority thread. A thread is runnable as
long as it is not blocked in some way. We discuss what makes a thread non-runnable
soon when we discuss various mechanisms that can manifest in the life of a thread.

In test1, both Mom and Dad threads have same priority (of five) because they are
created by main method, which also has a priority of five. The Mom thread is
started first. In computer 1, all four loop iterations from the Mom thread are
finished first, and then the run method of Dad thread is executed. Notice that in all
cases except for the test4, signified by the output “**********Ending the main
thread!!!!” the main method ends while other two threads keep running. In
computer 2, the second logical CPU picks up the execution of Dad thread and the
output from two threads becomes intermixed, as both threads are executed in
parallel.

In test2 we set the priority for Mom thread at ten and that for the Dad thread at
two. However, we start the Dad thread first. As indicated from the result for the
computer1, starting low priority Dad thread first had no affect. The JRE picks up
the execution of high priority Mom thread first and finishes it, and then finishes the
execution of low priority Dad thread. In test2 the results on computer 2 show drastic
variations in results patterns. In run#1 Dad thread starts execution first, even
though it is a low priority thread. In run#3 Mom thread execution starts first. In all
runs, the output and execution of both threads is intermixed. A bit later we would

Topic 20 Multithreading (Singhal) Page 9 of 52


show that in multi-processor machines and also on hyper-threaded CPU’s, JRE
binds program threads to as many “native threads” or “kernel threads” it can.

In test3, the priorities of Mom and Dad threads are same as they were in test2.
However, this time we start the high priority Mom thread first. The output on
computer 1 is identical to test2. JRE starts the high priority Mom thread first and
then finishes the low priority Dad thread. For computer 2 the output from Mom
thread always starts first, and then the output from both threads gets intermixed,
showing some parallel processing.

In test4, we do not call start method to start the thread execution. Rather we call the
run method directly for both threads. Doing so results in a non-threaded sequential
execution of all program code lines and results for both computers are identical.

We can make following conclusions. In all runnable threads, in a single processor,


single threaded CPU, the highest priority thread is run first ignoring the sequence in
which the threads were started. Understand that JVM does not guarantee to time
slice all runnable threads. It may do so, but it does not guarantee that. If a high
priority thread hogs the single threaded, single processor CPU, then all other
threads will suffer so called “starvation”. Therefore one should avoid doing thread
scheduling based on relative priorities of threads in a Java program.

In hyper-threaded CPU or multiple CPU computers, threads of lower and higher


priority may run in parallel. The scheduling and time slicing of threads in this case
is done by binding the program threads with the native or kernel threads. We
discuss this, along with the subject of thread scheduling below.

Thread Scheduling
When JVM needs to switch between threads of control it must use a scheduling
algorithm to do so. There are two types of scheduling algorithms in vogue. These
are:
• Pre-emptive Scheduling, and
• Cooperative Scheduling

In pre-emptive scheduling the scheduler is empowered to stop a process at some


suitable point and freeze its state. Then scheduler will take another frozen or new
process and run it. In this manner, no single process monopolizes the CPU time.
Windows NT, XP, 2000, 9X, etc., all use pre-emptive scheduling.

On the other hand in cooperative scheduling, the operating system is a passive


bystander, allowing a process to finish itself, and then let another process run. This
was used in Windows 3.1, which could not do multitasking.

A thread scheduling algorithm can be written to be pre-emptive or cooperative. In


Java the type of scheduling done by JVM depends upon the particular
implementation of JVM. One can indeed design different types of JVM and choose

Topic 20 Multithreading (Singhal) Page 10 of 52


different thread scheduling algorithms in them. At least in this sense, Java is not
truly platform independent.

Older Java Runtime environment (JRE) provided by Sun used only so called
“Green Threads5”. Use of green threads allowed multithreading at the application
level, where JRE and user program managed the thread scheduling. However, to
operating system JRE is just one process. Therefore if machine has multiple CPU’s,
the green thread implementation could not take advantage of running your Java
application on multiprocessors simultaneously (thus achieving true multitasking
and parallel processing). In that case multithreading would speed up only those
Java applications, where one or more threads were blocked for long time or were
waiting for user input.

Sun realized this limitation, and made improvement in later JVM implementations,
where a multithreaded Java application could actually use thread scheduler
available on the operating system. Such threads are called native threads (or kernel
threads). For example, Sun’s Solaris operating system allows multiple CPU’s. One
can run a multithreaded Java application on Solaris with improved speed by using
its multiple CPU’s. For a Java program to use the native threads for an OS requires
a binding between “user or application threads” and operating system “native
threads”. Figure 20.3 shows schematics of such binding.

Or
native
threads

FIG. 20.3
In above Figure, the tasks one, two and three contain one or more threads in various
user programs running on the computer. The lightweight process resulting from
threads binds to kernel threads, which are threads at the operating system level.
Then these kernel threads bind to various CPU’s on the computer. One can debate
5
Green threads use so called fixed priority scheduling, where a threads are executed based on their
priority.

Topic 20 Multithreading (Singhal) Page 11 of 52


whether a single CPU, single threaded system would afford any speed improvement
in a multithreaded Java program unless it was doing parallel processing in the time,
where one or more threads were blocked or were waiting for some input.

It is clear now that pre-emptive scheduling has the advantage of not hogging CPU
entirely (the way cooperative scheduling does). One may then wish to adapt pre-
emptive scheduling for the threads in their Java application, which would allow
time slicing various thread executions. Before we discuss thread scheduling further,
we shall learn some more details about life cycle of threads and events that can take
place in their life.

Thread life cycle and events


The thread states and events are shown by Figure 20.4. Sleep, wait, and blocked
for I/O would make a
thread non-runnable.

Figure 20.4
A thread can have following states: Thread can become runnable
1. New thread again by elapse of sleep time,
2. Runnable or yielded by being notified that wait is
3. Not Runnable (non-runnable) over, or when I/O is over.
4. Dead
The thread is in new state just after the constructor call has been made to create it.
The events in thread’s life are changes in its state that are brought about by calling
one of its methods or sending a message to it. For example:
1. A new thread becomes runnable by calling its start method.
2. A thread becomes dead when it’s run method exits. In older Java
implementation a stop method could be called to kill a thread. However, the
use of stop was considered unsafe; therefore stop has been deprecated now.
In current technology a thread must plan its own death by gracefully exiting
from its run method.

Topic 20 Multithreading (Singhal) Page 12 of 52


3. Calling yield method on a thread keeps it in runnable state, however it would
temporarily yield control to another thread.
4. A thread would become non-runnable when:
1. It is put to sleep by calling sleep method on it.
2. When the wait method is called on thread. Wait is only over when some
condition is satisfied.
3. Thread is blocked because of some input or output (I/O blocking).

A thread can go back and forth between runnable and non-runnable states. The
escape routes from non-runnable to runnable states depend upon the process by
which the thread got into non-runnable state in the first place. For example:
1. If a thread became non-runnable because it was put to sleep by calling sleep
method, then time specified by sleep method must elapse for it to become
runnable again.
2. If a thread was made non-runnable by calling its wait method, then it could
become runnable after another object notifies it that wait is over and wait
condition has been satisfied. This notification is sent by using methods notify
or notifyAll. Understand that methods wait, notify, and notifyAll are final
methods from Object class ready for use.
3. If thread becomes non-runnable because it was blocked for I/O, then it
becomes runnable when I/O block is over.

Inducing time slicing by using thread sleeping


From the results of test methods in Table 20.2 we saw that on a single
threaded/single processor (STSP) computer time slicing was never accomplished.
This was because if two threads had same priority, then the thread that started first
took over execution till its run method exited. Otherwise the thread with highest
priority took over, irrespective of how many threads were in runnable state. Time
slicing and some degree of parallel processing can be induced in STSP machines by
making threads sleep for some length of time, allowing other threads to execute in
that duration. As mentioned earlier, a thread is put to sleep by calling its overloaded
sleep method. As shown by signatures of sleep method in Table 20.1 a thread can be
put to sleep for fixed number milliseconds or for some combination of milliseconds
and nanoseconds. To make a thread sleep we write a simple method as below:

public static void goToSleep(long millis)


{
try
{
Thread.currentThread().sleep(millis);
}
catch(InterruptedException Irex)
{
Irex.printStackTrace();
}

Topic 20 Multithreading (Singhal) Page 13 of 52


}
We just call this static method inside the run method of the Dad and Mom thread to
make them sleep for millis length of time. Understand that sleep method throws a
checked exception InterruptedException, which must be caught or thrown. In
code line,

Thread.currentThread().sleep(millis);

Gets the current Makes the current thread


thread. sleep for millis number of
milliseconds

the portion Thread.currentThread( ) calls the currentThread static method of


Thread class to get the current thread. Then instance method sleep put that thread
to sleep for millis number of milliseconds. Threads can also be put to sleep by a
direct call to sleep method. We modify the codes for run methods of MomThread
and DadThread as follows in Listing 20.2.

public void run()


{
for (int count = 0; count < 4; count++)
{
System.out.println ( "Message " + (count+1) + " From: Mom" );
System.out.println ("Mom thread going to sleep.");
TestIndependentThreads.goToSleep (5000);
}
} Also added to the run
method of DadThread
class.

Above modification would make each thread sleep for 5000 milliseconds at the end
of one loop iteration. Table 20.3 shows the results for the test methods test1, test2,
and test3 for the STSP machine. The time slicing and parallel processing that was
missing earlier is now induced.

Test method (See code in Table 20.2) Typical output from STSP machine
test1 *********Starting the main thread!!!!
Starting the Mom thread.
Starting the Dad thread.
**********Ending the main thread!!!!
Message 1 From: Mom
Mom thread going to sleep.
Message 1 From: Dad
Dad thread going to sleep.

Topic 20 Multithreading (Singhal) Page 14 of 52


Message 2 From: Mom
Mom thread going to sleep.
Message 2 From: Dad
Dad thread going to sleep.
Message 3 From: Mom
Mom thread going to sleep.
Message 3 From: Dad
Dad thread going to sleep.
Message 4 From: Mom
Message 4 From: Dad
Mom thread going to sleep.
Dad thread going to sleep.
test2 *********Starting the main thread!!!!
The priority of Mom1 = 10
The priority of Dad1 = 2
Starting the Dad thread.
Starting the Mom thread.
Message 1 From: Mom
Mom thread going to sleep.
**********Ending the main thread!!!!
Message 1 From: Dad
Dad thread going to sleep.
Message 2 From: Mom
Mom thread going to sleep.
Message 2 From: Dad
Dad thread going to sleep.
Message 3 From: Mom
Mom thread going to sleep.
Message 3 From: Dad
Dad thread going to sleep.
Message 4 From: Mom
Mom thread going to sleep.
Message 4 From: Dad
Dad thread going to sleep.
test3 *********Starting the main thread!!!!
The priority of Mom1 = 10
The priority of Dad1 = 2
Starting the Mom thread.
Message 1 From: Mom
Mom thread going to sleep.
Starting the Dad thread.
**********Ending the main thread!!!!
Message 1 From: Dad
Dad thread going to sleep.
Message 2 From: Mom
Mom thread going to sleep.
Message 2 From: Dad
Dad thread going to sleep.
Message 3 From: Mom
Mom thread going to sleep.
Message 3 From: Dad
Dad thread going to sleep.
Message 4 From: Mom
Mom thread going to sleep.
Message 4 From: Dad
Dad thread going to sleep.
Table 20.3
Understand that in STSP machines time slicing introduced by above technique may
not speed up the multithreaded program. However, this is one way in which threads

Topic 20 Multithreading (Singhal) Page 15 of 52


scheduling can be done and some sort of parallel processing can be accomplished.
As indicated before, in STSP machines speed improvements could only be made
when some thread is blocked for I/O or to open network connections, availing this
wait time to do something else that is useful.

Object sharing and Synchronization


The threads we have discussed so far are independent threads. That means that
their actions are as independent as of two stand-alone programs. Often however,
two threads may need to change the state of same object at different times. Consider
for example a bank account object inside the information system for a bank.
Assume it is a checking account, where the account holder could make deposits and
withdrawals, and bank at the end of month deducts the monthly fee. We could write
the withdraw method for the bank account object as follows:

public boolean withdraw (int amount)


{
if(balance >= amount)
{
balance -= amount;
return true;
}
return false;
}

Under normal examination, the above method works fine as it ascertains that
withdrawal is not done if balance is not equal or higher than amount being
withdrawn. Now imagine the situation that two threads – one initiated by the
customer to withdraw money, and other by the bank to deduct monthly fee are
initiated at the same time. Assume that at that time the balance is $25. The thread
that withdraws the money wishes to withdraw $20 from it, and the thread that needs
to charge a $20 monthly fee also needs to deduct the same amount. Assume that
program is running on a STSP computer, and the following happens. The customer
money withdrawal thread performs the following check:

if (25>=20)

At that instant the pre-test condition is true, thus customer thread enters the block
under the scope of if condition. However, assume that before customer thread can
actually set the balance down to $5 , the monthly fee thread tests the pre-condition
and still finds it true and gets the permission to execute the code inside the if block.
In this case the timing of both threads is arranged such that both of them would get
to deduct $20 from the balance, thus leaving the balance of -15, which would violate
the invariant of the bank account class. (You would recall from earlier chapters, the
invariant for bank account class is that balance can never become negative). This
condition in software, where the state of an object or other class variables is

Topic 20 Multithreading (Singhal) Page 16 of 52


corrupted because of uncontrolled access by more than one threads is called
“racing” or “race” condition. We must emphasize here that if you test run a
multithreaded program that can fall prey to racing, with in practically feasible test
conditions the racing bug never manifest itself. In that sense racing bugs are
absolutely sinister. In fact the failure of North American power grid in summer of
2003, which left 50 million clients with out power has been traced to a bug causing
racing condition in a C++ multithreaded program. Sidebar 20.1 discusses some of
the details of this colossal engineering disaster.

Sidebar 20.1 Racing condition and blackout bug


After auditing four million lines of code in software system called XA/21 designed
by GE Energy system, it was found that a multithreaded C/C++ program caused
racing condition in this system that was installed at First Energy of Ohio power
plants. In this failure, several processes (threads) were contending to get write
access to the “same” data structure. That eventually allowed a combination of read
and write error in that data structure allowing an alarm event application getting
into an infinite loop and spinning. This degraded the plant operator’s ability to
detect an impeding failure, leading to the biggest power grid failure in North
America. Needless to say that badly written Java multi-threaded programs are not
immune to similar types of racing conditions and failures. If you would like to read
more details about this software failure, then search at www.google.com with
keywords blackout bug or XA/21 bug.

With respect to our discussion of withdraw method, what is needed to prevent this
invariant violating situation and racing is to arrange the action of threads using the
bank account object that while one thread is using the method withdraw, the object
is “locked” to all other threads, thus allowing the withdraw method to run to
completion. Java allows this locking by using the keyword synchronized in the
header of a method. Thus the method withdraw must be modified as follows:

public synchronized boolean withdraw(int amount)

Designation of instance or static methods synchronized is termed generically as


synchronization. To illustrate the problem due to lack of synchronization Listing
20.3 shows four classes, BankAccount, Customer, AccountManager, and
TestSynchronization. For the sake of simplicity of illustration, we keep the code in
all classes to a bare minimum.
public class BankAccount
{
private int balance ;
public BankAccount(int init)
{
balance = init;
}

Topic 20 Multithreading (Singhal) Page 17 of 52


public boolean withdraw(int amount)
{
if(balance >= amount)
{
pause( );
balance -= amount;
return true;
}
return false;
}
public static void pause()
{
try
{
Thread.currentThread().sleep(5000);
}
catch(InterruptedException Irex)
{
Irex.printStackTrace();
}
}
public String toString()
{
return "The current balance = " + balance;
}
}
//Listing 20.3A
public class Customer extends Thread
{
private BankAccount Account;
public Customer(BankAccount Act)
{
Account = Act;
}

public void run()


{
Account.withdraw(20);
System.out.println ("From Customer: " + Account);
}
}
//Listing 20.3B
public class AccountManager extends Thread
{
private BankAccount Account;

Topic 20 Multithreading (Singhal) Page 18 of 52


public AccountManager(BankAccount Act)
{
Account = Act;
}

public void run()


{
Account.withdraw(20);
System.out.println("From Account Manager: " + Account);
}
}
//Listing 20.3C
public class TestSynchronization
{
public static void main(String[] args)
{
BankAccount Act = new BankAccount(25);
Customer Cust = new Customer(Act);
AccountManager AM = new AccountManager(Act);
Cust.start( );
AM.start( );
}
}
//Listing 20.3D
The class BankAccount has a private int data member called balance. The
constructor takes the initial balance (init) as argument, and sets the balance equal to
it. The method withdraw is similar to the one we described earlier in this section.
However, we call the method pause inside the if block to slow down the execution of
program. With modern day fast computers, we may need to invoke the program
infinite times to see that in some conditions the invariant was indeed violated.
Therefore deliberate slowing down of the program will dramatize the invariant
violation easily. Basically we would like to ascertain that condition (balance >=
amount) would be found true by both threads that try to call method withdraw on a
BankAccount object. The method pause makes the thread using the BankAccount
object and calling its method withdraw sleep for 5000 milliseconds.

The classes Customer and AccountManager both extend the Thread class, and have
BankAccount as the private datum. The constructor for both takes a BankAccount
object as argument, and initializes the class datum to it. The run method of both
classes calls the withdraw method on its BankAccount object, and in each case tries
to withdraw $20 from the balance, and then print the balance after the call to
withdraw method.

The class TestSynchronization creates a BankAccount object Act, with initial


balance of $25. Then it creates threads Cust, and AM, the first being an object of

Topic 20 Multithreading (Singhal) Page 19 of 52


class Customer, and second of AccountManager. Both threads take the object Act as
argument, so that their run methods can use that same object. Then main method
starts both threads. Figure 20.5 shows the output for a STSP computer.
From Customer: The current balance = 5
From Account Manager: The current balance = -15
Fig. 20.5
As discussed earlier, this is an expected result causing the violation of BankAccount
class invariant. The results from a multithreaded CPU would vary from run to run
as that depends upon how two threads Cust and AM bonded to the kernel threads
during a particular program run. However, even there the result of Figure 20.5
would be seen if many program runs are performed. Worst part is that in case such
as this, the results on a multithreaded CPU would be unpredictable. There is a
definition of software bug that even companies like Microsoft wish to impress upon
the user. They insist that “bug” must be reproducible in all program runs. Here is a
bug, which is a bug for sure, but it would not be reproducible consistently on a
multithreaded CPU.

What is needed for correct functioning of method withdraw of BankAccount class is


that the BankAccount object, which is sought by several threads, is “locked” when
its withdraw method is being called by one thread, thus ascertaining that method
completes execution. Such arrangement in software engineering is called imparting
“thread safety” to the method or making the method “thread safe”. In old days this
was done by using program constructs called “semaphores”. The critical region of
the program would be placed between method calls that would ascertain that this
region is executed in entirety by one thread only. Java provides the keyword
synchronized to lock an object to one thread at a time for the purpose of executing
the synchronized instance methods. Therefore if we replace the header of method
withdraw in BankAccount class by the one below (adding the word synchronized),
the problem is solved, and BankAccount invariant would be preserved.

public synchronized boolean withdraw (int amount)

To shape the program output better, we make slight modifications to the run
methods of both Customer, and AccountManager classes as shown in Listing 20.4.
public class Customer extends Thread
{
//Rest of code is identical to Listing 20.3B. Modified run method is shown below
public void run()
{
if(Account.withdraw(20))
System.out.println("From Customer: " + Account);
else
System.out.println("Withdrawal failed");
}
}

Topic 20 Multithreading (Singhal) Page 20 of 52


//Listing 20.4A
public class AccountManager extends Thread
{
//Rest of code is identical to Listing 20.3C. Modified run method is shown below
public void run()
{
if( Account.withdraw(20))
System.out.println("From Account Manager: " + Account);
else
System.out.println ("Account fee deduction failed.");
}
}
//Listing 20.4B
Figure 20.6 shows the output from the main of TestSynchronization class on a STSP
computer.
From Customer: The current balance = 5
Account fee deduction failed.
FIG. 20.6
For a multithreaded CPU the output would be similar, though the order of output
may alter. Thus synchronized version of withdraw method ascertains that in
multithreaded environment the invariant for a BankAccount object is preserved
and racing condition is avoided.

How does synchronization works?


The execution of threads in Java is synchronized by the “locks” called monitors6.
JRE assigns a monitor to each object and this monitor shadows the object like a
guardian angel. When more than one thread seeks to call synchronized instance
methods on the “same” object, JRE would give the ownership of the monitor for
that object only to one thread at a time. The thread possessing the monitor can now
complete the synchronized method calls. While monitor is in possession of one
thread, all other threads seeking that monitor must wait for it to become free.
Consider this similar to the situation when you go to use the restroom on a gas
station, where the clerk keeps the key to restroom. If restroom is not being used,
then the clerk gives you the key. You use the key to get in and lock the door from
inside, and while you are in, all others wanting to use it must wait. When you are
finished, you hand over the key back to clerk, and now clerk can give the restroom
keys to next waiting patron. In this analogy, restroom is the object, key is the
monitor for that object, and patrons wishing to use the restroom are threads waiting
to execute some code on it, and clerk is JRE.

Only one thread can call the synchronized method on an object at a time, and all
others are blocked in the interim. However, there are no such limitations placed on
the non-synchronized methods of an object. If an object has more than one

6
Purists however insist that locks and monitors are different things.

Topic 20 Multithreading (Singhal) Page 21 of 52


synchronized methods, then only one of them can be executed at a time on that
object. The derived classes of a class can override synchronized methods and they
are under no obligation to make the overridden method also synchronized.

Static methods can be declared synchronized even though they only deal with local
variables and static class members. For example there is a design pattern called
singleton. The characteristic of a class that adheres to singleton pattern is that in
one program execution only one of its instances can exist. For example there was
only one Elvis Presley, therefore class Elvis must be written in such a way that never
two or more instances of Elvis be created in a program. Listing 20.5 shows a way of
doing that.
public class Elvis
{
private static Elvis Instance;
private Elvis()
{
//constructor code
}
public static Elvis getElvis()
{
if (Instance == null)
Instance = new Elvis();
return Instance;
}
}
//Listing 20.5
Now imagine the following scenario: the first thread calling getElvis, testing the if
condition would find Instance to be null, as all class level object references are
initialized so. Therefore this thread will get inside the if block to execute the code to
create only one Elvis instance that should be. However similar to BankAccount case,
if timing of two threads calling the getElvis method is arranged such that before
first thread can execute the code line
Instance = new Elvis ();
another thread also calls getElvis and tests if condition inside it and finds it to be
true and gets the permission to execute the code in the scope of if block. Then
impossible would take place. We would have two Elvis, instead of one-and-only-one
Elvis. Making the method getElvis synchronized would solve this problem. Thus the
correct signature of method getElvis must be:

public static synchronized Elvis getElvis ()


Therefore synchronization of a static factory method for a class that must be a
singleton is one way to accomplish the goal of it being singleton. Understand that
static methods do not belong to a single class object. Therefore they do not use the
same monitors that calling instance method would use. For example the call to
getElvis could be made as follows:

Topic 20 Multithreading (Singhal) Page 22 of 52


Elvis Great_Elvis = Elvis.getElvis ( );

How does JRE locks the call to synchronized getElvis method as there is no object to
lock? When the class-loader loads the class Elvis during the call to getElvis, it would
create a java.lang.Class object describing the class Elvis on the fly. The thread
calling the synchronized getElvis would get the monitor for that Class object which
was created by class-loader. Only one synchronized static method can be called for a
class by a thread at a time. In this sense the behavior of synchronized static and
instance methods is identical. Monitor used to manage synchronized execution of
static methods is different from the one used for instance methods. Therefore it is
perfectly possible for two threads to execute a synchronized static method and
instance method at the same time.

Smaller granularity locking


If only a small portion of the code inside a member method needs to be guarded by
the monitor, then it is not necessary to synchronize the whole method. Java allows a
smaller granularity locking by encasing the critical code inside the construct shown
below:
Object to be locked is passed as an argument
synchronized (obj) following keyword synchronized
{
//Place the code to be guarded by the lock or monitor here
}
In above construct obj is the object to be locked while the code in the curly braces is
executed. When object being locked is the same in whose class the synchronized
block is placed then obj is simply the reference this.

This allows us to modify the withdraw method of BankAccount class as below


(Listing 20.6A) and achieving the results identical to the case, when whole method
was synchronized.
public boolean withdraw(int amount)
{
synchronized(this)
{ Critical code that must complete
if(balance >= amount) by one thread at a time is placed
{ in the synchronized block.
pause();
balance -= amount;
return true;
}
}
return false;
}
//Listing 20.6A

Topic 20 Multithreading (Singhal) Page 23 of 52


Results from withdraw method shown in Listing 20.6A are identical to the one used
in Listing 20.3A. One may ask as to in which situations use of a synchronized block
would be indispensable? Suppose before balance is set to the new value, the method
withdraw needed to get user input to confirm withdrawal action. In this case the
method withdraw would need to do an I/O operation. This is a conflicting situation
because the thread calling withdraw has the monitor to the BankAccount object, yet
I/O needs to block thread executing the synchronized method till it completes I/O
operation. In such condition use of synchronized block locks only the critical portion
of entire method. If a synchronized method throws an exception then the monitor to
the object is also freed as it would be after a normal method completion.

Perhaps a better example of using the synchronization block is given by a situation,


when an instance method is operating on a static variable, and we would like a
mutually exclusive access to the static variable. Consider the code given below for
method decreaseCount in the class CountEngine (Listing 20.6B).
public class countEngine
{
private static int count;
public synchronized void decreaseCount()
{
count--;
}
}//Listing 20.6B
One may think that since method decreaseCount is synchronized the static variable
count is not accessible by another synchronized method at the same time! This is not
true. Since count is a static variable, another static method can get access to it while
some thread is executing the method decreaseCount. For example if we add a static
method increaseCount to above class as follows (Listing 20.6C), then both methods
decreaseCount and increaseCount can get hold of variable count at the same time.
(Recall that the monitors for object and class are different).
public class countEngine
{
private static int count;
public synchronized void decreaseCount()
{
count--;
}
public synchronized static void increaseCount()
{
count++;
}
}//Listing 20.6C
The reason for this is because the thread executing the method decreaseCount will
get the object monitor, whereas the thread executing the method increaseCount will
get the class monitor. This would allow two independent threads to manipulate the

Topic 20 Multithreading (Singhal) Page 24 of 52


variable count at the same time, creating the unpredictability in the results7. The
solution to this situation is to place the decrement of static variable count in the
method decreaseCount inside a synchronized block (Listing 20.6D).
public class countEngine
{
private static int count;
public void decreaseCount() When synchronizing operation on
{ a static member, the argument to
synchronized(getClass()) synchronization block is the Class
{ object for that class. Method
count--; getClass returns a Class object.
}
}
public synchronized static void increaseCount()
{
count++;
}
}//Listing 20.6D
The modified decreaseCount method works because the protected code, count—gets
places inside a synchronized block that uses the class level monitor, and not the
object monitor. Thus when a thread is executing the synchronized block inside the
decreaseCount method, another thread trying to execute increaseCount method will
be denied access as the class monitor needed is unavailable. One could use a
synchronization block inside a static method, but it should be done with great care.
There are situations, where it may appear to work, but the result may not be what
you would expect. For example in Listing 20.5, we recommended that getElvis
method be written as follows: (Listing 20.6E).
public synchronized static Elvis getElvis()
{
if (Instance == null)
Instance = new Elvis();
return Instance;
}
//Listing 20.6E
Interesting thing about this method is that one needs the synchronization, only the
very first time when Instance is indeed null. After first invocation, the
synchronization is not needed and one has to live with its overhead8. One may be
tempted to re-write the getElvis method as below to avoid synchronization overhead
after the first call (Listing 20.6F).

7
We would admit that it would be hard to imagine that any one would write such bad code.
However, in defensive programming one must think of all possibilities.
8
It has been suggested that synchronized methods may be slower by a factor of 100 compared to
their non-synchronized version.

Topic 20 Multithreading (Singhal) Page 25 of 52


public static Elvis getElvis()
{
if (Instance == null)
{
synchronized(Elvis.class)
{
Instance = new Elvis();
}
}
return Instance;
}
//Listing 20.6F
The logic goes that when getElvis is invoked the very first time, then synchronized
block will call the constructor to create the only Elvis instance ever needed. After
first invocation, the if block will have a pre-condition that is false and it will never
be executed again. Unfortunate thing is that this does not work! The problem is that
when the first thread invokes getElvis it gets inside the if block. However it is totally
possible that before this thread executes the code line inside the synchronized block,
another thread invoking getElvis would also find condition Instance == null to be
true, and it too can get inside the if block, thus destroying the singleton pattern of
class Elvis. Therefore in a situation such as this, the idiom of using a synchronized
block does not work, and one has to live with the overhead of the synchronization.
Programmers have suggested a little trick called “Double-checked locking (DCL)”
to keep the synchronization block. This trick is shown in Listing 20.6G.
public static Elvis getElvis()
{
if (Instance == null)
{
synchronized(Elvis.class)
{
if (Instance == null)
Instance = new Elvis();//Line #8
}
}
return Instance;
}
//Listing 20.6G
While above shown DCL idiom would work in C++, it is not guaranteed to work in
Java. This has to do with Java’s memory model which is different from C++. Java’s
memory model does not guarantee that one thread would read data exactly in the
order in which other thread writes it. This problem is called “out of order writes”.
The first thread that executes getElvis would execute the line #8 in the following
order:

Topic 20 Multithreading (Singhal) Page 26 of 52


1. Memory for Instance is allocated.
2. The constructor for Elvis is called.
3. Finally Instance is given a non-null value.
There would be no problem if the second thread executing getElvis saw the above
operations in the sequence (1Æ2Æ3) performed by first thread. This however is not
guaranteed! The second thread may see the operations performed by first thread in
this sequence:
1. Memory for Instance is allocated.
2. Instance is given a non-null value.
When that happens, the second thread would not satisfy the condition
Instance==null and skip the synchronization block and return a partially
constructed object to its caller. That means that it would skip the third step
altogether. This problem is not a bug in JVM, rather it is an outcome of platform
independent Java Memory Model9. Therefore in a case such as Singleton class one
may have to live with the slowness of the synchronization of static factory method.

Waiting inside a Synchronized method or block and communication


between threads
Results of Figure 20.6 shows that account fee deduction failed when call to
synchronized method withdraw by the AccountManager thread realized that
account did not have adequate funds. When that happened in old days, your bank
will pick up the phone and ask you to deposit money in your checking account. In
today’s banking system checking account is linked to the savings by a mechanism
called as “overdraft” protection. If the balance in checking account falls below a
certain threshold, then an automatic transfer from savings or from a credit card
account takes place. The manner in which this protection can be automated is that
as soon as a thread executing the method withdraw realizes that there are not
enough funds in the account being debited, the thread does two things:
1. It gives up the monitor to the object it had locked, so that some other thread
can transfer money from another account to activate the overdraft
protection.
2. The original thread executing the withdraw method waits inside the method,
so that once additional funds are added to the account, it would proceed to
complete execution of withdraw method.
Java provides overloaded methods called wait, which when invoked by an object
results in snatching away its monitor from the thread which had owned it at that
time and returns it to JRE. The current thread is thus made non-runnable, and JRE
is then free to give monitor to other waiting thread. Wait method is ALWAYS called
from inside of a synchronized method or from inside of a synchronized block. If an
attempt is made to call wait from outside the synchronized block an exception of
type IllegalMonitorStateException is thrown. Table 20.4 shows a brief summary of
three versions of wait method which are inherited by all Java classes, as they are
passed down by the class java.lang.Object.

9
For more details read “Double-checked locking: Clever, but broken” in Java World February 2001
or search www.google.com with query “double- checked locking”.

Topic 20 Multithreading (Singhal) Page 27 of 52


void wait()
Causes current thread to wait until another thread invokes the
notify() method or the notifyAll() method for this object.
void wait(long timeout)
Causes current thread to wait until either another thread invokes the
notify() method or the notifyAll() method for this object, or a specified
amount of time has elapsed.
void wait(long timeout, int nanos)
Causes current thread to wait until another thread invokes the
notify() method or the notifyAll() method for this object, or some other
thread interrupts the current thread, or a certain amount of real time has
elapsed.
Table 20.4
What is also important about the calling the wait method is that it must be called
inside a loop. Thus the method withdraw of BankAccount class must be modified as
follows: (Listing 20.7).

public synchronized void withdraw(double amount)


throws InterruptedException
{
while (balance < amount)
wait();
System.out.print("Withdrawing " + amount);
double newBalance = balance - amount;
System.out.println(", new balance is " + newBalance);
balance = newBalance;
}
//Listing 20.7
When a thread calls the instance method withdraw above, if the pre-test condition
(balance <amount) is true, then object calls its wait method. As mentioned before,
after the wait method is called the monitor for the object is taken away from the
current thread and that thread waits inside the loop, until the pre-test condition of
balance being less than amount tests to be true. The method withdraw throws an
InterruptedException, because the wait method can throw it. We also have an
option of putting the call to wait method inside a try block, followed by a catch
clause that handles the InterruptedException. We need to emphasize again that wait
method is called by the object, and not by the thread, thus call to wait in Listing 20.7
is seen as being this.wait ( ). This technique, where a thread is locked inside a wait
loop is also called using a mutex lock. (Mutex is short form for mutually exclusive).
The general idiom of using the wait method inside a synchronized method is:

while ( ! the_condition_I_am_waiting_for )
wait( );

Topic 20 Multithreading (Singhal) Page 28 of 52


On the other hand the idiom of using the wait method inside a synchronized block
is:

synchronized (The_Object){
while ( ! the_condition_I_am_waiting_for )
The_Object .wait( );
}

If synchronization is being done for a class level monitor to synchronize the access to
the static members, then The_Object is the Class object for the class. getClass is an
instance method inherited from java.lang.Object super class that returns the Class
object for a class. For example if we need to call the wait method inside the
synchronized block in Listing 20.6D, we can do it as follows: (Listing 20.6E).

public class countEngine


{
private static int count;
private boolean the_condition_I_am_waiting_for = false;
public void decreaseCount( ) throws InterruptedException
{
synchronized(this.getClass()) The object being passed
{ to the synchronized
while (! the_condition_I_am_waiting_for) block must be the one to
this.getClass().wait(); invoke wait method!
count--;
} Figure
Figure 0.2
0.1
}
public synchronized static void increaseCount()
{
count++;
}
}//Listing 20.6E
If the synchronization block is inside a static method then an instance of the class to
invoke the getClass method would need to be available.

In order to liberate the thread frozen inside the wait loop, two things must happen.
1. Another thread must make the pre-test condition (balance < amount) to
evaluate to false. In our case it means that there must be a thread that
executes a method to transfer money from the savings to checking account or
deposit money into it.
2. The thread that was waiting must be “notified” that its wait is over, and it
could get the monitor back to execute rest of the withdraw method on the
object from which it was frozen out earlier. This notification can be made by
calling one of the methods notify and notifyAll– both inherited from class
java.lang.Object (Table 20.5).

Topic 20 Multithreading (Singhal) Page 29 of 52


void notify()
Wakes up a single thread that is waiting on this object's monitor.
void notifyAll()
Wakes up all threads that are waiting on this object's monitor.
Table 20.5
Once again, the methods notify or notifyAll are called by the object and not by the
thread. Most of the Java literature suggests that thread that takes the responsibility
of waking other threads should call notifyAll, rather than notify. It is also indicated
however, that notifyAll has a higher performance penalty and in situation, where
only a single thread has been waiting, calling notify is more efficient. It goes without
saying that when in doubt, use notifyAll. We write the method transferFromSavings
to accomplish above objectives (Listing 20.8).
public synchronized void transferFromSavings(int account_num, double amount)
{
if (amount<=0)
{
notifyAll();
return;
}
System.out.print("Transferring " + amount + " from account number " +
account_num);
double newBalance = balance + amount;
System.out.println(", new balance is " + newBalance);
balance = newBalance;
notifyAll();
}
//Listing 20.8
The method transferFromSavings, tests if amount to be transferred is zero or
negative, in which case it notifies the waiting threads and ends the method call. It is
obvious that calling notifyAll or notify would also make the current thread non-
runnable as the calling thread will give up its object monitor. However, if a finite
amount of money is to be transferred, then method echo prints the amount being
transferred and the account number from which the transfer is being made from.
Then it sets the new value of balance equal to the old value plus the amount
transferred. The last line of code notifies all waiting threads that method
transferFromSavings finished the execution and it releases the monitor to the object,
so that one of the waiting threads can get it now. Few things are important to note
here.
1. The call to wait method must be made inside a loop (see Listing 20.7).
Making a call inside an if structure would not do it.
2. For every call to the wait method, there must be a call made to the method
notify or notifyAll. If that does not happen then the waiting thread may wait
forever and there is no guarantee that it would be freed from the mutex lock.
3. Another thread also must change the condition that made the waiting thread
wait in the first place.

Topic 20 Multithreading (Singhal) Page 30 of 52


Dynamics of all these factors is better shown by redesigned BankAccount and other
utility classes. Figure 20.7 shows the high level diagram for the members of re-
designed BankAccount class.

FIG. 20.7
The Listing 20.9A shows the source code for the class BankAccount.
00007 public class BankAccount
00008 {
00013 private String Str1 = ", new balance is ";
00017 private double balance;
00021 public BankAccount()
00022 {
00023 this(0.0);
00024 }
00030 public BankAccount(double amt)
00031 {
00032 balance = amt;
00033 }
00034
00039 public synchronized void deposit(double amount)
00040 {
00041 if(amount<=0)
00042 {
00043 notifyAll();
00044 return;
00045 }
00046 System.out.print("From " + Thread.currentThread().getName()+

Topic 20 Multithreading (Singhal) Page 31 of 52


00047 ": Depositing " + amount);
00048 double newBalance = balance + amount;
00049 System.out.println(Str1+ newBalance);
00050 balance = newBalance;
00051 notifyAll();
00052 }
00053
00059 public synchronized void withdraw(double amount)
00060 throws InterruptedException
00061 {
00062 while (balance < amount)
00063 wait();
00064 System.out.print("From " + Thread.currentThread().getName()
00065 +": Withdrawing "+ amount);
00066 double newBalance = balance - amount;
00067 System.out.println(Str1+ newBalance);
00068 balance = newBalance;
00069 }
00070
00075 public synchronized double getBalance()
00076 {
00077 return balance;
00078 }
00079
00085 public synchronized void transferFromSavings(int account_num, double
amount)
00086 {
00087 if(amount<=0)
00088 {
00089 notifyAll();
00090 return;
00091 }
00092 System.out.print("From " + Thread.currentThread().getName()+
00093 ": Transferring " + amount + " from account number " + account_num);
00094 double newBalance = balance + amount;
00095 System.out.println(Str1+ newBalance);
00096 balance = newBalance;
00097 notifyAll();
00098 }
00099 }//end of class
//Listing 20.9A
We have already discussed methods withdraw and transferFromSavings. The
method deposit is almost identical to transferFromSavings, except that it only takes
amount to be deposited as an argument. Method getBalance is now synchronized, as
we need to see the balance in each thread ascertaining that it is not changed while
getBalance method is invoked.

Topic 20 Multithreading (Singhal) Page 32 of 52


The other major design change we make is that now we define three common
operations on the BankAccount objects: withdraw, transfer, and deposit, and we
create a thread class for each of them. Thus we have three classes:
WithdrawThread, TransferThread, and DepositThread, each facilitate the
corresponding actions on the BankAccount object. These three classes are derived
from abstract super-class BankAccountOperations, which extends
java.lang.Thread. Figure 20.8 shows the high level view of super-class and sub-
classes.
Abstract class
Extends Thread

Extends BankAccountOperations
Fig. 20.8A

Fig. 20.8B

Topic 20 Multithreading (Singhal) Page 33 of 52


Extends BankAccountOperations

Fig. 20.8C
The class DepositThread is structurally alike the class WithdrawThread. Super-
class BankAccountOperations defines the protected data members account, amount,
DELAY, and REPITITIONS, common to all thread sub-classes. Table 20.6 gives the
summary of data members for super-class BankAccountOperations.

Field Summary For class BankAccountOperations


protected account
BankAccount The BankAccount object on which certain thread operation is
performed.
protected amount
double Amount of money to be either deposited/transferred or
debited.
DELAY
protected
static int
Delay in milliseconds to put the thread to sleep.
REPETITIONS
Number of iteration cycles by which the sleep loop is executed.
Table 20.6
Listing 20.9B, C, D, and E gives the code for super-class BankAccountOperations
and its concrete thread sub-classes.
00012 public abstract class BankAccountOperations extends Thread
00013 {
00014
00018 protected BankAccount account;
00019
00023 protected double amount;
00024
00028 protected static final int DELAY = 10;
00029
00033 protected static final int REPETITIONS = 10;
00034 }

Topic 20 Multithreading (Singhal) Page 34 of 52


//Listing 20.9B
00006 class WithdrawThread extends BankAccountOperations
00007 {
00013 public WithdrawThread(BankAccount anAccount, double anAmount)
00014 {
00015 account = anAccount;
00016 amount = anAmount;
00017 }
00018
00024 public void run()
00025 {
00036 try
00037 {
00038 account.withdraw(amount);
00039 sleep(DELAY);
00040 }
00041 catch(InterruptedException Irex)
00042 {
00043
00044 }
00045 }
00046
00047 }
//Listing 20.9C
00004 class DepositThread extends BankAccountOperations
00005 {
00011 public DepositThread(BankAccount anAccount, double anAmount)
00012 {
00013 account = anAccount;
00014 amount = anAmount;
00015 }
00016
00017 public void run()
00018 {
00019 try
00020 {
00026 account.deposit(amount);
00027 sleep(DELAY);
00028 }
00029 catch (InterruptedException exception)
00030 {
00031 }
00032 }
00033 }
//Listing 20.9D
00011 public class TransferThread extends BankAccountOperations

Topic 20 Multithreading (Singhal) Page 35 of 52


00012 {
00013 private int act_num;
00014
00016 public TransferThread(BankAccount anAccount, double anAmount, int
act_num1)
00017 {
00018 account = anAccount;
00019 amount = anAmount;
00020 act_num = act_num1;
00021 }
00022
00023 public void run()
00024 {
00025 try
00026 {
00027 // for (int i = 1; i <= REPETITIONS && !isInterrupted(); i++)
00028 //{
00029 account.transferFromSavings(act_num, amount);
00030 sleep(DELAY);
00031 //}
00032 }
00033 catch (InterruptedException exception) { }
00034 }
00035 }
//Listing 20.9E
run method of thread sub-classes deserve further explanation. All threads are put to
sleep by the amount of time equal to DELAY milliseconds. Before that however, the
threads call the corresponding instance method in the BankAccount class. For
example the run method of WithdrawThread class calls the withdraw method of
BankAccount class with an argument equal to the amount to be withdrawn. The
DepositThread class run method calls the deposit method of BankAccount class with
an argument equal to the amount to be deposited. Similarly, the run method of
TransferThread class calls the transferFromSavings instance method with account
number (from which the transfer is done) and the amount to be transferred.

Customer class
The Customer class is designed so that a BankAccount customer can make
withdrawals, deposits, and transfers through a menu driven interface. When
withdrawal is being made, an overdraft protection is applied automatically. Figure
20.9 shows the high level diagram for Customer class.

Topic 20 Multithreading (Singhal) Page 36 of 52


Data Type:
BankAccount

Figure 20.9
The class Customer has one data member account, which is of type BankAccount.
The constructor takes a BankAccount type object and initializes account equal to it.
The menu method provides a menu driven interface to carry out various banking
activities. Listing 20.9F gives the source code for the class Customer.
00006 import java.io.*;
00015 public class Customer
00016 {
00021 private BankAccount account;
00023 public Customer(BankAccount act)
00024 {
00025 account = act;
00026 }
00027
00032 public void menu()
00033 {
00034 boolean ok = true;
00035 do
00036 {
00037 System.out.println( "From " + Thread.currentThread().getName()+
00038 ": [W]ithrdaw, [T]ranfer, [D]eposit , [P]rint balance or [E]xit?");
00039 BufferedReader BR = new BufferedReader(
00040 new InputStreamReader(System.in));
00041 String Input = "";
00042 try
00043 {
00044 Input = BR.readLine();
00045 if(Input.startsWith("W")||Input.startsWith("w"))
00046 {
00047 System.out.print("From " + Thread.currentThread().getName()+

Topic 20 Multithreading (Singhal) Page 37 of 52


00048 ": Enter the amount to withdraw: ");
00049 Input = BR.readLine();
00050 Input = Input.trim();
00051 double amount = Double.parseDouble(Input);
00052 System.out.println("From " + Thread.currentThread().getName()+
00053 ": If the balance in checking account is less than "
00054 + amount + " an automatic transfer will be made from savings to cover "
00055 + " the over draft.");
00056 WithdrawThread t1 = new WithdrawThread(account, amount);
00057 double val = account.getBalance();
00058 double amt_trn = amount - val + 1;
00059 TransferThread TT = new TransferThread(account, amt_trn , 1);
00060 TT.start();
00061 t1.start();
00062 continue;
00063 }
00064 else if(Input.startsWith("P")||Input.startsWith("p"))
00065 {
00066 System.out.println("From " + Thread.currentThread().getName()+
00067 ": The current balance = " + account.getBalance());
00068 continue;
00069 }
00070 else if(Input.startsWith("T")||Input.startsWith("t"))
00071 {
00072 System.out.print("From " + Thread.currentThread().getName()+
00073 ": Enter the amount to transfer from Savings: ");
00074 Input = BR.readLine();
00075 Input = Input.trim();
00076 double amount = Double.parseDouble(Input);
00077 TransferThread TT = new TransferThread(account, amount, 1);
00078 TT.start();
00079 continue;
00080 }
00081 else if(Input.startsWith("D")||Input.startsWith("d"))
00082 {
00083 System.out.print("From " + Thread.currentThread().getName()+
00084 ": Enter the amount to deposit: ");
00085 Input = BR.readLine();
00086 Input = Input.trim();
00087 double amount = Double.parseDouble(Input);
00088 DepositThread DT = new DepositThread(account,amount);
00089 DT.start();
00090 continue;
00091 }
00092 else if(Input.startsWith("E")||Input.startsWith("e"))
00093 ok = false;

Topic 20 Multithreading (Singhal) Page 38 of 52


00094 else
00095 {
00096 System.out.println("From " + Thread.currentThread().getName()+
00097 ": Illegal option");
00098 continue;
00099 }
00100 }
00101 catch(IOException Ioex)
00102 {
00103 Ioex.printStackTrace();
00104 }
00105 }while(ok);
00106 }//method menu
00107 }//class
//Listing 20.9F
The menu method of Customer class runs a do-while loop to present the following
menu choices to the user:
• Withdraw
• Deposit
• Transfer
• Print balance
• Exit
Each menu choice is controlled by an if-else-if control structure. In blocks
facilitating withdrawal, deposit and transfer the threads needed to perform the
required activity are instantiated and then such threads are started. Most important
of among these is the withdrawal block (L20.9F#45-63) which needs to ascertain the
overdraft protection. If user enters either “W” or “w” as the menu choice then
program prompts the user to enter the amount of money to be withdrawn
(L20.9F#47-48). After parsing the user input the WithdrawThread t1 is instantiated
(L20.9F#56). Then TransferThread is instantiated with arguments BankAccount,
amount that is to be withdrawn, and account number (L20.9F#59). In this case we
just give a fictitious account number (=1). In a more advanced application we would
need to run another thread that would make a simultaneous deduction from this
account, from which the transfer is being done. Finally we start both the transfer
and withdrawal threads – in that order (L20.9F#60-61). When user needs to
perform deposit (L20.9F#81-91), or transfer (L20.9F#70-80), the control blocks
instantiate needed DepositThread and TransferThread objects respectively.

AccountManager class
The class AccountManager performs a single activity of deducting monthly fee.
Figure 20.10 shows the high level diagram for this class.

Topic 20 Multithreading (Singhal) Page 39 of 52


Data Type:
BankAccount

Figure 20.10
The class data members Account is the BankAccount on which the
AccountManager needs to operate. The fee data member is the static data which has
the monthly fee to be deducted at the end of the month. The constructor takes the
BankAccount object and sets the class level Account equal to it. The method
deductMonthly fee creates TransferThread and WithdrawThread objects to
accomplish the deduction of monthly fee and transfer money from savings if needed.
Listing 20.9G shows the source code for the AccountManager class.
00011 public class AccountManager
00012 {
00013 private BankAccount Account;
00014 private static double fee = 20;
00016 public AccountManager(BankAccount Act)
00017 {
00018 Account = Act;
00019 }
00020
00021 public void deductMonthlyFee()
00022 {
00023 System.out.println("From " +
Thread.currentThread().getName() + ": Deducting monthly fee. If the balance is below "
00025 + fee + " then a transfer would be made from savings account.");
00026 WithdrawThread WT = new WithdrawThread(Account,fee);
00027 double val = Account.getBalance();
00028 double amt_trn = fee - val +1;
00029 TransferThread TT = new TransferThread(Account,amt_trn,1);
00030 WT.start();
00031 TT.start();

Topic 20 Multithreading (Singhal) Page 40 of 52


00032 }
//Listing 20.9G
In the deductMonthlyFee method, program first prints out a message that if
monthly fee to be deducted exceeds the current balance, then a transfer would be
made from the savings account. The program then instantiates a WithdrawThread
and a TransferThread. Both threads take the BankAccount and fee parameters as
arguments. If balance is below the fee then TransferThread ascertains that
appropriate amount of money is transferred from the Savings account whose
account number is passed to the former. Finally both threads are started.

BankAccountThreadTest and integration of all classes


The class BankAccountThreadTest instantiates the objects of type BankAccount,
AccountManager, and Customer. The BankAccount object is passed to the
constructor of the later two. The Customer object calls its menu method, whereas
the AccountManager calls its deductMonthlyFee method. The Listing 20.9H shows
the code for this test class with main method.
public class BankAccountThreadTest
{
public static void main(String[] args)
{
BankAccount account = new BankAccount(10);
AccountManager AM = new AccountManager(account);
Customer Cust = new Customer(account);
AM.deductMonthlyFee();
Cust.menu();
}
}
//Listing 20.9H
Before we discuss the output from the above main method, we may wish to review
dependency diagram showing relationships between various classes in Listing 20.9.
Figure 20.11 shows these dependencies.

Topic 20 Multithreading (Singhal) Page 41 of 52


FIG. 20.11
The BankAccountThreadTest class is the starter class and uses the Customer,
BankAccount, and AccountManager classes. The Customer class uses BankAccount,
WithdrawThread, DepositThread, and TransferThread. The AccountManager class
uses the aforementioned classes except the DepositThread. The three thread classes
derive from class BankAccountOperations and they all use the BankAccount class.
The dependency diagram shows something interesting in the sense that all classes
end up using the BankAccount class. Therefore any change in that class may
propagate through the classes in the entire package.

Testing all classes


Figure 20.12 shows the test run from the Listing 20.9 on a hyperthreaded, single
processor machine.
From main: Deducting monthly fee. If the balance is below 20.0 then a transfer
would be made from savings account.
From main: [W]ithrdaw, [T]ranfer, [D]eposit , [P]rint balance or [E]xit?
From Thread-1: Transferring 11.0 from account number 1, new balance is 21.0
From Thread-0: Withdrawing 20.0, new balance is 1.0
p

Topic 20 Multithreading (Singhal) Page 42 of 52


From main: The current balance = 1.0
From main: [W]ithrdaw, [T]ranfer, [D]eposit , [P]rint balance or [E]xit?
w
From main: Enter the amount to withdraw: 99
From main: If the balance in checking account is less than 99.0 an automatic
transfer will be made from savings to
cover the over draft.
From main: [W]ithrdaw, [T]ranfer, [D]eposit , [P]rint balance or [E]xit?
From Thread-3: Transferring 99.0 from account number 1, new balance is 100.0
From Thread-2: Withdrawing 99.0, new balance is 1.0
p
From main: The current balance = 1.0
From main: [W]ithrdaw, [T]ranfer, [D]eposit , [P]rint balance or [E]xit?
100
From main: Illegal option
From main: [W]ithrdaw, [T]ranfer, [D]eposit , [P]rint balance or [E]xit?
w
From main: Enter the amount to withdraw: 100
From main: If the balance in checking account is less than 100.0 an automatic
transfer will be made from savings t
o cover the over draft.
From main: [W]ithrdaw, [T]ranfer, [D]eposit , [P]rint balance or [E]xit?
From Thread-5: Transferring 100.0 from account number 1, new balance is 101.0
From Thread-4: Withdrawing 100.0, new balance is 1.0
d
From main: Enter the amount to deposit: 23
From main: [W]ithrdaw, [T]ranfer, [D]eposit , [P]rint balance or [E]xit?
From Thread-6: Depositing 23.0, new balance is 24.0
t
From main: Enter the amount to transfer from Savings: 26
From main: [W]ithrdaw, [T]ranfer, [D]eposit , [P]rint balance or [E]xit?
From Thread-7: Transferring 26.0 from account number 1, new balance is 50.0
p
From main: The current balance = 50.0
From main: [W]ithrdaw, [T]ranfer, [D]eposit , [P]rint balance or [E]xit?
w
From main: Enter the amount to withdraw: 49
From main: If the balance in checking account is less than 49.0 an automatic
transfer will be made from savings to
cover the over draft.
From main: [W]ithrdaw, [T]ranfer, [D]eposit , [P]rint balance or [E]xit?
From Thread-8: Withdrawing 49.0, new balance is 1.0
p
From main: The current balance = 1.0
From main: [W]ithrdaw, [T]ranfer, [D]eposit , [P]rint balance or [E]xit?
w

Topic 20 Multithreading (Singhal) Page 43 of 52


From main: Enter the amount to withdraw: 23
From main: If the balance in checking account is less than 23.0 an automatic
transfer will be made from savings to
cover the over draft.
From main: [W]ithrdaw, [T]ranfer, [D]eposit , [P]rint balance or [E]xit?
From Thread-11: Transferring 23.0 from account number 1, new balance is 24.0
From Thread-10: Withdrawing 23.0, new balance is 1.0
p
From main: The current balance = 1.0
From main: [W]ithrdaw, [T]ranfer, [D]eposit , [P]rint balance or [E]xit?
d
From main: Enter the amount to deposit: 300
From main: [W]ithrdaw, [T]ranfer, [D]eposit , [P]rint balance or [E]xit?
From Thread-12: Depositing 300.0, new balance is 301.0
p
From main: The current balance = 301.0
From main: [W]ithrdaw, [T]ranfer, [D]eposit , [P]rint balance or [E]xit?
E
FIG. 20.12
The main method calls the method menu for object Cust and deductMonthlyFee for
object AM. Since the menu method blocks on an I/O (presenting menu choices), it
does not start any threads first. On the other hand the deductMonthlyFee method of
AccountManager class creates threads of type WithdrawThread and
TransferThread and completes the deduction of monthly fee. Fourth and fifth lines
of output in Figure 20.12 show the output from the two threads started by the
deductMonthlyFee method. They show up named as Thread-1(transfer thread) and
Thread-0 (withdraw thread). The reason that we get a message from
TransferThread first (even though it is started later) is because fee to be deducted
(20) is larger than the initial account balance (=10), which puts the
WithdrawThread in the wait loop. It comes out of that wait loop after the
TransferThread has made a transfer of 11, allowing the loop condition inside the
withdraw method to be false and thus liberating the WithdrawThread to complete
the execution of withdraw method of BankAccount class. The deductMonthlyFee
method called by Act then completes execution. In line #9 of Figure 20.12 output,
user chooses to withdraw money from the account and in line #10 they enter the
withdrawal amount to be 99. Since that is larger than the current balance of 1, the
withdrawal thread once again waits in the loop and transfer thread makes a
transfer of 99 from savings and then withdrawal thread proceeds to withdraw
money. You would notice that as we continue to use the program, more and more
threads are created – and by the end we have created about 13 threads (not
counting the main). There is no way of reusing Java threads that have finished their
run method and when needed the program instantiates new threads.

You would appreciate now that synchronization is a powerful tool. By using the
thread synchronization, we were able to automate the overdraft protection in our
bank account simulations. While without synchronization, some modern software

Topic 20 Multithreading (Singhal) Page 44 of 52


may be rendered useless, it has few problems of its own. We have already mentioned
that synchronized methods carry an overhead, making them vastly slower than their
non-synchronized versions. The other problem introduced by badly designed
synchronization is creation of deadlocks.

Synchronization deadlocks
Excessive synchronization may cause deadlocks. What are deadlocks? Deadlocks
are blocked processes that can never be unblocked. One reason for this condition is
that threads in a deadlock set wait for a process that only another thread from the
set could execute. Unless the software is designed to recover from deadlocks, it will
hang the program or system using it. You would recall that in the
transferFromSavings method of our BankAccount class, we were only able to do one
way transfers i. e. from savings to checking. Imagine that you would like to write
just one transfer method, which can take the following three arguments:
1. From_Account – The account from which the money is to debited.
2. To_Account – The account into which the money is to be credited.
3. amount – Amount to be transferred.
The header of such generic transfer method can be written as follows:

public void transfer (BankAccount From_Account, double amount,


BankAccount To_Account)

You would like to ascertain that while method transfer is in execution, both
From_Account, as well as To_Account objects are locked by the same thread, so
that state of both accounts is not altered by another thread. In that case we may
wish to write the body of transfer method as follows (Listing 20.10A).
public void transfer (BankAccount From_Account, double amount,
BankAccount To_Account)
{
synchronized(From_Account)
{
synchronized(To_Account)
{
// Make sure that there are enough funds in From_Account
// Debit the From_Account by amount
// Credit the To_Account by amount
}
}
}
//Listing 20.10A
Now imagine that two threads are trying to use the method transfer at the same
time. (Notice that method transfer is not synchronized, so two threads can call it at
the same time). We create two BankAccount objects as follows:

BankAccount Savings = new BankAccount ( );

Topic 20 Multithreading (Singhal) Page 45 of 52


BankAccount Checking = new BankAccount ( );

It could happen that one thread is calling the method transfer with arguments in the
following order:
transfer (Savings, amount, Checking),
while the other thread is calling it with the following argument list:
transfer (Checking, amount, Savings).
The sequence of events could be such that first thread would acquire the lock to
object Savings. However before it can acquire the lock to Checking (the second lock
needed in the method transfer), it is entirely possible that second thread may
acquire the lock to object Checking. (This because for second thread Checking
becomes the From_Account whose lock it must acquire first). When this happens
then two threads are deadlocked. The first thread has the lock on object Savings
and it waits for the lock on Checking, and the second thread does the reverse. Both
threads are waiting for each other to release the lock but neither does it. Of course
in this case the solution is simple: do not use synchronization blocks. Rather make
the method transfer as a whole synchronized. It would also appear that many
potential deadlocks would be prevented if you would write methods in a manner
that does not require locking more than one object at a time. The probability of
deadlocks increase in direct proportion to the number of objects one needs to lock.
If one has to use multiple locks then one needs to define an order in which the
threads would acquire the locks to the objects. Listing 20.10B shows as to how one
can define a lock order to avoid deadlocks.
1 public void transfer (BankAccount From_Account, double amount,
2 BankAccount To_Account) throws InterruptedException//because of withdraw method
3 {
4 BankAccount First_Lock = null;
5 BankAccount Second_Lock =null;
6
7 if(amount<=0)//negative or zero amount is not transferred
8 {
9 notifyAll();
10 return;
11 }
12 else if(From_Account.getAccountNumber() == To_Account.getAccountNumber())
13 {
14 // Cannot transfer to the same account
15 notifyAll();
16 return;
17 }
18 else if(From_Account.getAccountNumber() < To_Account.getAccountNumber())
19 {
20 First_Lock = From_Account;
21 Second_Lock = To_Account;
22 }
23

Topic 20 Multithreading (Singhal) Page 46 of 52


24 else
25 {
26 First_Lock = To_Account;
27 Second_Lock = From_Account;
28 }
29
30 synchronized (First_Lock)
31 {
32 synchronized (Second_Lock)
33 {
34 if (From_Account.hasSufficientBalance(amount))
35 {
36 From_Account.withdraw(amount);
37 To_Account.deposit(amount);
38 notifyAll();
39 }
40 }
41 }
}//Listing 20.10B
In Listing 20.10B, we define two BankAccount objects, First_Lock & Second_Lock
and set them equal to null (L20.10B#4-5). Then program takes no action if amount
to be transferred is zero, negative, or transfer is being done (mistakenly) to the same
account (L20.10B#7-17). The lock order setting takes place in the last two blocks of
if and else structure (L20.10B#18-28). For every object of BankAccount class, we
introduce a unique ID called account number. If account number of From_Account
is less than To_Account then the First_Lock is set equal to the From_Account and
Second_Lock equal to the To_Account (L20.10B#20-21). Reverse assignment is
made in the last else block, which shall be executed when From_Account is larger
than the To_Account. This structure makes sure that locks are assigned in
ascending order of account numbers.

Now imagine that two thread that calls transfer method makes a call such as:
transfer (Savings, amount, Checking); //by first thread
and
transfer (Checking, amount, Savings); //by second thread
Then following two possibilities exist.
1. If savings account number is smaller than the checking account number then
first thread will acquire lock to Savings first and then to Checking. Notice that in
this scenario the else block (L20.10B#24-28) would be true for the second thread.
It will also try to acquire the locks in the same order i. e. Savings and then
Checking. However, the deadlock would be avoided because either lock to
Savings would be available at that time or it would not be.
2. The second possibility is exact mirror image of the first one. If Savings account
number is larger than the Checking account number then the lock order is
Checking and then Savings.

Topic 20 Multithreading (Singhal) Page 47 of 52


In either case it becomes certain that both threads try to acquire the locks in the
same order. Then among competing threads, either a thread would acquire both
locks and none of them. Appendix to this chapter gives another good example of
defining lock order to avoid deadlocks. It is important to understand that best way
to avoid deadlocks is to ascertain during the design that locking behavior does not
occur. It is also important to document the design rules and locking order which
should be followed during coding.

Killing Java Threads


If run method does not have a loop that must iterate forever, then a Java thread
would come to the end of its life naturally. However, there are situations in control
systems where certain code inside the run method must loop continuously until
some condition is met and the thread must be killed. The stop method of Thread
class is now deprecated since it was realized that its use can lead to corruption of
objects shared by threads. Now the responsibility falls on the programmer to
provide an appropriate stop method for the thread class they design. One
recommended technique to stop a thread is to have it poll one of its fields and stop if
the field has acquired certain value. One would write a class
WellBehavedStopThread as below (Listing 20.11).
public class WellBehavedStopThread extends Thread
{
private boolean stop_requested = false;

public void run()


{
boolean done = false;

while(!stopRequested() && !done)


{
// do the thread task
}
}

private synchronized boolean stopRequested()


{
return stop_requested;
}

public synchronized void stopThread()


{
stop_requested = true;
}
}
//Listing 20.11
When the program instantiates and starts a thread of type
WellBehavedStopThread, then since initially both stop_requested and done (inside

Topic 20 Multithreading (Singhal) Page 48 of 52


the run method) are false, the while loop with in the run method executes
continuously. As soon as the user calls the stopThread instance method on the
thread, it sets the class variable stop_requested to true. Then in next loop iteration
when loop pre-condition is checked then private method stopRequested returns the
current synchronized value of the stop_requested which is true and this allows the
while loop to exit. It is important to realize here that the reason this technique of
stopping a thread works lies in the synchronization of methods stopThread and
stopRequested. By now you would appreciate that all user created threads run in
main thread or they can be made to run with in other threads. Imagine that we use
the unsynchronized version of stopThread method and the while loop inside the run
method is modified as follows:

while ( !stop_requested && !done) {


//loop body
}

Topic 20 Multithreading (Singhal) Page 49 of 52


Appendix

Listing such as below can cause deadlock.

public int sumArrays(int[] a1, int[] a2)


{
int value = 0;
int size = a1.length;
if (size == a2.length) {
synchronized(a1) {
synchronized(a2) {
for (int i=0; i<size; i++)
value += a1[i] + a2[i];
}
}
}
return value;
}
Below Listing shows as how to define a gloabal lock order and rewrite the method
sumArrays to avoid deadlocks.

class ArrayWithLockOrder
{
private static long num_locks = 0;
private long lock_order;
private int[] arr;

public ArrayWithLockOrder(int[] a)
{
arr = a;
synchronized(ArrayWithLockOrder.class) {
num_locks++; //Increment the number of locks.
lock_order = num_locks; //Set the unique lock_order for
} //this object instance.
}
public long lockOrder()
{
return lock_order;
}
public int[] array()
{
return arr;
}
}

class SomeClass implements Runnable


{
public int sumArrays(ArrayWithLockOrder a1,
ArrayWithLockOrder a2)
{
int value = 0;
ArrayWithLockOrder first = a1; //Keep a local copy of array
ArrayWithLockOrder last = a2; //references.
int size = a1.array().length;
if (size == a2.array().length)

Topic 20 Multithreading (Singhal) Page 50 of 52


{
if (a1.lockOrder() > a2.lockOrder()) //Determine and set the
{ //lock order of the
first = a2; //objects.
last = a1;
}
synchronized(first) { //Lock the objects in correct
order.
synchronized(last) {
int[] arr1 == a1.array();
int[] arr2 == a2.array();
for (int i=0; i<size; i++)
value += arr1[i] + arr2[i];
}
}
}
return value;
}
public void run() {
//...
}
}

Topic 20 Multithreading (Singhal) Page 51 of 52


//Listing 20.10B
////////////////////////////////////////////////////////////////////////////////////////////////////////////

Topic 20 Multithreading (Singhal) Page 52 of 52


CS 23: Advanced Java
Chapter 21: Networking Or Talking to other Machines
Author: Satish Singhal Ph. D.
Version 1.0 (November 2004)

Java networking is a technology that enables one to write programs that would
allow one to connect to various computers on the Internet, on a local area network
(LAN), or on an intranet1. Computers connected to the Internet for the purpose of
serving clients are called servers and they may perform one or more of the following
services:
• Publishing content on web pages and on web sites,
• Provide web service such as banking, entertainment, and knowledge base,
• Provide data, software, and other kind of files,
• Provide communication assistance such as e-mail, text chat, voice chat,
telephony, and video conferencing,
• Provide electronic shops and e-commerce channels.
Java libraries are so well designed for the Internet and for networking between the
computers and devices that it is now said “Java is the language for the
Internet”. Networking is the name given to the process by which computers or
other devices communicate with each other. In order for the computers to
communicate with each other, we can connect them directly. This technique is called
point to point connection. This can work if number of computers that need to
communicate with each other is small. When large numbers of computers need to
communicate with each other then they are connected to a network. Figure 21.1
shows a schematic picture of a generic network.

1
Intranet is a network of computers that uses the same principles that Internet does. However unlike
Internet the intranet is a private network. Intranets are built and used by corporations and entities
for their own use.

Chapter 21 Networking (Singhal) Page 1 of 36


FIG. 21.1
A computer network has nodes which reside in a network cloud. Nodes are special
purpose computers such as routers (that direct network traffic) or switches (in
telephone networks). The computers that are not the part of network cloud are
called end nodes. The end nodes can be client or server or peer to each other.
In modern days the best example of networking is Internet, which is a world-wide
collection of computers attached to the same network in disparate geographic
locations on the globe. At the time of this writing, it is estimated that nearly 600
million computers are connected to the Internet. The technology of networking is
not limited to just computers talking to each other. Device such as mobile phones,
GPS navigation systems in modern automobiles, radio frequency tagging of
merchandise storage boxes, PDA’S, transmission towers, fax machines, and satellite
communication are all examples of networking between machines. Before we learn
as to what Java can do for us in the world of computer networks & communication,
we must learn something about common technology that is used by such networks.
To understand this, once again we turn our attention to the Internet.

By now you can appreciate that Internet facilitates the communication between
computers which may have vastly different hardware and operating system (OS).
For example when a client computer requests a web page from a server, irrespective
of the brands and OS of client and server the request is fulfilled. Therefore, the
designer of Internet had to come up with a scheme that would allow communication
between any two machines, as long as they fulfilled some basic requirements. The

Chapter 21 Networking (Singhal) Page 2 of 36


technology which allows networking between disparate machines is called Open
Systems Interconnection or OSI model.

OSI Model
OSI model divides the communication process in seven layers. The layered structure
in OSI model is analogous to the modular structure adapted in designing modern
software. Once the function of each module is defined, the implementation can be
done in many different ways. Same way, once the function and service provided by
each layer is defined; the hardware and software implementation can be done in
many different ways. Dividing the task of communication in layers also facilitates
management of complexity of the network. Figure 21.2 shows the various layers in
the OSI model that participate in computer2 networking. This figure shows seven
layers, however in some applications the number of layers can be as low as five or
four.

Internet
applications
combine
these 3
layers in
one and call
them
application!

FIG. 21.2
Data from the source computer flows downward from the application layer through
each layer until it reaches to the physical layer or physical link between two
computers. Then on the receiver computer data travels upwards from physical layer
2
We are using the word computer in this chapter in a more generic sense. The fact is that any two
devices can be made to network with each other.

Chapter 21 Networking (Singhal) Page 3 of 36


to the application layer presenting the data to it. The physical link can be an actual
copper or fiber optic wire or even a wireless link (for example in mobile phones). In
a two way communication process, the receiver and transmitter computers can
switch roles sending data back and forth to each other. This is exactly what happens
when you chat on the Internet through common programs such as Yahoo or MSN
messengers. The bottom three OSI layers are also called by the name subnet.
Application layers on source and destination computers have software’s that
manage their communication session. The Java programming that we discuss in this
chapter would program applications only for the top layer. However even to do that
effectively, we need to know something about the other layers underneath.

Our Figure 21.2 does not give numbers to the OSI layers; however it is customary to
number them from bottom to top in ascending order, thus physical layer being
number one and application layer being number seven. (This is why many times you
would hear networking professional referring to some layer number, when they
have problem with that particular layer in their network). The Internet applications
combine the layers five, six and seven into one layer and call this collection as the
application layer (thus reducing number of layers to five). It is hard for people to
remember the names of all the layers. Therefore many devices are floating around
to memorize them. For example “Please Do Not Teach Students Poor Acronyms”,
where the first alphabet of each word is also the first alphabet of each layer (P =
Physical, D = Datalink, N = Network, T = Transport, S = Session, P = Presentation,
A = Application).

We now briefly describe the service provided by each layer in OSI model. Table 21.1
gives the laundry list of service each layer must perform and example(s) wherever
we can give one.
Layer Layer Service performed Example(s) of
Number Name service
7 Application Gets the data from the source or Web page request,
sends data to the destination. e-mail, files
transfer requests.
6 Presentation Prepares data in the format that it Conversion from
can be transported on the network Unicode to ASCII
and can be understood by the or ASCII to binary
receiver.
5 Session Sets up an active connection Shopping on an e-
between source and destination, commerce site
maintains it, and when session is
over tears it.
4 Transport Manages the flow of data between If part of a
the source and destination and message is lost, it
control the quality of data can be resent.
communication. Handles the
addressing of the messages.

Chapter 21 Networking (Singhal) Page 4 of 36


3 Network Handles the route from source to Converting web
destination, manages the traffic address typed by
problems including congestion. the user to the
domain address in
numbers.
2 Datalink Manages the flow of data to next Stamping the
physical node in the route by address of the next
determining its address and also physical machine
prints this address on each portion in the route.
of the message being sent.
1 Physical Carries the bits between source and Flow of current in
destination. The signal can be the copper
analogue (like old phone line) or communication
digital (Fiber optic link). wire or flow of
light in the fiber
optic cable
Table 21.1
All layers except for the physical layer need some software to ascertain that they
perform service they are designed for to the given standards. The implementation
details of the services provided by each layer are called protocols. The reason to
separate service from implementation detail is because that allows one to change the
hardware and software implementation of certain layer without changing its service
& functionality. This is analogous to OOP software paradigm, where abstraction is
separated from the implementation. Based on the network design there may be
many protocols available for a layer. While service details of each protocol for a
layer may be different, they would fall into same genre.

Alphabet soup of protocols


One thing that frightens the programmers about network programming is the
alphabet soup of protocol acronyms. The communication engineers talk about
protocols assuming that programmers know the details of a service a particular
protocol performs. This is hardly the case. Therefore programmers must exert
effort in understanding the binding between layers, services and protocols. Table
21.2 gives a list of acronyms & examples for the protocols that can be used for
various layers. Obviously each protocol for a layer does not perform exact same
service, but they do provide the basic service that layer is supposed to perform.
Layer Layer Protocols and Examples
Number Name
7 Application • FTP File Transfer Protocol
• HTTP Hypertext Transport Protocol, used in the
World Wide Web
• POP3 Post Office Protocol Version 3
• SNMP Simple Network Management Protocol
• SMTP Simple Mail Transfer Protocol

Chapter 21 Networking (Singhal) Page 5 of 36


• Telnet, a remote terminal access protocol
• Gnutella, a peer-to-peer file-swapping protocol
• DNS Domain Name Service
• SSH Secure Shell
• IMAP Internet Message Access Protocol
• NTP Network Time Protocol
• Gopher, a precursor of web search engines
• Finger, which gives user profile information
• NNTP News Network Transfer Protocol
• LDAP Lightweight Directory Access Protocol
• DHCP Dynamic Host Configuration Protocol
• IRC Internet Relay Chat
• Jabber, an instant-messaging protocol
• WebDAV Web Distributed Authoring and
Versioning
• DICT Dictionary protocol
• BACnet Building Automation and Control
Network protocol
• Secure versions of the above (as HTTPS, etc.)

6 Presentation HTTP/HTML (hypertext mark up language), ASN.1,


XML (Extensive mark up language), TDI, XDR, SNMP,
Netware Core Protocol, AppleTalk Filing Protocol (AFP)
5 Session AppleTalk Session Protocol (ASP), AppleTalk Data
Stream Protocol (ADSP), Data Link Control (DLC),
Named Pipes, NBT, NetBIOS, NWLink, Printer Access
Protocol (PAP), Zone Information Protocol (ZIP)
4 Transport AEP, AMTP, AppleTalk Transaction Protocol (ATP),
NBP, NetBEUI, RTMP, SMB, SPX, TCP Transport
control protocol) , UDP (User datagram protocol)
3 Network IP (Internet protocol), IPX, NWLink, DDP
2 Datalink Ethernet, 802.11 WiFi, Token ring, FDDI, Point-to-Point
Protocol (PPP)
Table 21.2
What is most important to understand is that to write network software you do not
need to memorize the details of alphabet soup in the Table 21.2. This list is
presented as a reference so that if some one throws a protocol acronym at you, then
you can at least decipher as to which network layer they are talking about, and then
if need be, you can look up the details of that protocol in the literature. For Java
network programming, the important facts to master are depicted in Figure 21.3.
The applications that we are interested in would be built on the top of IP (Internet
Protocol), using TCP (Transport Control Protocol) or UDP (User Datagram
Protocol). Figure 21.3 shows the stack of protocols used by the common Internet
applications.

Chapter 21 Networking (Singhal) Page 6 of 36


FIG. 21.3: DNS = Domain name sever, TFTP = Trivial File Transfer
Protocol
Services needed for our applications from the network layer would be adequately
satisfied by the IP. Most web services applications use TCP for the transport layer,
thus we end up saying that we are using TCP/IP stack. Fortunately this stack and its
related software are installed on most modern computer systems. (Windows 95 did
not have it originally, however later on it was included).

First of all let us describe as to how the IP works. The source computer would send
data to destination that would be broken up in “packets”. The data packets received
at the destination computer are assembled back into the original data form. The
way in which packetization is done and the address headers are added to them is
shown by the Figure 21.4.

Chapter 21 Networking (Singhal) Page 7 of 36


FIG. 21.4
The source computer breaks down the data being sent in packets of certain number
of bytes each. Layers TCP, IP, and datalink; each stamps a header on the packet.
Network layer stamps the IP address of the destination computer on the packet,
whereas the datalink layer stamps the MAC (Media Access Control) address of next
machine in the network which shall receive the data packet. TCP header is mostly
for controlling the quality of data transport, while IP and MAC headers control
routing of the packet. If you would ever like to know as to how many intermediate
nodes your web request goes through, just go to console and type:

> tracert web address

Figure 21.5 shows a trace of route an IP packet would travel from Southern
California from my computer to the web site of Guardian newspaper
(www.guardian.co.uk) in England.

Chapter 21 Networking (Singhal) Page 8 of 36


FIG. 21.5
Fifteen intermediate nodes were involved in getting the packet from my computer to
the Guardian server in England. Though TCP and IP headers are printed on the
packet in the beginning, each intermediate node puts the MAC address of next node
that shall receive the packet. Why do we need TCP? Network layer, for which IP is
the implementation, is a dumb layer in the sense that it only knows where to send
the packets. Things such as whether all packets reached the destination, the order in
which they reached, and the recovery of lost packets3 – these are all responsibility of
transport layer. Figure 21.3 showed two protocols used for the transport layer –
UDP and TCP. UDP is similar to you mailing the letter at the post office. Just like
you place the address and stamp on the envelope and you rely on post office’s
performance to deliver the letter to its destination, UDP places a destination address
on the packet and gives it to the network layer – hoping that it will get to the address
on header. UDP can be used in those applications where portions of lost data do not
cause a problem.

When one needs to ascertain that ALL packets reach their destination, more robust
protocol is needed. It is similar to the fact that when you need to make sure that
your letter must reach the destination, you would pay post office extra money and
send it certified or registered. TCP is the implementation of transport layer which
has aforementioned robustness. TCP ascertains that all packets sent by source are
received by destination. It sends a packet and waits for an acknowledgement from
destination that packet was received. Lost packets are re-sent. TCP keeps a copy of
a sent packet till it receives the acknowledgement from destination that packet was
received.

3
Some packets are inevitably lost in the transmission due to so called transmission losses.

Chapter 21 Networking (Singhal) Page 9 of 36


Client Server Architecture
In world of the network communication the applications are designed using so
called “client server architecture4”, which is also called two-tier-architecture. In this
architecture the client makes the request for the data or service to the server
computer which is usually more powerful. Client would have a software application
which can communicate with the corresponding software on the server. Both the
client and server software’s are designed based on the common underlying protocol
controlling the type of communication. We have already seen one example of use of
client server architecture when using JDBC we were able to communicate with the
database5 from the client Java program. Internet applications such as using a web
browser to get the web pages from the server, getting files from an FTP server,
getting emails from a POP3 server, and sending e-mail through a SMTP server are
all examples of client server applications. There are applications in which a server
can connect and served several clients at the same time. This is what happens when
several people chat in a chat room. The chat server is able to serve several clients at
the same time. Java network libraries can be used to develop software for both
client and server machines. We saw one example of that in chapter on graphical
user interface, where we developed a web browser to connect to servers on the
Internet. In that application we used URL class from the package java. net. The use
of URL is a high level network programming paradigm. One popular lower level
network programming technique which allows lot of flexibility in designing client
server applications is called “Socket Programming, which we discuss next.

Sockets
Using sockets is actually much easier than defining them. In this sense trying to
define a socket is like blind men grabbing different parts of an elephant and
describing elephant according to what they grabbed on to. The person grabbing the
tail said that elephant is like a rope, whereas the person grabbing the leg said that
elephant is like a pole. Let us hope that we can do better then those unfortunate
blind men. Sockets are to communication between client and server what I/O system
is to the program that wishes to communicate with a file and file itself. When a
client and a server must communicate a process must exist on each computer to do
so. If we would use TCP/IP, then this communication process would piggy-back the
process on client and server. Creation of this communication process or interface
generically embodies sockets. For example the steps in creating and using a socket
could be:
• Creation – Open a socket.
• Reading & Writing – Receive data from and send data to socket.
• Destruction – Close socket.
Both in Java and in Berkeley BSD flavor of UNIX (originator of sockets) as well as
in other operating systems, API’s are available to send and receive data through

4
To understand the impact of client server architecture we have to go back to the era of main frame
computing where all the processing was done by the server and client was just a dumb terminal
which unlike today’s desktop of client computer, had no real processing power or software.
5
Databases usually follow a three tier architecture which apart from client and server software’s
uses an intermediate software layer called middleware.

Chapter 21 Networking (Singhal) Page 10 of 36


sockets. Process of writing software to do so is called sockets programming. On
server side the socket is just like a listener in a GUI. It’s an object that is bound to a
port number. Port numbers are just integers bound to certain programs on the
server. They are not actually physical port numbers on the server machine. For
example if you are calling port number 80, that does not mean that server machine
has 79 other physical ports. You may think of port number as a virtual port and not
a physical one. The socket on server side waits and listens for a communication
request initiated by a client. Obviously for a client to initiate such request it has to
know the name of the machine it needs to connect to and its port number.

Client Side Programming using Socket


When a client wishes to connect to server through a socket, following must be
available:
• A physical or wireless connection with the server.
• Implementation of TCP/IP or UDP/IP stacks on client machine.
• The address of the host.
• Port number to which to connect to.
If above are available, then creating a client Socket object in Java is quite easy. It is
done by calling the constructor of class java.net.Socket as below:

Socket Sock = new Socket (“Host Name”, port number);

The Host Name is the string providing the name of the host with whom a Socket
communication is intended. The host name can be a numerical IP address or a
domain name. For example the host name (domain name) www.photo.net would
automatically be translated by the domain name server, to the IP address:
216.127.244.133
The string in Socket class constructor above could either be the domain name or
numerical IP address for the host. The port number is the integer bound to the
program on host which would facilitate the communication with respect to the
application being sought (See Figure 21.3). The above constructor call can throw the
following three exceptions, of which first two are checked type. Therefore the
constructor call must be embedded in proper try catch blocks:

UnknownHostException - if the IP address of the host could not be determined.


IOException - if an I/O error occurs when creating the socket.
SecurityException - if a security manager exists and its checkConnect method
doesn't allow the operation.

Socket class has many other constructors, whose details are given by the API for
that class. If exceptions are not thrown then constructor would create a Socket
object which can be used to read and write those files on the server which exist and
for which the read/write permissions are available, or perform other activities
permitted by the program on server side. Sidebar 21.1 gives more information about
IP addresses and domain names.

Chapter 21 Networking (Singhal) Page 11 of 36


Sidebar 21.1
Each server on Internet is given an IP address which depending upon the type of
protocol may be a string made of digits, periods, and hex digits. (The computers on
LAN may just be given MAC addresses or both MAC and IP). For the protocol IPv4
the IP for a machine is a 32 bit address including digits and periods. For example:
IP address 216.127.244.133 belongs to web site www.photo.net. Therefore in
your browser you may be able to open this web site either by typing the address:
http://216.127.244.133 or by
http://www.photo.net
What is more important however, that when you type a domain name, a domain
name server converts that into a numerical IP address on the fly. The domain name
server is automatically called by one of the network layer to do this translation. The
maximum number of IP addresses allowed by the 32 bit IPv4 protocol can be 232 =
4,294,967,296 or about 4 billion. The new 128 bit addressing scheme IPv6 would
allow a 128 bit addressing scheme which would allow about 2128 =
3.4028236692093846346337460743177e+38 addresses, which could provide an IP
address for every conceivable device in the universe. (Considering that number of
atoms in the universe is estimated to be in the range 1078 to 1081, IPv6 can provide IP
addresses for everlasting future). For all Internet related documents one can search
the web site of Internet Engineering Task Force (ITEF) on address: www.itef.org

Protocol and Port Number bindings


On the server side the industry has agreed upon a standard as to which protocol and
its related applications must be hosted on which port number. Each port number
has associated server software bonded with it. For example a web-server software
would be able to listen to a client HTTP request on a port number 80. Table 21.3
gives summary of such protocols, the generic names for the server software and the
port number it binds to.
Protocol Port Generic name for the server software or its use
Number
HTTP 80 Web server
SMTP 25 Mail transfer server or SMTP server
NNTP 119 NNTP Server or news group server
FTP 21 File transfer server or FTP server
Telnet 23 Remote connection
Finger 79 System user information provider
POP3 110 POP3 Server
Table 21.3
Port numbers up to 1024 are reserved for binding to standard protocols. Numbers
larger than 1024 may be used for any of the pre-defined protocols or user defined
ones.

Chapter 21 Networking (Singhal) Page 12 of 36


HTTP6 protocol and related methods
On client side a suitable constructor for the Socket class would create a socket
object for us that can be used to communicate with the server. Just like SQL
allowed you to make certain queries or create data tables on the database server, a
paradigm of similar nature allows client to use some HTTP methods to either make
requests from the server or make postings on it. The details of HTTP protocol and
its methods are described by the documents number RFC7 2616 & RFC 2518 and
they can be found on the web addresses: http://www.ietf.org/rfc/rfc2616.txt, and
http://www.ietf.org/rfc/rfc2518.txt.

The above documents define 15 HTTP methods. Table 21.4 gives a summary of
some HTTP methods. Understand however, that web server administrator may
disallow any methods to the client that are deemed unsafe or security hazards. On
the other hand, the authenticated users may be allowed to use them based on the
degree deemed necessary by the server administrator.
Method Name (All Description
upper case)
GET Used during web browsing to get documents
POST To submit data back to the server when filling out web forms
OPTIONS Used to query web server about its capabilities provided to the
client.
TRACE Used to trace the path of the client request through fire walls,
and proxy servers.
HEAD Used to get the header information for a resource
PROPFIND
PROPPATCH
MKCOL
DELETE Provides a way to delete the document from the server
PUT Stores the content body at the location specified in the request
COPY
MOVE
LOCK
UNLOCK
SEARCH
Table 21.4
HTTP methods are used in the request that client makes of the server. The general
syntax of the request is as follows:

6
What is important in real estate? Location, location, location. What is important in writing HTTP
based applications? Understand HTTP, understand HTTP, understand HTTP.
7
RFC stands for request for comments. In early days of Internet development the IETF created
specification documents and asked the community to make comments on it. The final form of the
documents retained original name which was given a RFC title and a number.

Chapter 21 Networking (Singhal) Page 13 of 36


Method Name Requested Resource Protocol

Using the GET method, the generalized syntax above would boil down to:

GET Path to the resource requested / Resource file name HTTP / Protocol #
\ 2 line feeds

When using socket programming the path to the resources requested is the web
address of the server and is not needed in the string making the GET request. Thus
all you need is the resource file name. Protocol number can be 1.0 or 1.1 etc.,
depending upon the implemented HTTP by the web server. Based on how the GET
request is sent, additional line feeds may be needed. As an example if I needed the
file index.html from a web server whose name and port number has already been
passed to the Socket constructor, then my GET request string to get the file
index.html would look like below:

“GET index.html HTTP/1.0\n\n”

When using URL’s (rather than socket programming)8, path to the resource
requested would include the web address and other path details to the requested
resource.

After the GET request is made, the server may do two things:
• It may honor the request and provide the resource requested. If something
goes wrong in fulfilling the request, it may also provide an error code.
• It may decline the request.
Understand that in HTTP, the process is over after the sever has fulfilled or
declined the request. Even if the Socket object on client side is still alive, it would
have to make another request and server would have no memory of any previous
requests made by the same client socket. In this sense it is said that HTTP is a
stateless protocol as it does not maintain any information from the previous session
with the same client. (Some servers may put cookies in your web browser to retain
some of the information from previous sessions. Cookies are small text files).

Connecting to a web server through a client side socket


We show first example of Java network programming in which we connect to a web
server using a Socket on the client side. The usual thing one does on a web server is
to get the web page whose file name is known. For many web sites the homepage is
stored in a file called index.html. Listing 21.1 shows a program where user can enter
web server’s IP address or domain name and the file name to be printed on the
command line and then program will display the contents of the requested file on
the standard output.

8
URL = Uniform Resource Locater

Chapter 21 Networking (Singhal) Page 14 of 36


00001 import java.io.*;
00002 import java.net.*;
00003
00004 public class MySocket
00005 {
00006 public static void main(String[] args)
00007 {
00008 if(args.length <2)
00009 {
00010 System.out.println(
"The program needs two command line arguments. First for the web address and second for the file name."
00012 + " Exiting the program.");
00013 System.exit (0);
00014 }
00015 Socket Sock = null;
00016 PrintWriter Fout = null;
00017 BufferedReader Fin = null;
00018 try
00019 {
00020 //args[0] must be the DNS or IP address of the web server
00021 Sock = new Socket(args[0],80);
00022 System.out.println("connected");
00023 Fout = new PrintWriter(
00024 new OutputStreamWriter(Sock.getOutputStream()));
00025 Fin = new BufferedReader(
00026 new InputStreamReader(Sock.getInputStream()));
00027 //args[1] must be the file name requested from the web server
00028 //Server must use HTTP 1.0 or you must know which version it is
using
00029 // String path = "GET " + args[1] + " HTTP/1.0\n\n";
00030 String path = "GET " + args[1] + " HTTP/1.1\n\n";
00031 //String path = "HEAD " + args[1] + " HTTP/1.1\n\n";
00032 // send GET to the server
00033 Fout.print (path);
00034 // Must flush or command never gets sent!!
00035 Fout.flush();
00036 //read response
00037 String Line = "";
00038 System.out.println("sent request");
00039
00040 while((Line = Fin.readLine()) != null)
00041 System.out.println(Line);
00042
00043 Sock.close();
00044 }

Chapter 21 Networking (Singhal) Page 15 of 36


00045 catch(UnknownHostException Unkhst)
00046 {
00047 System.out.println("The host is not found");
00048 Unkhst.printStackTrace();
00049 }
00050 catch(IOException e)
00051 {
00052 System.out.println("Cannot perform I/O");
00053 e.printStackTrace();
00054 }
00055 }//end of main
00056 }//end of class
//Listing 21.1
Our program run from the command line and would need at least two arguments.
The first argument would be the address of the web server we wish to connect to
and second is the name of the resource (for example file) we wish to retrieve from it.
Therefore if number of command line arguments is less than two we end the
program (L21.1#8-14). Then we instantiate our Socket object which takes the first
command line argument as the string for the host address and we just use the port
number 80 which is the default for HTTP requests (L21.1#21).

The Socket class has two methods getOutputStream which returns an object of type
OutputStream and getInputStream which returns object InputStream. Figure 21.6
reproduces the Java API description of these instance methods.

public OutputStream getOutputStream()throws


IOException
Returns an output stream for this socket.

If this socket has an associated channel then the resulting output stream delegates all of
its operations to the channel. If the channel is in non-blocking mode then the output
stream's write operations will throw an IllegalBlockingModeException.

Returns:
an output stream for writing bytes to this socket.
Throws:
IOException - if an I/O error occurs when creating the output stream or if the
socket is not connected.
///////////////////////////////////
public InputStream getInputStream() throws
IOException
Returns an input stream for this socket.

If this socket has an associated channel then the resulting input stream delegates all of its
operations to the channel. If the channel is in non-blocking mode then the input stream's

Chapter 21 Networking (Singhal) Page 16 of 36


read operations will throw an IllegalBlockingModeException.

Under abnormal conditions the underlying connection may be broken by the remote host
or the network software (for example a connection reset in the case of TCP connections).
When a broken connection is detected by the network software the following applies to
the returned input stream :-

• The network software may discard bytes that are buffered by the socket.
Bytes that aren't discarded by the network software can be read using
read.
• If there are no bytes buffered on the socket, or all buffered bytes have
been consumed by read, then all subsequent calls to read will throw an
IOException.
• If there are no bytes buffered on the socket, and the socket has not been
closed using close, then available will return 0.

Returns:
an input stream for reading bytes from this socket.
Throws:
IOException - if an I/O error occurs when creating the input stream, the
socket is closed, the socket is not connected, or the socket input has been
shutdown using shutdownInput()
FIG. 21.6
The OutputStream object returned by the method getOutputStream can be
converted into a PrintWriter object for our Socket (Sock), which can then send our
GET request to the server as simply as the PrintWriter can write to a file. This is a
two step process. First step requires that we pass the OutputStream object returned
by getOutputStream method to the constructor of class OutputStreamWriter, and
then pass the object thus constructed to the constructor of class PrintWriter. Figure
21.7A shows the schematics of this process.

Chapter 21 Networking (Singhal) Page 17 of 36


FIG. 21.7A
The OutputStream pipe gets joined to the OutputStreamWriter pipe, which in turn
gets joined to the PrintWriter pipe, and this final pipe is the one that we use to send
our requests to the web server (L21.1#23-24). If the connection we created with the
server (through OSI layers), is successful, we would get data packets back from the
server. To read that data we need a BufferedReader object. This is also created by a
two step process, where the InputStream object returned by the method
getInputStream of Socket object, is passed to the constructor of class
InputStreamReader, which in turn is passed to the constructor of class
BufferedReader. Figure 21.7B shows the schematics of this process.

Chapter 21 Networking (Singhal) Page 18 of 36


FIG. 21.7B
The Fin object created in the above manner can be used to read the bytes sent by
the server, just the way one reads a data file. Most beautiful thing about the piping
of these streams in Java is that communication with the server by the socket is
rendered as simple as a file I/O. After constructing our writer and reader objects,
now we are ready to send our request to the server. We thus construct our request
string path (L21.1#30), which uses the GET method and its associated syntax
discussed earlier. Sending the request is as simple as writing to a file, and we simply
use Fout.print (path) to send our request to the server (L21.1#33). Here is the
important part: You must call the flush method of PrintWriter class to
flush the buffer, otherwise the request never gets sent! (L21.1#35). If
server accepted our request and it does have the file that whose name we passed in
the GET request (part of the path string), then bytes start to flow to our machine,
which the Fin object created by us must read. We simply use the readLine method
of BufferedReader class to read the character stream sent by the server one line at a
time and display them on the standard output using a display loop (L21.1#40-41).
The loop exits when readLine method reaches the EOF character at the end of
stream and returns a null. The loop task is simply to display the strings read by
readLine on the standard output. Finally we close the socket to end our session with
the server (L21.1#43). The catch blocks following the try block handle
UnknownHostException and IOException. Figure 21.8 shows the results from
Listing 21.1 when we supply the following command line arguments:

Chapter 21 Networking (Singhal) Page 19 of 36


www.photo.net index.html . It actually gives us the source code in HTML for
the home page of www.photo.net. To reduce the size of output, we are only showing
beginning and end portion of the output. Actual output includes the HTML source
code for the homepage of www.photo.net.
00001 connected
00002 sent request
Status Code
Description
Protocol

00003 HTTP/1.0 200 OK Header information


about the server and
the resource
00004 MIME-Version: 1.0 requested!
00005 Date: Sun, 21 Nov 2004 18:10:51 GMT
00006 Server: AOLserver/4.0
00007 Content-Type: text/html; charset=iso-8859-1
00008 Content-Length: 21863
00009 Connection: close
00010
00011
00012 <html>
00013 <head>
00014 <title>photo.net Home Page and Recent Digital Camera Reviews</title>
00015 <meta name="description"
00016 content="the Internet's largest learning
00017 community for photographers; read a camera review,
18 ask a question, share a photo">

//Output deleted for brevity


00449 </body>
00450 </html>
FIG. 21.8
In Figure 21.8, the first two lines are the output from our program. The line #3 is
the message sent by the web server echoing the protocol of our request (HTTP), its
request code (200), and its status (OK). The line #4 tells us the MIME version,
whereas the line #5 prints the date and time of our request. Line #6 tells us the type
of server software being used and seven tells us the kind of content the file we
requested has. Line #8 gives us the size of file in bytes. Line #9 says the connection is
closed, however that means that connection will be closed after the requested data
has been packetized and sent to the client. Each line in the header information part

Chapter 21 Networking (Singhal) Page 20 of 36


of the server response has a keyword (for example Date, Server etc.) and value
assigned to that keyword.

Description of sever status codes


When the HTTP server responds to the client request it provides a status code and
its description. For example in output of Figure 21.8 on line#3, the status code is 200
and its description is OK. The status codes generated by the server are grouped into
five categories (Table 21.5).
Code Meaning Selected Example(s)
Range
100 – 199 Informational • 100 – Continue: Client should continue
with its request.
• 101 – Switching protocol: Server
understood the client switching the
protocol in the current request and is
willing to comply with it.
200 – 299 Indicates that client • 200 – The request succeeded and data
request was successful sent.
• 206 – Server carried out partial GET
request.
300 – 399 The client request was • 301 – The requested resource has been
redirected and further moved to a new permanent URI9.
action is necessary • 305 Use proxy server to get the
requested resource.
400 – 499 Client request incomplete • 400 – Client made a request not
understood by the server.
• 401 – Request could not be fulfilled
because the client lacks proper
authorization.
• 404 – Not Found: The server could not
find the resource requested by the
client.
500 – 599 Server Error took place • 500 – Internal server error.
• 503 – The server is unable to handle the
request at this time due to overloading
or maintenance.
Table 21.5
Among the error code listed above you have perhaps come across the 404 when you
hit a broken link for a web page on a web site. In our program if we give command
line arguments:

www.photo.net xyz

9
URI means uniform resource indicator.

Chapter 21 Networking (Singhal) Page 21 of 36


We would get a server response as follows:

HTTP/1.0 404 Not Found

Reason for that is because no resource names xyz exists on the server. Status code
400 would be used if client made a request that is not understood by the server. One
example of this is when there is an error in the IP address; For example the
command line arguments:

www.phto.net index.html

would produce a server response:

HTTP/1.1 400 Bad Request

Server Side programming using Sockets


Before beginning sever side programming, please read the advice in the sidebar 21.2
below.
Sidebar 21.2
We must caution you about few issues before you begin to write server side software
on your computer at work or even at home. Just like you would create a socket on
client side, you can create a socket on server side. The problem however, is that once
your server socket is alive – your computer in affect has become a server! Any one
knowing the IP address of your machine can connect to it through the server socket
you created. There are hackers out there in the cyber space who are running port
scanner10 programs 24/7 to scan and find unprotected web servers. Once they
connect to your machine, they can make HTTP requests to read your entire
directory structure and perhaps at a later date hack your system. Best way to
protect yourself when you write server software at home is to turn off your internet
connection. If you must keep the Internet connection on, then you must use a
network firewall to protect your computer. In work settings become fully aware of
as to what the company policies are about protections that you must use, when you
write server software. Programmers have been fired from their jobs for
being careless about these security issues!
Server side sockets listen to client requests, and take appropriate actions on them.
In this sense the server side sockets are like phone receptionist, who with out
knowing who will call them, must wait for the phone to ring and answer it when it
does ring. Our first example of server side software is designing a web server to
serve multiple HTTP clients. What that means is that our web server must be able
to accept requests from new clients, while it is still in the process of serving previous
ones. This is best done by using multithreading, where process to serve each client

10
Port scanners are the programs that scan Internet for unguarded sockets and Internet connections
that can be exploited for un-authorized entry to the system. Port scanners do have legitimate uses as
well.

Chapter 21 Networking (Singhal) Page 22 of 36


runs in its own thread of control. Figure 21.9 shows the flow diagram of activities
that server must undertake.

FIG. 21.9
For each client request, server must perform activities enclosed in the blue bordered
oval. To limit the scope of this exercise we confine ourselves to the types of files that
server can send to the followings: html, jpg, gif, and plain text. In previous example
when we developed client side application using socket, we did not have to worry
about the details of what server did when it received a request. Now we explain
those details. When server gets a valid client request, it creates a “sever side socket”
and a new port to serve this client. This frees the original port to serve next client.
This new port and its associated socket fulfill the client request, after which the
former two are torn down. Since HTTP is a stateless protocol, this process repeats
again, even if the same client sends a new request right after fulfillment of its
previous one. Java provides a different socket class, called ServerSocket to create a
socket on the sever side. This server side socket is created by making the constructor
call of the following type:

ServerSocket Listener_Socket = new ServerSocket (port);

In above call, port is the port number integer on which sever will listen to the client
requests. For this application, in order to choose a non-standard port number, we
choose it to be a number above 102311 (must be below 65536). This constructor
throws an IOException (which is a checked exception), requiring that the

11
On UNIX server one cannot choose a port number less than 1024 without the authorization from
super user.

Chapter 21 Networking (Singhal) Page 23 of 36


constructor call be enclosed in a try catch block. Figure 21.10 reproduces the
description of this constructor from Java API.
public ServerSocket(int port)throws IOException
Creates a server socket, bound to the specified port. A port of 0 creates a socket on any
free port.

The maximum queue length for incoming connection indications (a request to


connect) is set to 50. If a connection indication arrives when the queue is full, the
connection is refused.

If the application has specified a server socket factory, that factory's


createSocketImpl method is called to create the actual socket implementation.
Otherwise a "plain" socket is created.

If there is a security manager, its checkListen method is called with the port
argument as its argument to ensure the operation is allowed. This could result in a
SecurityException.

Parameters:
port - the port number, or 0 to use any free port.
Throws:
IOException - if an I/O error occurs when opening the socket.
SecurityException - if a security manager exists and its checkListen method
doesn't allow the operation.
See Also:
SocketImpl, SocketImplFactory.createSocketImpl(),
setSocketFactory(java.net.SocketImplFactory),
SecurityManager.checkListen(int)
FIG. 21.10

Chapter 21 Networking (Singhal) Page 24 of 36


If the port number passed to the constructor is zero, then system assigns a port
number. However, this port number would be anonymous as no one would know it.
Some applications do use anonymous ports.

Once the constructor call above provides the ServerSocket object, we can create a
Socket object to serve the client by calling the accept instance method of the
ServerSocket class as follows:

‘accept’ method blocks until a client


request is received. It activates when
a client request is received and
returns a Socket to serve that client.

Socket Serve_Client = Listener_Socket.accept ( );

The accept method listens for a connection to be made to fulfill the impending client
request and finally creates a new Socket object (Serve_Client in this case)
materializing the connection with the client. Figure 21.11 reproduces the Java API
description of accept method.
public Socket accept()throws IOException
Listens for a connection to be made to this socket and accepts it. The method
blocks until a connection is made.

A new Socket s is created and, if there is a security manager, the security


manager's checkAccept method is called with
s.getInetAddress().getHostAddress() and s.getPort() as its arguments to
ensure the operation is allowed. This could result in a SecurityException.

Returns:
the new Socket
Throws:
IOException - if an I/O error occurs when waiting for a connection.
SecurityException - if a security manager exists and its checkListen method
doesn't allow the operation.
SocketTimeoutException - if a timeout was previously set with setSoTimeout
and the timeout has been reached.
IllegalBlockingModeException - if this socket has an associated channel, the
channel is in non-blocking mode, and there is no connection ready to be accepted
See Also:
SecurityManager.checkAccept(java.lang.String, int)
FIG. 21.11
The beauty of using ‘accept’ method is that it blocks the execution of its own code,
until an actual request is received from the client. In this sense it works almost like a
GUI listener. The method ‘accept’ can throw many exceptions; however it only
broadcasts the IOException in its header. The reason for that is that

Chapter 21 Networking (Singhal) Page 25 of 36


SocketTimeoutException is a subclass of IOException. Exception handling rule is,
that if a method throws a super class and subclass checked exceptions, then
broadcasting the super-class exception is enough. Both SecurityException and
IllegalBlockingModeException are unchecked type. The Socket object thus obtained
can now be used to create streams to read and write to the client. The read and
write processes on server side are identical to the previous example where client did
it. The Socket Serve_Client would first read the client request and then parse it to
get the resource name that client needs. Then the output stream writes the bytes to
the client.

Since each client request must run in its own thread, we write a class called
HttpRequest, and each object of this class would be used to serve one client. The
structure of HttpRequest class is shown by the Figure 21.12.

All member methods


except contentType
have void return type.
Method contentType
has String return type.

FIG. 21.12
This class has a constructor that takes a Socket object as an argument. This
argument would be provided by the return value from the accept method of the
ServerSocket object, when an actual client request is received. Since each object of
HttpRequest must run in its own thread, this class implements Runnable interface
and provides the implementation of run method. Method contentType,
processRequest, and sendBytes are helper methods. Run method calls the

Chapter 21 Networking (Singhal) Page 26 of 36


processRequest method. Figure 21.13 shows the dependency diagram for the class
HttpRequest.

Depends
upon

FIG. 21.13
Lines going from icons into the class HttpRequest show class members which are
also shown in Figure 21.12. Red arrows (connecting icons) show as to which member
depends on which other member. Sock is used by the constructor and
processRequest, so both of them depend upon Sock. CRLF is used only by
processRequest. processRequest is called by run. In turn processRequest calls
methods contentType and sendBytes. Relationships between various members of
class HttpRequest is now becoming clear. ‘run’ method will be called when a thread
of class HttpRequest would start. To process client request, the run method calls
processRequest which needs to make a determination as to what kind of content is
requested by the client. It does that by reading client request and parsing it for the
type of file client asked for. (For example if client asked for an html file, that file
extension would be included in the client request string). Method contentType takes
the client requested file name and returns its type as a String. Table 21.6 gives the
concluding summary of class HttpRequest.
Field Summary For class HttpRequest
(package private) CRLF
static java.lang.String A carriage return and line feed string used by method
processRequest.

Chapter 21 Networking (Singhal) Page 27 of 36


(package private) Sock
java.net.Socket Socket object that would be generated when client
makes a HTTP request to the web server.

Constructor Summary For class HttpRequest


HttpRequest(java.net.Socket Sock1)
Explicit constructor takes a Socket object as
argument and initializes the class level Socket object
equal to it.

Method Summary For class HttpRequest


private contentType(java.lang.String File_Name)
java.lang.String Determines the type of file requested by the client and
returns a String describing it.
void processRequest()
Reads and processes the client request.
void run()
Calls the processRequest method to fulfill client request.
private sendBytes(java.io.FileInputStream fis,
static void java.io.OutputStream Data_OS)
Sends the byte stream of resource requested by the client.
Table 21.6
Listing 21.2 shows the source code for the class HttpRequest.
00006 import java.net.*;
00007 import java.io.*;
00008 import java.util.*;
00019 public class HttpRequest implements Runnable
00020 {
00024 final static String CRLF ="\r\n";
00028 Socket Sock;
00029
00035 public HttpRequest(Socket Sock1)
00036 {
00037 Sock = Sock1;
00038 }
00039
00043 public void run()
00044 {
00045 try
00046 {
00047 processRequest();
00048 }
00049 catch (Exception e)
00050 {
00051 System.out.println(e);

Chapter 21 Networking (Singhal) Page 28 of 36


00052 }
00053 }
00054
00060 public void processRequest() throws Exception
00061 {
00062 //Get references to sockets input and output streams
00063 InputStream Istream = Sock.getInputStream();
DataOutputStream Data_OS = new DataOutputStream(Sock.getOutputStream());
00065
00066 //Set up input stream filter
BufferedReader br = new BufferedReader(new InputStreamReader(Istream));
00068
00069 //Get the request line of HTTP message
00070 String requestLine = br.readLine();
00071 // Extract the filename from the request line. Assume a GET command
00072 StringTokenizer tokens = new StringTokenizer(requestLine);
00073 tokens.nextToken(); //SKIP OVER THE ASSUMED 'GET' token
00074 String File_Name = tokens.nextToken();
00075 // Drop the slash at the beginning.
00076 if(File_Name.startsWith("/"))
00077 File_Name = File_Name.substring(1,File_Name.length());
00078
00079 // Open the requested file.
00080 FileInputStream fis = null;
00081 boolean fileExists = true;
00082 try
00083 {
00084 fis = new FileInputStream(File_Name);
00085 }
00086 catch (FileNotFoundException e)
00087 {
00088 fileExists = false;
00089 }
00090
00091 // Construct the response message.
00092 String statusLine = null;
00093 String contentTypeLine = null;
00094 String entityBody = null;
00095
00096 if (fileExists)
00097 {
00098 statusLine = "HTTP/1.0 200 OK" + CRLF;
00099 contentTypeLine = "Content-type: " + contentType(File_Name) +
CRLF;
00100 }
00101 else

Chapter 21 Networking (Singhal) Page 29 of 36


00102 {
00103 statusLine = "HTTP/1.0 404 Not Found" + CRLF;
00104 contentTypeLine = "NONE";
00105 entityBody = "\n\n Not Found";
00106 }
00107
00108 // Send the status line.
00109 Data_OS.writeBytes(statusLine);
00110
00111 // Send the content type line.
00112 Data_OS.writeBytes(contentTypeLine);
00113
00114 // Send a blank line to indicate the end of the header lines.
00115 Data_OS.writeBytes(CRLF);
00116
00117 // Send the entity body.
00118 if (fileExists)
00119 {
00120 sendBytes(fis, Data_OS);
00121 fis.close();
00122 }
00123 else
00124 {
00125 Data_OS.writeBytes(entityBody);
00126 }
00127
00128 //Close the streams
00129 Data_OS.close();
00130 br.close();
00131 Sock.close();
00132 }
00133
00140 private String contentType(String File_Name)
00141 {
00142 if(File_Name.endsWith(".htm") || File_Name.endsWith(".html"))
00143 return "text/html";
00144 else if(File_Name.endsWith(".jpg") || File_Name.endsWith(".jpeg"))
00145 return "image/jpeg";
00146 else if(File_Name.endsWith(".gif"))
00147 return "image/gif";
00148 else if(File_Name.endsWith(".txt"))
00149 return "text/plain";
00150 else
00151 return "application/octet-stream";
00152 }
00153

Chapter 21 Networking (Singhal) Page 30 of 36


00161 private static void sendBytes(FileInputStream fis, OutputStream Data_OS)
throws Exception
00162 {
00163 // Construct a 1K buffer to hold bytes on their way to the socket.
00164 byte[] buffer = new byte[1024];
00165 int bytes = 0;
00166
00167 // Copy requested file into the socket's output stream.
00168 while((bytes = fis.read(buffer)) != -1 )
00169 Data_OS.write(buffer, 0, bytes);
00170 }
00171
00172 }
//Listing 21.2
Most important method in class HttpRequest is processRequest that deserves
further explanation. The class member Sock would be created by the ‘accept’
method of ServerSocket object and passed to the constructor of class HttpRequest.
This will only happen after a client request is received as the method ‘accept’
blocks, until a request is received. Since we need to read and write from and to the
client, we create two corresponding stream objects of type: InputStream and
DataOutputStream (L21.2#63-64). Creation of these objects is facilitated by the
instance methods getInputStream and getOutputStream of the Socket class. Since
we expect the client request to be made entirely of characters, we create a
BufferedReader object br (L21.2#67). To create object br, we pass the object of type
Istream to the constructor of class InputStreamReader. The object thus created is
passed to the constructor of BufferedReader class. The technique of piping these
streams together the shown by the Figure 21.7B. Understand that since now we may
need to write binary files to the client, we can no longer use a PrintWriter object,
the way we did in Listing 21.1. Rather we use DataOutputStream object, whose
write method would allows us to write a byte stream to the client. In order to create
an object of type DataOutputStream, we pipe the OutputStream object returned by
the Socket class instance method getOutputStream directly to the
DataOutputStream object (Figure 21.14).

Chapter 21 Networking (Singhal) Page 31 of 36


FIG. 21.14
Next we need to read the client request and tokenize it (L21.2#70-74). You would
recall from our earlier discussion in client side programming that client request
string would be of form:
GET Path to the resource requested / Resource file name HTTP / Protocol #
\ 2 line feeds
Therefore we need to strip the “GET” from the request string, and then read the
portion after the ‘/’ but before the next white space. If client is limited to the request
of type:

http://URL/FileName

then their request string would be of form below12:

GET / Resource file name HTTP / Protocol # \ 2 line feeds

Therefore we just need to drop the slash from the second token in the request string
in order to retrieve file name or path to filename. Therefore after tokenizing the
‘requestLine’ (L21.2#72), an empty call is made to method ‘nextToken’ to discard
string ‘GET’ (L21.2#73). Next call to ‘nextToken’, gives us the file name string with
slash appended in front (L21.2#74). We confirm that and extract the file name by
dropping the slash in front by calling the substring method of String class, and
dropping the first character in the String (L21.2#76-77). Notice that this technique
requires that requested file be in the same directory in which the class file with
12
Understand that URL is not part of requested resource.

Chapter 21 Networking (Singhal) Page 32 of 36


application’s main method is. If all client accessible files are stored at another
location, then code for making proper path correction must be added. (We leave
that as an exercise). We now need to perform two activities: read the file requested
by the client and then write it to them. We also need to handle an eventuality that
client may have mistyped the file name in which case the file does not exist. Thus we
define a boolean variable ‘fileExists’ and set it to true (L21.2#81), and in order to
get a input stream from file we define the reference ‘fis’, of type FileInputStream
(L21.2#80). The FileInputStream class has a constructor that can take the filename
string as an argument. However, this constructor throws an exception of type
FileNotFoundException. Therefore the code to instantiate the FileInputStream
object is placed inside the try block followed by the corresponding catch block
(L21.2#82-89). If the file requested by the client exists then fis is instantiated.
Otherwise an exception is thrown and in the catch block we set ‘fileExists’ to false.
Now we need to construct the body of the message to be given to the client. We
define three string variables ‘statusLine’, ‘contentTypeLine’, and ‘entityBody’,
whose values will be set based on whether file exists or not and what type of content
the file has (L21.2#92-94).

If ‘fileExists’ is true, then statusLine is set to string "HTTP/1.0 200 OK" + CRLF
(L21.2#98). The ‘contentTypeLine’ string is set to reflect the type of content file has.
Portion of this string is constructed by the return value from the method
contentType, which takes the file name string as argument and returns a string
indicating its content type (L21.2#99). If the file does not exist then the else block is
executed (L21.2#101-106), which sets the values of strings to be published to the user
to give the error code 404 indicating that file was not found on the server. Instance
method writeBytes of class DataOutputStream is used to write the strings
‘statusLine’ and ‘contentTypeLine’ to the client (L21.2#109 & 112). We only need to
write the file to client if the file exists. Therefore, under the scope of if statement
testing the value of boolean variable ‘fileExists’, we call the method ‘sendBytes’ that
takes ‘fis’, and ‘Data_OS’ as arguments (L21.2#118-122) and writes the file to the
client. If ‘fileExists’ evaluate to false then the else block is executed (L21.2#123-126),
which informs the user that file is not found.

Method sendBytes
Method sendBytes takes the FileInputStream object bonded to the file on the server
that must be written to that client to which the second argument OutputStream is
connected (see Figure 21.14). The method simply reads the file on the server byte-
by-byte and then writes it to the client. However, for efficiency purpose, we do not
write to the client byte-by-byte. Rather we build a buffer of 1024 bytes. This buffer
is first filled with bytes from the input file, and then it is emptied as it is written to
the client. One version of read method of FileInputStream takes a byte array as
argument and fills the array with the data from the file being read (L21.2#168). If
end of the file is reached then the method returns an integer -1 value. Therefore the
file reading loop exits as soon as the end of file being read is reached. If end of file is
not reached then the read method returns the number of bytes pumped into the
buffer. The code in the scope of while loop uses the overloaded instance method

Chapter 21 Networking (Singhal) Page 33 of 36


write of class DataOutputStream to write to the client (L21.2#169). This method
takes three arguments in the following order: The buffer (which is a byte array), an
integer as an offset, and number of bytes to be written. The offset is the value of the
array index from where the writing would begin. This allows one to discard some
bytes that are in the front of the array, if needed. In this case we do not wish to
discard any bytes, so we choose the offset to be zero. When the loop exits, the file is
written to the client.

Using the class HttpRequest


Using the above class to build a multi-threaded server is rather easy. We write the
class HyperTextServer, whose source code is shown in the Listing 21.3.
00007 import java.net.*;
00013 public class HyperTextServer
00014 {
00022 public static void main(String[] args)
00023 {
00024
00025 ServerSocket Listener_Socket = null;
00026 int port = 2468; //select a number > 1123
00027 try
00028 {
00029 //Establish the listener socket
00030 Listener_Socket = new ServerSocket(port);
00032 //Process HTTP service requests in an infinite loop
00033 while(true)
00034 {
00035 //listen for TCP connection request
00036 //Construct an object to process the HTTP request message
00037 HttpRequest Request = new HttpRequest(Listener_Socket.accept());
00038 Thread TH = new Thread(Request);
00039 TH.start();
00040 System.out.println ("Server is active.");
00041 }
00042 }
00043 catch(Exception ex)
00044 {
00045 ex.printStackTrace();
00046 }
00047 }
00048 }
//Listing 21.3
Inside the main method, a ServerSocket reference Listener_Socket is declared and a
port number, on which server would listen is chosen (L21.3#25-26). The code to
instantiate the Listener_Socket is placed inside a try block as the constructor of
class ServerSocket could throw a checked exception. Listener_Socket is instantiated
at the port number port (L21.3#30). Then we put rest of the code to get request from

Chapter 21 Networking (Singhal) Page 34 of 36


a client and fulfilling client request inside a while loop that run infinitely, unless the
program is shut down by keyboard input (for example using Control + C on
windows in this case). The purpose of running the server code inside an infinite loop
is to always be listening for client requests on the port number assigned to the server
(in this case 2468). An object of class HttpRequest is created by passing to its
constructor, the Socket object, returned by the instance method ‘accept’ of class
ServerSocket. As mentioned before, the ‘accept’ method blocks (waits and listens)
until the client request is received (L21.3#37). If no client request is received then
code actually freezes at the line:

HttpRequest Request = new HttpRequest (Listener_Socket.accept());

However, as soon as the client request is received, the above line is executed and a
Request object is created. Since Request is a Runnable, we pass it as an argument to
the Thread class constructor to create a Thread of control to fulfill the current client
request (L21.3#38). Then we call the start method of Thread TH, in order to execute
the run method, which from previous description, we know calls the processRequest
method to fulfill client request. The loop process continues unless an exception is
thrown or server is shut down.

Test Results
We test our web server locally, so that client and server both reside in the same
computer. In this situation the IP address of the server is:

http://localhost:portNumber

Assuming that we wish to get a file from the server called index.htm then complete
client request string using a web browser would be (in this case),

http://localhost:2468/index.htm

While server is running, we can launch any of our browsers and type the above
address in it to display the file index.htm. Make sure that you run the application
from command line, as some times the default directory that an IDE like Netbeans
would look for is different from the folder where main class is located. In this case it
just so happens that in file index.htm I placed html format of my Multithreading
lecture, and web browser simply displays that. Read sidebar 21.2 for comments on
servers written purely in Java.
Sidecar 21.2: Server Software Engineering and Java
Although most industrial strength servers, such as Apache (the most successful
server) are written in C, recent release of a purely Java based server called Jigsaw
by the w3 organization (www.w3.org) has proven that good quality web servers can
be written using Java. W3 organization cites following examples of using a pure
Java server:
• A multithreaded server that is portable

Chapter 21 Networking (Singhal) Page 35 of 36


• Automatic garbage collection
• Dynamic architecture

Chapter 21 Networking (Singhal) Page 36 of 36


CS 23: Advanced Java
Chapter 23: Servlets and Java Server Pages
Or
Presenting dynamic web content
Author: Satish Singhal Ph. D.
Version 1.0 (November 2004)

With the advent of Internet and HTTP protocol, servers around the world became
able to publish static web content for clients connecting from disparate geographical
locations. There was, however a problem with static web pages. For example a
weather reporting web site could not (with out difficulty) build a web page of
changing weather conditions every few hours and host it as an HTML file for the
client. Similarly the web site that updates stock quotes also could not update
changing prices by means of static HTML pages as often as the investors need it to
make buying and selling decisions. (People had to depend upon TV, radio, and stock
quote ticker devices for that). What was needed was a technology that can rebuild
the web pages as the client request or as the data to be displayed changed. Java
applets could in fact present information dynamically. Therefore early on there was
a tremendous enthusiasm for them (including their use in a technology called “push
technology”, which died rather quickly). Java applets however, are client side
technology and not as reliable as the server taking the control of updating the
information. What was needed was a layer of software between the client and HTTP
server, which can run programs on the server to generate web pages on the fly in
the light of fast changing data and customer request for it. This was first
accomplished by CGI (common gateway interface), in which a directory on the
server, cgi/bin became repository of programs to run, when a client request needed
the dynamic information. The program would get the information, generate an html
page on the fly and serve it to the customer. One example of this is as follows: Let us
assume that client is flying from Dallas to New York and needs to know current
weather conditions at the destination. The client would make a request to the
weather web site, the web site will run a cgi program to get the current weather
data, build an html page and display to the client.

The problem with cgi was that if 15 clients are asking for the same information at
the same time, the server had to fork a new process of the cgi program and serve the
clients. This became expensive in terms of server resources. (Imagine the overhead
of running 15 copies of the same program at the same time). Business to consumer
(B-to-C) web sites presented another new challenge. By now you know that HTTP is
a stateless protocol. HTTP does not remember anything about the client from the
previous session because serving each web page starts a new session. On an e-
commerce web site client may visit a web page, look at the products on it, put items
on their shopping cart and then move to next web page to do more shopping. How

Topic 23 Servlets and Java server Pages (Singhal) Page 1 of 42


must the data on client’s shopping cart be carried from one page to another? In
other words, how should the client’s visit to the web site be turned into a session,
rather then a single HTTP request? Cgi and other sever side technologies, such as
Active Server pages (ASP) by Microsoft were able to handle aforementioned
requirements, though they had many limitations. Some of these limitations
included:
• Lack of efficiency
• Inconvenient to use
• Not scalable to large number of client requests
• Non-portable
• Not secure enough
• Expensive
• Tied to certain server side operating system.
Sun belatedly introduced its own technology called servlets and Java Server Pages
(JSP) to improve upon the above limitations. Though it required fair amount of
development, the technology has matured and many of the above limitations have
been overcome. Incidentally, ASP that was developed by Microsoft has been
replaced by them in favor of a more robust technology called ASP.Net that uses
Java like language C#. In other words ASP.Net is Microsoft’s counterpart to
Servlets and Java server pages1.

Servlets and JSP are two faces of the same technology. Servlets either implement
interface javax.servlet, or extend a class that already does that. JSP pages have
HTML and Java code embedded in them, which are compiled into a servlet. Java
packages javax.servlet and javax.servlet.http contain necessary classes to write
servlets. The inheritance hierarchy of abstract class HttpServlet that is extended to
write servlet classes is shown by the Figure 23.1.

1
It is extremely saddening and maddening that all these robust e-commerce technologies (JSP and
ASP.Net) arrived after dot com crash, which slowed the growth of e-commerce to a crawl. In the
meantime the e-commerce vision promoted to customers turned bleak. This is perhaps a starkest
example of how over-hyped technologies do incalculable harm to prospects of building new
businesses and distribution channels.

Topic 23 Servlets and Java server Pages (Singhal) Page 2 of 42


FIG. 23.1
The abstract class HttpServlet derives from GenericServlet and it also implements
the interface Serializable. The syntax for writing a user-defined servlet class is
rather simple:

public class MyServlet extends HttpServlet


{
// code
}

Table 23.1 gives a summary of methods inherited by the class HttpServlet from its
super-classes (excluding the Object class).
Method Summary For class HttpServlet
protected doDelete(HttpServletRequest req, HttpServletResponse resp)
void Called by the server (via the service method) to allow a servlet to
handle a DELETE request.
protected doGet(HttpServletRequest req, HttpServletResponse resp)
void Called by the server (via the service method) to allow a servlet to
handle a GET request.
protected doHead(HttpServletRequest req, HttpServletResponse resp)
void Receives an HTTP HEAD request from the protected service method
and handles the request.

Topic 23 Servlets and Java server Pages (Singhal) Page 3 of 42


protected doOptions(HttpServletRequest req, HttpServletResponse resp)
void Called by the server (via the service method) to allow a servlet to
handle a OPTIONS request.
protected doPost(HttpServletRequest req, HttpServletResponse resp)
void Called by the server (via the service method) to allow a servlet to
handle a POST request.
protected doPut(HttpServletRequest req, HttpServletResponse resp)
void Called by the server (via the service method) to allow a servlet to
handle a PUT request.
protected doTrace(HttpServletRequest req, HttpServletResponse resp)
void Called by the server (via the service method) to allow a servlet to
handle a TRACE request.
protected getLastModified(HttpServletRequest req)
long Returns the time the HttpServletRequest object was last modified,
in milliseconds since midnight January 1, 1970 GMT.
protected service(HttpServletRequest req, HttpServletResponse resp)
void Receives standard HTTP requests from the public service method
and dispatches them to the doXXX methods defined in this class.
void service(ServletRequest req, ServletResponse res)
Dispatches client requests to the protected service method.
Methods inherited by class HttpServlet from class GenericServlet
destroy, getInitParameter, getInitParameterNames, getServletConfig,
getServletContext, getServletInfo, getServletName, init, init, log, log

Table 23.1
For class MyServlet to do anything useful, it must override, at least one of the
following super-class methods:
• doGet, if the servlet supports HTTP GET requests
• doPost, for HTTP POST requests
• doPut, for HTTP PUT requests
• doDelete, for HTTP DELETE requests
• init and destroy, to manage resources that are held for the life of the servlet
• getServletInfo, which the servlet uses to provide information about itself.
You would recall that GET, POST, PUT, OPTIONS, TRACE, HEAD, and
DELETE are HTTP methods, whose brief summary we discussed in the chapter on
Networking. Therefore the HttpServlet class includes methods to handle all these
methods that may be embedded in the client request. Each such method is of type
doxxx, for example doGet, doPost etc.

Similar to applets, sockets, and threads, servlets also have a typical life cycle.
However, before we discuss that, we need to understand another concept called
“servlet container”. The servlet container is to servlet, what a browser is to a Java
applet. You would recall from chapter on Java applets that browser called the init
method to initialize the applet, start method to start it, stop method to stop it from

Topic 23 Servlets and Java server Pages (Singhal) Page 4 of 42


running, and finally the destroy method to dispose it and free its resources. The
servlet container performs similar management for the servlet. The servlet
container is a compiled and executable program2. It is a middleware between the
client and server and it contains the servlet objects needed to provide dynamic web
pages. Understand that web server can function in a dual mode. It can handle static
html request by itself, whereas it can direct the dynamic content request to the
servlet container which in turn would invoke the servlet to build and serve that
content. In that sense the servlets work like little software robots, programmed to do
something and keep doing it during their lifetime. There are servlet containers now
available that also work as a full-fledged web server. One example of this is Jakarta
Tomcat server built by Apache Foundation3. Servlet containers acting as
middleware can be hosted on the same physical machine on which the web server is
located or on another machine.

The servlet life has three phases:


• Initialization
• Service
• Destruction
Figure 23.2 shows these three phases schematically.

FIG 23.2

2
Older name for a servlet container is servlet engine.
3
See www.apache.org. At the time of this writing the specific link to the Tomcat page is:
http://jakarta.apache.org/tomcat/index.html

Topic 23 Servlets and Java server Pages (Singhal) Page 5 of 42


Our servlet robot comes to life when it is initialized and resources are loaded into it.
From Table 23.1 you would see that super-class GenericServlet has overloaded
method ‘init’. The init method is invoked to create and initialize a servlet. This is
similar to the way in which browser calls the init method for an applet. Java API
describes the functioning of init method as follows:
“Init is called by the servlet container to indicate to a servlet that the servlet is being
placed into service. The servlet container calls the init method exactly once after
instantiating the servlet. The init method must complete successfully before the servlet
can receive any requests. The servlet container cannot place the servlet into service if the
init method

1. Throws a ServletException
2. Does not return within a time period defined by the Web server”

The second phase of a servlet’s life is service in which it can accept requests and
render responses to them (Figure 23.2). It does so through objects of two other
classes: HttpServletRequest and HttpServletResponse. This is the reason why you
see that ALL doxxx methods in Table 23.1 take these two object types as arguments.
doxxx methods however are called by the method service which is an overloaded
method (Table 23.1). Java API describes the public version of service method as
follows:

“service is called by the servlet container to allow the servlet to respond to a request.
This method is only called after the servlet's init() method has completed successfully.
The status code of the response always should be set for a servlet that throws or sends an
error. Servlets typically run inside multithreaded servlet containers that can handle
multiple requests concurrently. Developers must be aware to synchronize access to any
shared resources such as files, network connections, and as well as the servlet's class and
instance variables.”

Just like the Java applets are destroyed after browser is closed to dispose resources
used by them, servlets are also destroyed when it is removed from the container.
Container does that by calling the destroy method (Table 23.1). None of the
following methods: ‘init’, ‘service’, or ‘destroy’ need be called directly by the servlet
writer as the container does that automatically. Nor is there a need to override these
methods in the class extending HttpServlet.

Servlets Handling Many Requests at the Same time


By now we are aware that if there are multiple clients connecting to the web server,
the server handles them by multithreading, i. e. by creating a thread of control for
each client. If many clients need the information that could be provided by the
“same” servlet, then all such client threads share the resources of that servlet
simultaneously. Figure 23.3 shows this situation schematically.

Topic 23 Servlets and Java server Pages (Singhal) Page 6 of 42


FIG. 23.3
The thread has the access to the single instance of the servlet whose state was
initialized when it was loaded.

Writing and Testing your servlets


So far in this book we have given code examples, that are not dependent on Java
IDE you may have been using, or on operating system you are testing your
applications on. In fact so far you could (if you had to) learn Java by installing Java
SDK and using a notepad type editor. Unfortunately our lone ranger journey now
comes to an end. To test servlets we need either a servlet container connected to a
web server, or a stand-alone server that would have both. From teaching point of
view any bundling with ever changing commercial or even open source products is
undesirable. However, at the time of this writing open source IDE Netbeans is in
advanced enough stage that one could build and test web applications using servlets
and JSP entirely inside it, with out having to grind through the grueling details of
server management, since all you are interested is in testing your servlets. Server
and servlet container Jakarta Tomcat comes integrated as part of Netbeans IDE,
which can be used to test servlets and JSP projects entirely with in IDE. One
limitation Tomcat has however is that it cannot be used to develop and test
Enterprise Java beans (EJB). Sun has recently released free download of their Java
System Server application 8, which can be used to develop and test the following
applications:
• Enterprise applications
• EJB modules
• Web applications including servlets and JSP
At the time of this writing one can download bundled Netbeans and Java System
applications Server (JSAS) 8 from the following link:

http://java.sun.com/j2ee/1.4/download.html#nb

If in future this link is dead then you may go to general site java.sun.com and look
for Netbeans bundled with JSAS. (In fact Netbeans 4.1 would have Java System
Server application 8 or higher integrated into it). The download page would have
installation notes and release guide. It would be best to print this guide after the

Topic 23 Servlets and Java server Pages (Singhal) Page 7 of 42


download completes and before you begin installation. The installation details are
described in the appendix.

We now proceed assuming that you successfully installed the Netbeans and JSAS.
First we show as how to build a servlet example. The following description applies to
Netbeans 3.6.
1. Start Netbeans IDE.
2. If you have any previous file systems mounted then un-mount them. Your file
systems tab should be clear (Figure 23.4A).

No files mounted.

FIG. 23.4A
3. For the illustration purpose we create a folder on our C directory called
J2EE.
4. Mount this file system in Netbeans. Right click on Filesystems and then on
mount/Local Directory (Figure 23.4B).

FIG. 23.4B
5. Then navigate to the folder J2EE and click on finish. (Do not open this
folder). Once it is mounted, it would look like Figure 23.4C.

Topic 23 Servlets and Java server Pages (Singhal) Page 8 of 42


FIG. 23.4C
6. Right click on folder C:\J2EE in the FileSystems node and from Tools menu
choose the menu “Convert Filesystem into Web Module (Figure 23.4D).

FIG. 23.4D
7. Once you have done that the Filesystems node will change as shown in Figure
23.4E.

Topic 23 Servlets and Java server Pages (Singhal) Page 9 of 42


1. Node used to write JSP
pages.

2. Node used to
write servlets

FIG. 23.4E
8. Netbeans creates an additional node which can be used to write servlets.
Right click on the node pointed by the bubble #2 in Figure 23.4E and then
click on New and then on Servlet (Figure 23.4F).

FIG. 23.4F
9. After last step a popup menu similar to the Figure 23.4G will open up.

Topic 23 Servlets and Java server Pages (Singhal) Page 10 of 42


FIG. 23.4G
10. When you develop servlets for your enterprise, it would be advisable to have
them in package that uses the reverse domain name system for naming the
packages. For example my company’s domain name is Gandhi.net, so I could
keep my servlets in package net.gandhi.servlets. Suppose the name of servlet
being developed here is Hello, then the name to be filled in the class Name
text box would be net.gandhi.servlets.Hello (Figure 23.4H).

Topic 23 Servlets and Java server Pages (Singhal) Page 11 of 42


Fill fully qualified
name of servlet class

Location of the
servlet java and class
files

FIG. 23.4H
11. Notice that the path in the location text field has changed automatically. This
text field gives you path to the folder where your servlet Hello.java would be
created. In the popup box in Figure 23.4H click on finish. (Clicking on next
would give you other options, which we are not ready to investigate yet).
Netbeans creates the servlet class Hello.java and fills in its method headers
and some code automatically. If you would now expand the node
C:\J2EE :/WEB-INF/classes fully, it would look like the Figure 23.4J

Topic 23 Servlets and Java server Pages (Singhal) Page 12 of 42


FIG. 23.4J
You can see that Netbeans automatically added the super-class HttpServlet methods
destroy, doGet, doPost, getServletInfo, and init in your class Hello.java. The method
processRequest is a helper method inside which the executable code is placed.
Listing 23.1 shows the Hello.java created for you by Netbeans.
/*
* Hello.java
*
* Created on December 1, 2004, 9:00 AM
*/

package net.gandhi.servlets;

import java.io.*;
import java.net.*;

import javax.servlet.*;
import javax.servlet.http.*;

/**
*
* @author authorised user
* @version
*/
public class Hello extends HttpServlet {

/** Initializes the servlet.

Topic 23 Servlets and Java server Pages (Singhal) Page 13 of 42


*/
public void init(ServletConfig config) throws ServletException {
super.init(config);

/** Destroys the servlet.


*/
public void destroy() {

/** Processes requests for both HTTP <code>GET</code> and


<code>POST</code> methods.
* @param request servlet request
* @param response servlet response
*/
protected void processRequest(HttpServletRequest request, HttpServletResponse
response)
throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter(); 1. This portion must be
/* TODO output your page here uncommented and modified
out.println("<html>"); to display the web page per
out.println("<head>"); specification.
out.println("<title>Servlet</title>");
out.println("</head>");
out.println("<body>");

out.println("</body>");
out.println("</html>");
*/
out.close();
}

/** Handles the HTTP <code>GET</code> method.


* @param request servlet request
* @param response servlet response
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}

/** Handles the HTTP <code>POST</code> method.


* @param request servlet request

Topic 23 Servlets and Java server Pages (Singhal) Page 14 of 42


* @param response servlet response
*/
protected void doPost(HttpServletRequest request, HttpServletResponse
response)
throws ServletException, IOException {
processRequest(request, response);
}

/** Returns a short description of the servlet.


*/
public String getServletInfo() {
return "Short description";
}
}
//Listing 23.1
The Listing 23.1A would compile and run, however it will produce no output as the
code to do so is yet to be added. In this scheme the code to produce a web page is
added in the method processRequest. If you see the pre-generated code for this
method, the commented portion has the basic HTML tags already placed for you.
You would also see that processRequest method is called by class methods doGet
and doPost. You would recall the meanings of HTML tags from our chapter on Java
Applets. Before we go further we need to explain as to how servlets write web pages.

Servlets produce web pages by embedding HTML tags and content displayed by
them as strings passed as argument to the method println. In method
processRequest the PrintWriter object out is created by calling the getWriter
method of HttpServletResponse object response. This class inherits this method
from its super-class ServletResponse. The Java API description of getWriter
method is given in Figure 23.5.
public java.io.PrintWriter getWriter( ) throws java.io.IOException
Returns a PrintWriter object that can send character text to the client. The
PrintWriter uses the character encoding returned by getCharacterEncoding(). If the
response's character encoding has not been specified as described in
getCharacterEncoding (i.e., the method just returns the default value ISO-8859-1),
getWriter updates it to ISO-8859-1.
Calling flush() on the PrintWriter commits the response.
Either this method or getOutputStream() may be called to write the body, not both.
Returns:
a PrintWriter object that can return character data to the client
Throws:
UnsupportedEncodingException - if the character encoding returned by
getCharacterEncoding cannot be used
java.lang.IllegalStateException - if the getOutputStream method has already been
called for this response object
java.io.IOException - if an input or output exception occurred
See Also:

Topic 23 Servlets and Java server Pages (Singhal) Page 15 of 42


getOutputStream(), setCharacterEncoding(java.lang.String)
FIG. 23.5
Notice the highlighted portion of the method description in above Figure. If only a
character stream is to be written to the client then one creates a PrintWriter type
object by calling the method getWriter. However, if you wished to write content to
the client that would include binary files (such as gif, jpeg etc.), you would call the
method getOutputStream for the HttpServletResponse object. In fact this situation
is analogous to when we created writer objects for server side sockets. For writing
just the text data we created a PrintWriter, whereas to write binary data we had to
create an object of type OutputStream. The method getOutputStream of
HttpServletResponse returns an object of type ServletOutputStream, which is a
subclass of java.io.OutputStream.

In Listing 23.1 if we uncomment the portion pointed to by bubble #1, we get the
basic headers in place to print an HTML page. Whatever we wish to display on our
web page must now be placed inside the tags <body> and </body>. Let us assume
that we wished to say hello to the user from our domain and print the day, date, and
time. The line saying hello would be composed as follows:

out.println (“Hello from Gandhi.net <BR>”);

The above line gets printed on the web page served by our servlet called Hello just
the way a regular HTML page would.

In order to print day, date and time, would need to create an instance of class
java.util.Date and pass that to the method println. This is done by the following code
line.

Out.println (“Date and time are: “ + new java.util.Date() + “<BR>);

Compiling and testing your servlets.


You can compile your servlet class either from command line or from Netbeans
environment. In the latter, just press F9 to compile. Alternatively, you can click on
build menu and then click on compile. If after compilation, there are no errors, then
you can run your servlet by pressing F6 or clicking on Build and then on Execute in
the menu. When you do that JSAS begins to run automatically and it would show a
progress bar similar to Figure 23.5.

Topic 23 Servlets and Java server Pages (Singhal) Page 16 of 42


FIG. 23.5
The program would automatically open your default browser and display the
HTML page generated by the servlet. The output of Listing 23.1 modified by un-
commenting the portion pointed to by the bubble #1, and adding the above
discussed two println statements is shown by Figure 23.6.

Notice
the URL

FIG. 23.6
Notice the URL used by the browser. The IP address used is localhost:1168. This
shows port number to be 1168. However, JSAS may be shown to be running on a
different port in the Runtime tab in Netbeans environment. If you copy the above
web address into any other browser on your system, you would get similar results.

Response and Request Objects


We saw in discussion of Listing 23.1 that object of type HttpServletResponse can be
used to get a PrintWriter type object to write the character stream or an
OutputStream type of object to write byte stream to the client. The object of type
HttpServletRequest does the opposite. It can read byte or character streams from
the client request. You can easily see a pattern here. When we did file I/O we needed
java.io.Writer type object to write to the file and java.io.Reader type to read from it.
When we dealt with sockets in the networking chapter we saw the Socket type
objects on both server and client side had methods that provided us the Reader and
Writer type objects. That enabled intercommunication between client and server as

Topic 23 Servlets and Java server Pages (Singhal) Page 17 of 42


easily as if we were dealing with file I/O. Same situation exists here. The servlet can
use an HttpServletResponse object to write to client (in this case furnishing an
HTML page), and an HttpServletRequest page to accept client input when client is
on a certain web page. This is the beauty of Java. The pattern for file I/O, client
server communication using sockets or servlets – all obey the same design pattern.
In Listing 23.1 we saw the action of HttpServletResponse object where an HTML
page was created for the client on fly. Similarly the HttpServletRequest object can
parse the information submitted by the client, examine it and then supply that
information to create web page pursuant to it. Before we can see the action of
HttpServletRequest object, we need to understand as to how HTML forms (which
are one way to submit data to the server) work. HTML forms collect data from the
client and pass it to the server. In order to create a form an HTML tag pair
< form > and </form> is available. As you would recall some tags have attributes.
These attributes have names and values. In HTML 4.01 followings4 are the
attributes available for the form tag.
• Action – specifies the destination server or agent which will process the form
data.
• Method – specifies as to which HTTP method would be used to process the
form data. The possible methods are GET and POST. If method attribute is
skipped then by default the GET method is used.
• enctype – Tells the browser as to how to encode the information when the
method attribute is POST.
• accept-charset - specifies the list of character encodings for input data that is
accepted by the server processing this form. The value is a space- and/or
comma-delimited list of charset values.
• accept - specifies a comma-separated list of content types that a server
processing this form will handle correctly.
• Name - names the element so that it may be referred to from style sheets or
scripts.
Let us assume that we plan to build a web page that would submit the data to our
Servlet Hello whose basic structure is coded in Listing 23.1. (Obviously it would be
modified further if we wish it to do more). Also you would recall that when using an
HTML tag, you are not bound to provide the values of all attributes. Therefore the
syntax of the form tag that we would plan to submit to our servlet would be as
follows:

<form Action=’http://IP address: port number/Path to the servlet’ Method =


GET>
<!-- Place the HTML to create the form here -->
</form>
As we mentioned earlier, the method attribute can have two values, either GET or
POST. The server executes, either of those two HTTP method depending upon the
value provided in the form tag. There is a difference in the way in which the

4
http://www.w3.org/TR/html401/interact/forms.html

Topic 23 Servlets and Java server Pages (Singhal) Page 18 of 42


browser provides the information contained in the form to the server. When GET is
used, then browser appends all the information from the form in the URL string
that it sends to the server. Mechanism of this would not be clear with out actually
building an HTML form and illustrating as to how this works. Let us assume that
we wish the user to provide the following pieces of information on an HTML form.
• First name
• Last name
• Pick one of their favorite colors from choices provided in a group of radio
buttons.
• Pick one or more of their favorite food(s)/drink(s) from the choices provided
by number of check boxes.
Obviously the first two needs some sort of text input boxes. The third item needs a
way to create radio buttons and group them together, and last item needs check
boxes created. The HTML tag that is used to create text input box is simply <input>
and it does not need a closing tag. It can have many attributes; however, we are only
interested in two of them – the type and name. For simple text input the type is text,
and name is whatever name we wish to give to the string variable that would be
typed in the text box. For example if we wish to create a text box for the user to type
their first name, then the HTML tag written as below would do that.

<input type=’text’ name=’firstname’ value=’Type your first name’>


This HTML line placed in a proper HTML page would look as given in Listing
23.2A.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title></title>
</head>
<body><BR>
First Name:
<input type='text' name='firstname' value='Type your first name'><BR>

1. Tags to create radio buttons

2. Tags to create check boxes

3. Tag to create the submit button

</body>
</html>
<!—Listing 23.2A Æ
The HTML page created by the browser from Listing 23.2A is shown in Figure
23.7A.

Topic 23 Servlets and Java server Pages (Singhal) Page 19 of 42


FIG. 23.7A
Similarly, let us assume that we wish to provide the user a list of colors, from which
they are expected to pick one as their favorite then we use the radio buttons. In
HTML the radio buttons are also provided by the input tag, except the type of tag
become radio. To group the radio buttons together we provide the same value for
the name attribute for all of them. Since in this case browser would need to tell the
server as to what value is being chosen when the user clicks on a certain radio
button we need to provide a binding value as well. The syntax for writing a radio
button that would be clicked by the user whose favorite color is pink is given below.

<input type =’radio’ name='radio1' value='Pink'>Pink<BR>


The word Pink outside the pair of angular brackets simply displays the name
assigned to the radio button to display on the web page. When the above line is
added at the location shown by first box in the Listing 23.2A, then our web page
looks like Figure 23.7B.

FIG. 23.7B
Understand that since we wish to group all radio buttons together; they will all have
the same value (radio1) for the name attribute. In order to create check boxes, the
type attribute is given a value ‘checkbox’. Since user can check mark more than one

Topic 23 Servlets and Java server Pages (Singhal) Page 20 of 42


box, they all need different values for the name attribute. Finally as to what value
for that check box will be passed to the server needs to be added as part of overall
tag. The syntax for creating a check box is shown below.

<input type =checkbox name = 'check1' value='kimchi'>Kimchi<BR>

When the above HTML line is added at the location shown by the box#2 in Listing
23.2A, then the web page interpreted by the browser is shown by Figure 23.7C.

FIG. 23.7C
Finally we show the syntax for creating a button that user can click to submit the
data they typed or chose on the web form. To create a submit button for the input
tag the type is submit. The syntax is as follows:

<input type= submit >

When the above HTML tag is placed at the location shown by the box#3 in Listing
23.2A then the browser interprets the whole code as shown in Figure 23.7D.

FIG. 23.7D

Topic 23 Servlets and Java server Pages (Singhal) Page 21 of 42


If a radio button or check box must be presented to the user as pre-selected then the
status ‘checked’ is added inside the input tag. For example if the pink color radio
button must be presented as pre-selected then the HTML tag for it would be
modified as given below.

<input type =radio name='radio1' value='Pink' checked >Pink<BR>

Pre-selects the radio button Pink.

Similarly one can add the status checked to all the check boxes that must be pre-
selected. The latest version of HTML also allows one to add tool tip text to all input
components. This is done simply by adding the attribute title and the tool tip string
as the value of this attribute. For example we may wish that when user places the
mouse over check box Kimchi, then tool tip shows the message: “ Click here if your
favorite food is Kimchi”, then the HTML tag to create Kimchi check box changes as
follows:

<input type =checkbox name = 'check1' value='kimchi'


title=’ Click here if your favorite food is Kimchi ‘>Kimchi<BR>

Figure 23.7E shows the tool tip created by adding the title attribute.

FIG. 23.7E
Listing 23.2B shows the HTML file Gandhi_index.html that we create to submit the
form data entered by the user to the modified servlet Hello.
<html>
<head><title>Home Page of Gandhi Software</title></head>
<body>

<center><h1><font color='red'>Welcome to the web site of Gandhi Software</font></h1><BR>


<B>Please fill out the form below and then press Submit Query button at the

Topic 23 Servlets and Java server Pages (Singhal) Page 22 of 42


bottom!</B><BR><BR>
1. Form tag. Notice the values of
action and method attributes.

<Form action='http://66.27.200.112:1168/j2ee/Hello' method=GET>


First Name:
<input type=text name='firstname' value='Type your first name' title='Please type your first name
here'><BR><BR>
Last Name:
<input type=text name='lastname' value='Type your last name' title='Please type your last name
here'><BR><BR>
<B><U>Please choose your favorite color:</U></B><BR><BR>

<input type =radio name='radio1' value='Pink' checked title='Click if your favorite color is pink'>
<Font color='black'>Pink </font>
<input type =radio name='radio1' value='Magenta' title='Click if your favorite color is Magenta' >
<Font color='magenta'>Magenta </font>
<input type =radio name='radio1' value='Blue' title='Click if your favorite color is blue'>
<Font color='blue'>Blue </font>
<input type =radio name='radio1' value='Green' title='Click if your favorite color is green' >
<Font color='green'>Green </font>
<input type =radio name='radio1' value='Cyan' title='Click if your favorite color is cyan' >
<Font color='black'>Cyan </fonr>
<input type =radio name='radio1' value='White' title='Click if your favorite color is white'>
<Font color='black' >White </font>
<input type =radio name='radio1' value='Orange' title='Click if your favorite color is orange' >
<Font color='orange' >Orange </font>
<input type =radio name='radio1' value='Yellow' title='Click if your favorite color is yellow'>
<Font color='black' >Yellow </font>
<input type =radio name='radio1' value='Burgundy' title='Click if your favorite color is burgundy'>
<Font color='black'>Burgundy</font><BR><BR><BR>

<B><U>Please checkmark all your favorite foods and or drinks from the list given below:
</U></B><BR><BR>

<input type =checkbox name = 'check1' value='kimchi' title='Click if your favorite food is Kimchi'>
Kimchi
<input type =checkbox name = 'check2' value='Felafel' title='Click if your favorite food is Felafel'>
Felafel
<input type =checkbox name = 'check3' value='Cheeseburger'
title='Click if your favorite food is Cheese Burger'>Cheese Burger
<input type =checkbox name = 'check4' value='Curry' title='Click if your favorite food is Curry'>
Curry
<input type =checkbox name = 'check5' value='PolishHam'
title='Click if your favorite food is Polish Ham' checked>Polish Ham
<input type =checkbox name = 'check6' value='Vodka' title='Click if your favorite drink is Vodka'>
Vodka
<input type =checkbox name = 'check7' value='Chowmin'
title='Click if your favorite food is Cowmin'>Chowmin<BR><BR>

<input type= submit title='Press to submit the form'>

Topic 23 Servlets and Java server Pages (Singhal) Page 23 of 42


</form>
</center>
</body>
</html>
<--Listing 23.2B Æ
In Listing 23.2B, bubble #1 shows the HTML form tag whose action attribute has
the value giving the information in this order (Figure 23.8) :
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
'http://66.27.200.112:1168/j2ee/Hello'

Protocol
Web address Path to servlet and servlet
name
Port number

FIG. 23.8
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
The HTTP method we use in Listing 23.2B is GET. Later on we show the use of
method POST. Following the form tag we have two input tags to create two text
input boxes for the user to enter their first and last names. Then the lines
highlighted in yellow shows the code for placing all the radio buttons that are
grouped together. Then the lines highlighted in cyan show the code for placing
check boxes. Finally the line before the closing form tag shows the source code for
placing a submit button. When the user presses the submit query button the form
data would be sent to the URL listed in the action attribute using the method GET.
Figure 23.9 shows the form created by the Listing 23.2B in the web browser. The
look and feel would be slightly different in the Internet Explorer and Mozilla
Firefox browsers.

Topic 23 Servlets and Java server Pages (Singhal) Page 24 of 42


FIG. 23.9
There are two ways in which you can test the HTML pages you write. One is by
simply opening the HTML file in the test browser. In Netbeans environment with
JSAS installed, you can simply press F6 after saving the file. JSAS would open serve
the HTML file in the browser that is already opened or it would open a default
browser window. Let us assume that we fill the following information the form
shown in Figure 23.9:
First Name: Satish
Last Name: Singhal
Favorite Color: Cyan
Favorite foods: Felafel, Curry, and Polish Ham.
And after filling form as above the submit query button is pressed. Then the form is
submitted to the web server with the following URL string:

http://66.27.200.112:1168/j2ee/Hello?firstname=Satish&lastname=Singhal&radio1=
Cyan&check2=Felafel&check4=Curry&check5=PolishHam

When GET method is used to submit a form, then the browser sends all form
parameter to the web server by appending them to the URL it sends. In above URL
string all the form parameters entered by the user are appended after the question
mark ?. For example:
firstname=Satish and lastname=Singhal etc. For each parameter the browser send
the name of the parameter and its value entered by the user. Each set is separated

Topic 23 Servlets and Java server Pages (Singhal) Page 25 of 42


by the ampersand sign (&). This is a convenient way to send form data to the web
server. The limitation with using GET method, however is that length of URL string
must be below 256 characters. The web server can use the URL with user data in
variety of ways. It can parse the URL to get the data or it can submit the URL to the
servlet, which would parse it using its HttpServletRequest object. Now we are
beginning to see many options for building our web applications. Your web
applications may involve the following components depending upon the design you
choose.
• HTML pages
• Servlets
• JSP pages
Listing 23.2B shows an HTML page which calls a servlet.

Modified Servlet Hello and GET vs. POST methods


We modify out servlet called Hello, so that it can parse the user submitted form data
and create a web page that displays user’s first and last name, their favorite color,
the list of their favorite food(s) and drink(s), and finally the date and time. The
‘getParameter’ method of class HttpServletRequest is used to get the user inputted
parameters. Figure 23.10 gives the Java API description of getParameter method.
public java.lang.String getParameter(java.lang.String name)
Returns the value of a request parameter as a String, or null if the parameter does
not exist. Request parameters are extra information sent with the request. For
HTTP servlets, parameters are contained in the query string or posted form data.
You should only use this method when you are sure the parameter has only one
value. If the parameter might have more than one value, use
getParameterValues(java.lang.String).
If you use this method with a multi-valued parameter, the value returned is equal to
the first value in the array returned by getParameterValues.
If the parameter data was sent in the request body, such as occurs with an HTTP
POST request, then reading the body directly via getInputStream() or getReader()
can interfere with the execution of this method.
Parameters:
name - a String specifying the name of the parameter
Returns:
a String representing the single value of the parameter
See Also:
getParameterValues(java.lang.String)
//FIG. 23.10
‘getParameter’ method takes the string for the parameter name as argument and
then returns its value string. For example, in Listing 23.2B the parameter name
‘firstname’ is the name of text box in which user would enter their first name. The
servlet can use the code line such as below to access user inputted first name in the
text box:

String Name = request.getParameter (“firstname”);

Topic 23 Servlets and Java server Pages (Singhal) Page 26 of 42


In above code line the request is the instance of HttpServletRequest object. The
argument to getParameter method is the parameter name. The values of name
attributes for all input tags are parameter names that can be used as argument to
getParameter method. Following points are to be kept in mind when we use the
getParameter method to parse the data entered by the user in the form shown by
Figure 23.9.
• The user input for first name, last name and their favorite color can be
parsed by use of getParameter method the way it is shown above.
• When parsing the user input for the check boxes; because the possibility
exists for user marking more than one check box, it is needed that strings
returned by getParameter method be stored in an array. For example, in
Listing 23.2B, seven check boxes are coded. The code line like below would
parse user data as inputted through those check boxes.

String [ ] Choice = {request.getParameter (“check1”),


request.getParameter(“check2”), request.getParameter(“check3”),
request.getParameter(“check4”), request.getParameter(“check5”),
request.getParameter(“check6”), request.getParameter(“check7”)};

Obviously depending upon the choice made by the user, some members of array
Choice would be null and we would not need to print those. We can use a control
structure such as below to discern as to which one are those:

if (Choice[index] != null)
Print Choice [index] //index being the array index.
In order for the servlet hello to parse user inputted parameters from the web form
submitted to it, we just modify the method processRequest in Listing 23.1 as given
below (Listing 23.2B).
00039 protected void processRequest(HttpServletRequest request,
HttpServletResponse response)
00040 throws ServletException, IOException
00041 {
00042 response.setContentType("text/html");
00043 PrintWriter out = response.getWriter();
00044 out.println("<html>");
00045 out.println("<head>");
00046 out.println("<title>Servlet</title>");
00047 out.println("</head>");
00048 out.println("<body>");
00049
00050 out.println ("Hello " );
00051 String Name = request.getParameter("firstname");
00052
00053 if(Name !=null)
00054 out.println ("to " + Name +" ");
00055

Topic 23 Servlets and Java server Pages (Singhal) Page 27 of 42


00056 Name = request.getParameter("lastname");
00057
00058 if(Name !=null)
00059 out.println (Name +" ");
00060
00061 out.println ( " from Gandhi.net <BR>");
00062 Name = request.getParameter("radio1");
00063
00064 if(Name !=null)
00065 out.println("<U>Your favorite color is:</U> "+Name +"<BR>");
00066
String [] Str = {request.getParameter("check1"), request.getParameter("check2"),
00068 request.getParameter("check3"),request.getParameter("check4"),
00069 request.getParameter("check5"), request.getParameter("check6"),
00070 request.getParameter("check7")};
00071 out.println("<U>List of your favorite food(s)/drink(s):</U><BR>");
00072 if( Str[0]!=null)
00073 out.println(Str[0] + "<BR>");
00074 if( Str[1]!=null)
00075 out.println(Str[1]+"<BR>");
00076 if( Str[2]!=null)
00077 out.println(Str[2]+"<BR>");
00078 if( Str[3]!=null)
00079 out.println(Str[3]+"<BR>");
00080 if( Str[4]!=null)
00081 out.println(Str[4]+"<BR>");
00082 if( Str[5]!=null)
00083 out.println(Str[5]+"<BR>");
00084 if( Str[6]!=null)
00085 out.println(Str[6]+"<BR>");
out.println ("<U>Date and time are: </U>" + new java.util.Date() + "<BR>");
00087 out.close();
00088 }
//Listing 23.2B
We start to parse the data from user form on line # 51, where we get the value
entered in the text box for first name. If the first name entered is not null then we
print it on the web page to be displayed (L23.2B#53-54). We follow the same
procedure to display the non-null last name entered by the user (L23.2B#56-59).
Then we parse the value associated with the radio button chosen by the user
(L23.2B#62). Listing 23.2A shows that each radio button is associated with a color
name as its value attribute. We display the favorite color chosen by the user
(L23.2B#64-65). We need a different strategy for parsing the check boxes as user
could check mark, all, none, or any other number of check boxes in between. Thus
we create an array of string Str, where each member is the value attribute for each
check box. If we would like to get the value associated with the check box with name
as check1, it is returned to use by call request.getParameter (“check1”). The array

Topic 23 Servlets and Java server Pages (Singhal) Page 28 of 42


Str may have number of null elements from zero to the maximum array length. (It
would have zero null elements if user checked all the check boxes and all null
elements if user did not check any of them). Therefore we need a system of if control
structures to display only non-null elements of this array on the web page to be
served to the user. This is done by system of if statements (L23.2B#72-85). Finally
we print date and time and close the object HttpServletResponse (L23.2B#86-87).

Figure 23.11 shows the web page furnished to the user by the modified servlet Hello,
when the following entries are made in the form shown in Figure 23.9.
• First name : Satish
• Last name: Singhal
• Favorite color: blue
• Favorite foods: Felafel, curry, and Polish Ham.

FIG. 23.9
The URL that web page of Listing 23.2A submits to servlet is given below.

http://66.27.200.112:1168/j2ee/Hello?firstname=Satish&lastname=Singhal&radio1=
Blue&check2=Felafel&check4=Curry&check5=PolishHam

Notice that because we used the GET method to submit the form to the servlet, all
form data are appended to the URL after the question mark (?) in it. As we
mentioned earlier, there is a 255 character limit on HTTP URL’s. Therefore the use
of GET method to submit form data is not advisable if data in form would cross this
limit. In addition the URL displaying the form data is not a secure practice. In fact
it is possible to heck the form data when it is appended to the URL. For example if
we just add the string “&check6=WhoCares” to the end of URL shown above and
paste it in the web browser window and press enter, the web page produced (Figure
23.10) shows that displayed web page includes our hacked entry.

Topic 23 Servlets and Java server Pages (Singhal) Page 29 of 42


Hacked entry

FIG. 23.10
To overcome both these limitations we use HTTP method POST to submit the form
data. Using POST is deceptively simple. In fact you would not need to alter your
servlet code at all. All you need to do is, in Listing 23.2A, to replace word GET by
word POST in the line which has the form tag. For example the form tag would now
be changed as below.

<Form action='http://66.27.200.112:1168/j2ee/Hello' method=POST>

Rest of the code in Listing 23.2A and in servlet remains unchanged. Now when the
button Submit Query is pressed by the user the URL submitted to the servlet does
not include the parameter sent by the form, yet the functioning of servlet is
unaltered compared to when we used the GET method. One may ask as to what is
the advantage of using GET if POST (which has no problem with URL size and is
secure) works so well? The reason for using GET is that since it includes the
parameters in the URL string, such URL’s can be book marked by the user. This
provides one to do an instant search on the search engine such as Google.

JSP pages
We expressed that servlets and JSP are two faces of the same technology. Now we
would be able to illustrate that. We begin to see this equivalence, first studying the
similarity between the life cycle of a servlet and of a JSP page. Figure 23.11 shows
the events in the lifecycle of a JSP page. The various phases in its life cycle are as
follows:

Topic 23 Servlets and Java server Pages (Singhal) Page 30 of 42


1. JSP page is translated into a
servlet before being loaded.

FIG. 23.11
1. Translation: The JSP page is translated into a servlet before being loaded.
This translation included parsing the JSP page for servlet code and then
compiling the servlet. This is the reason that when first times a JSP page is
called by the browser when you test the page, there is a slight delay. The
servlet thus generated implements the interface
javax.servlet.jsp.HttpJspPage. This interface has the following methods,
which in turn are available to the servlet compiled from JSP page (Table
23.2).
Method Summary for HttpJspPage
void _jspService(javax.servlet.http.HttpServletRequest request,
javax.servlet.http.HttpServletResponse response)
The _jspService()method corresponds to the body of the JSP page.
Methods inherited from interface javax.servlet.jsp.JspPage
jspDestroy, jspInit
Methods inherited from interface javax.servlet.Servlet
destroy, getServletConfig, getServletInfo, init, service

Table 23.2

2. The JSP engine then instantiate the servlet.


3. Then the JSP engine initializes the servlet by calling the method ‘jspInit’.
This is the first method called by the engine and it is called only once during
the life time of servlet.

Topic 23 Servlets and Java server Pages (Singhal) Page 31 of 42


4. Request handling and service phase: Once initialized, the servlet is ready for
service. When requests are sent to the servlet, the method _jspService is
invoked by the engine and the request and response objects are passed to it.
The Java API gives the following description of _jspService method (Figure
23.12).
public void _jspService(javax.servlet.http.HttpServletRequest request,

javax.servlet.http.HttpServletResponse response)
throws javax.servlet.ServletException,
java.io.IOException
The _jspService()method corresponds to the body of the JSP page. This
method is defined automatically by the JSP container and should never be
defined by the JSP page author.

If a superclass is specified using the extends attribute, that superclass may choose
to perform some actions in its service() method before or after calling the
_jspService() method. See using the extends attribute in the JSP_Engine chapter
of the JSP specification.

Parameters:
request - Provides client request information to the JSP.
response - Assists the JSP in sending a response to the client.
Throws:
javax.servlet.ServletException - Thrown if an error occurred during the
processing of the JSP and that the container should take appropriate action
to clean up the request.
java.io.IOException - Thrown if an error occurred while writing the
response for this page.
FIG. 23.12
As long as servlet is loaded the method _jspService continues to handle client
requests.
5. Destruction: When the servlet is no longer needed, it is destroyed by the
engine by calling the method jspDestroy.
One can see that the life cycle of a JSP page created servlet is similar to the regular
servlet, except the different methods are called in the different phases of its life. Next
we describe as how to create a JSP project in Netbeans.

Topic 23 Servlets and Java server Pages (Singhal) Page 32 of 42


Creating a JSP project in Netbeans
First we illustrate the procedure for creating a JSP page in your web application
inside the Netbeans environment.
1. Click on the project tab in the project explorer.
2. Click on your web application folder to highlight it.
3. Then on File menu click on new. You will get a popup box similar to Figure
23.13. (Ignore the picture behind the popup box).

FIG. 23.13
Popup box presents all possible templates. Choose the template JSP (Figure 23.13).
Then click on next.
4. The next popup box (Figure 23.14) would prompt you to enter the name of
your JSP page.

Topic 23 Servlets and Java server Pages (Singhal) Page 33 of 42


FIG. 23.14
5. If you take the default name (index) and click on finish, Netbeans would add
a JSP page named index.jsp to your web application, whose location is given
in the Location display box at the bottom middle. It also creates a bare-bone
JSP page for you, which looks like Figure 23.15.

1. <%@page %>
t

2. JSP comment

FIG. 23.15

Topic 23 Servlets and Java server Pages (Singhal) Page 34 of 42


Just like HTML web page you can now fill your JSP code between the pair of tags
<body> and </body>.

JSP allows you to write regular HTML the way you write it to build static web
pages. However, it allows you to add JSP code, which would be compiled into a
servlet behind the scene. All5 JSP code is placed between a pair of angular brackets
<% and %> or

<% JSP code on one or more lines %>

You could have JSP code and HTML mixed together inside a .jsp file in the way in
which your design requires it. At runtime the servlet engine takes all the code
bounded in pairs of <% %> brackets and compiles it into a servlet to produce the
web page to be displayed by the jsp file. The elements <% and %> are considered
JSP operators6 and no space is allowed between them.

JSP tags
In order that JSP and HTML can co-exist in the same file JSP specification
introduced some special JSP tags. Two of them are already used in the Figure 23.13.
The bubble #2 shows the simple JSP comment. Any text (single or multi-line)
bounded in the pair of brackets given below

<%-- comment --%>


will be treated as a comment. Other JSP tags can be divided into following
categories:
1. Expressions to be evaluated and outputted ( <%= Expression %>).
2. JSP declarations – Enclosed in the pair of angular brackets below:

<%! One or more class variable(s) or method(s) declarations %>


3. JSP Directives – These directives govern importing Java packages or other files in
a JSP page, or they affect overall document structure. They are enclosed in a pair of
angular bracket which can be of following types:
<%@ page Directive %>
<%@ include Directive %>
<%@ taglib Directive %>

5
At times you may have a modifier attached to the first % sign. For example <%= expression %>
type. There are other modifiers as well.
6
Some of you may be somewhat unsettled to see us calling JSP tags as operators. Even though these
JSP tags are not classifiable as traditional unary and binary operators, their syntactic characteristics
are similar to operators such as == , or != , where no space is allowed between the characters forming
the operators. We believe that from syntactic point of view, finding a commonality with the multi-
character Java operators, makes it easier to remember the syntax of JSP tags. Thus we call them
operators, even though they do not fit the traditional definition of operators.

Topic 23 Servlets and Java server Pages (Singhal) Page 35 of 42


4. JSP Scriptlets – Java code enclosed in the pair of brackets given below:
<% Java code that does not fit in above categories %>
5. JSP action allowing use of Java beans7 and other custom actions- The information
about the Java bean or custom actions to be used is placed in the angular brackets
of type given below:
<jsp:usebean bean details />
<jsp:setProperty property details />
<jsp:getProperty property details />
<jsp:forward forwarding details />
<jsp:plugin plugin details />
In this chapter we shall show use of only first four JSP tags. For JSP directive tags
we shall discuss the important ones, and refer you to published sources for others.
Since each JSP page is compiled into a servlet, it is important to understand as to
how JSP tags relate to the structure of source code in the corresponding servlet.
Figure 23.16 attempts to establish this relationship.

7
Java beans are some special precompiled classes, which can supply some information or data at the
runtime. Bean classes are written under some restrictions. We shall discuss Java beans in a later
chapter.

Topic 23 Servlets and Java server Pages (Singhal) Page 36 of 42


FIG. 23.16

1. Importing Java packages and/or classes:


Every JSP page implicitly imports the following Java packages and no explicit
import statement is needed for them.
1. java.lang.*
2. javax.servlet.*
3. javax.servlet.jsp.*
4. javax.servlet.http.*
What that means is that all the classes from these packages are automatically
available to be used in a JSP page. However additionally, one or more Java
packages or classes from them can be imported into the JSP page using the syntax
below (called import directive):

<%@ page import = “java.util.*, java.text.*” %>

Topic 23 Servlets and Java server Pages (Singhal) Page 37 of 42


In above syntax the part <%@ acts like an operator where no spaces are
allowed between its elements. For example followings would be JSP compile errors:

Compile error because <% @ page import = “java.util.*, java.text.*” %>


of space between <%
and @

If there is a space between the angular bracket and percent sign then entire line is
treated like a regular HTML line and it is no longer a JSP code. That means that the
package java.util is not imported if code is written as follows:

No longer a JSP code < %@page import = “java.util.*” %>


because there is space
between < and %

Notice that in the import directive when multiple packages are imported, they are
separated by comma and not by semicolon! Also the end of import directive does not
have semicolon in the end. For example the below is a JSP compile error.

JSP compile error <%@ page import="java.util.*, java.text.*";%>


because import
directive is terminated
by semicolon! Can be a single or double quote

Comma separated package names or fully qualified class names may be placed
between single or double quotes. However, missing quotes altogether would be a
compile error. One can have as many import directive lines as needed.

2. Outputting the JSP Expressions


In Servlet class we got the object out which is of type PrintWriter, using the
following syntax:

PrintWriter out = response.getWriter ();

Then we were able to use the out object to display HTML on the web page using its
println method. JSP is actually provided with same object called out as one gets
from getWriter method of HttpServletResponse (response in above code). The
provided out object in JSP can be used exactly the way it is used in servlet. In fact
very soon we show an example of use of out object in JSP. More commonly,
however, in JSP the following strategy is followed in displaying strings and data on
the web page.

Topic 23 Servlets and Java server Pages (Singhal) Page 38 of 42


A. Literal strings and HTML tags are outputted exactly the way in which it is
done in static HTML pages. For example to output “Hello World” on its on
line, in servlet one would write a code such as below:
HTML Output done
out.println (“Hello World” + <BR>); in servlet

In JSP and HTML the same output would be made with code line:

Hello World <BR> Static HTML output

B. To print expressions8 in servlet, one passed the expression as the argument to


the method println. For example the following will print current date, time,
and day on its own line:
Expression
out.println (new java.util.Date () + <BR>); outputted in Servlet

Since in above case the expression is the string value of Date object created by
the call to constructor, in JSP this expression would be outputted by enclosing it
inside the operators <%= and %>, leading to the following syntax:
Expression outputted in
<%= new java.util.Date () %> <BR> JSP page.

Remembering our rule about the syntax for operators, no space is allowed
between the characters forming the operator <%= .

3. Declaration of class data members and methods:


All class data members and methods are declared inside the JSP tag starting
with operator <%! and ending with operator %>. As before, no spaces are
allowed between the characters forming the operators. For example the
declaration of data member val and method myMethod with syntax shown
below would add them in the servlet created from JSP page as class members:

<%! private int val = 5;

private String myMethod(){


return “From myMethod”;}
%>
Both val and myMethod are visible throughout the JSP document. Understand
that since the declarations enclosed in operators <%! And %> are class
members, their actual location in the JSP document is irrelevant. For example
the code fragment similar to below would compile and run fine in JSP.

8
Expressions are values of class or local variables return values from methods, string representation
of objects, and result of some mathematical operations, or any combinations of above.

Topic 23 Servlets and Java server Pages (Singhal) Page 39 of 42


<%= val ><BR> Will compile and run fine because
val is a class level variable and is
<%! private int val = 5; %> visible every where, irrespective of
the physical location of its
declaration!

The above code fragment would print ‘5’ on the web page. The reason that this
is OK is because in compiled servlet, val is a class level variable whose value is
set to 5 when servlet is initialized and loaded to the container. Therefore val is
available for outputting and the physical location of statement outputting val is
irrelevant. Same logic holds true about the declaration of member methods.

4. Local variables, method calls, control structures – JSP Scriptlets


The code placed between the pair of operators <% and %> is inserted into the
body of the method _jspService in the service phase to handle client requests. Figure
23.16 shows an example of this. Look at the code block inside a highlighted box on
both servlet code and JSP code sides. The selection structure if must print the val
only if val is 52. In JSP the actual output on the web page would be done by using a
combination of static HTML and JSP expression output. Obviously, to output the
value of val the HTML and JSP expression code is:

Val = <%= val%> <BR>

However to condition this output to the restriction that output be made only if val is
equal to 52, this must be under the scope of a pretest performed by the if selection
structure. In JSP it is done as follows (Figure 23.16):

<%
// code Under the scope of if
if(val == 52){ %> selection structure
Val = <%= val%> <BR>
<%}else{ %>
Under the scope of else
Val is not 52<BR>
selection structure.
<%}%>

This would indicate that all code in the scriptlet tags <% and %> is taken to be
continuous, even though physically it may be scattered all over the JSP page9.

9
Some programmers detest this inter dispersing of HTML and Java code and derisively they call it
spaghetti code. That is why if too many control structures, iteration structures, and
conditionals are to be used in a JSP page, one is better off writing a servlet to perform the same
function (if HTML to be outputted is small). On the other hand if your web page mostly has HTML,
and you just need to run Java code equivalent to a small servlet, then you are better off using a JSP
page. One can come upon a judicious mix of using servlets and JSP pages in their web applications.

Topic 23 Servlets and Java server Pages (Singhal) Page 40 of 42


Implicit JSP objects
You would recall from Listing 23.2B that our processRequest method (which is
called by doXX methods) had the objects request of type HttpServletRequest and
response of type HttpServletResponse passed to it for either parsing the user
submitted form data or for writing the response to the user on the web page. These
two (request and response) objects, and few other objects are provided to the JSP
page implicitly for use as per need. Table 23.3 gives the names and types of these
implicit JSP objects. They are automatically defined as local variables in the
_jspService method, when your JSP Java code is inserted into that method.

Table 23.3
You would recall that we needed the object request and call its getParameter
method to parse the data inputted by the user in a web form. Since this object is
automatically available to use, we can just go ahead and use it. First we would like
to create a JSP page that would perform the same function as the servlet called
Hello (Listing 23.1 but using the processRequest method shown in Listing 23.2B)
shown earlier did. The Table 23.4 shows the equivalence between the code contained
in processRequest method (Listing 23.2B) and the way we would write it in a JSP
page.

Servlet code in method processRequest Code on JSP page that would be inserted
into _jspService method
out.println ("Hello " ); Hello
String Name = <%! String Name = null; %>
request.getParameter("firstname"); <%
Name =
if(Name !=null) request.getParameter("firstname");
out.println ("to " + Name +" ");
if(Name !=null)%>
to <%=Name%>

Topic 23 Servlets and Java server Pages (Singhal) Page 41 of 42


Name = <%
request.getParameter("lastname"); Name =
request.getParameter("lastname");
if(Name !=null) if(Name !=null)%>
out.println (Name +" "); <%=Name +" "%>
out.println ( " from Gandhi.net <BR>"); from Gandhi.net <BR>
Name = <%
request.getParameter("radio1"); Name =
request.getParameter("radio1");
if(Name !=null) if(Name !=null)%>
out.println("<U>Your favorite <U>Your favorite color is:</U>
color is:</U> "+Name +"<BR>"); <%=Name %> <BR>

String [] Str = <% String [] Str =


{request.getParameter("check1"), {request.getParameter("check1"),
request.getParameter("check2"), request.getParameter("check2"),

request.getParameter("check3"),request request.getParameter("check3"),request
.getParameter("check4"), .getParameter("check4"),
request.getParameter("check5"), request.getParameter("check5"),
request.getParameter("check6"), request.getParameter("check6"),
request.getParameter("check7")}; request.getParameter("check7")};
out.println("<U>List of your %>
favorite food(s)/drink(s):</U><BR>"); <U>List of your favorite
if( Str[0]!=null) food(s)/drink(s):</U><BR>
out.println(Str[0] + "<BR>"); <%
if( Str[1]!=null) if( Str[0]!=null)%>
out.println(Str[1]+"<BR>"); <%=Str[0] + "<BR>"%>
if( Str[2]!=null) <% if( Str[1]!=null)%>
out.println(Str[2]+"<BR>"); <%=Str[1]+"<BR>"%>
if( Str[3]!=null) <%if( Str[2]!=null)%>
out.println(Str[3]+"<BR>"); <%=Str[2]+"<BR>"%>
if( Str[4]!=null) <%if( Str[3]!=null)%>
out.println(Str[4]+"<BR>"); <%=Str[3]+"<BR>"%>
if( Str[5]!=null) <%if( Str[4]!=null)%>
out.println(Str[5]+"<BR>"); <%=Str[4]+"<BR>"%>
if( Str[6]!=null) <% if( Str[5]!=null)%>
out.println(Str[6]+"<BR>"); <%=Str[5]+"<BR>"%>
out.println ("<U>Date and time <%if( Str[6]!=null)%>
are: </U>" + new java.util.Date() + <%=Str[6]+"<BR>"%>
"<BR>"); <U>Date and time are: </U>
<%= new java.util.Date()%>
<BR>
Table 23.4

Topic 23 Servlets and Java server Pages (Singhal) Page 42 of 42

Você também pode gostar