Top Banner
CS3 Java – Introduction to Java (Singhal) Page 1 of 52 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 “compilers 1 ” 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 computer 2 . They designed a language, which was first called “Oak 3 ” 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.
839
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Java_E_Book_Satish_Singhal

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

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.

Page 2: Java_E_Book_Satish_Singhal

CS3 Java – Introduction to Java (Singhal) Page 2 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).

Page 3: Java_E_Book_Satish_Singhal

CS3 Java – Introduction to Java (Singhal) Page 3 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

Page 4: Java_E_Book_Satish_Singhal

CS3 Java – Introduction to Java (Singhal) Page 4 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.

Page 5: Java_E_Book_Satish_Singhal

CS3 Java – Introduction to Java (Singhal) Page 5 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.

Page 6: Java_E_Book_Satish_Singhal

CS3 Java – Introduction to Java (Singhal) Page 6 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.

Page 7: Java_E_Book_Satish_Singhal

CS3 Java – Introduction to Java (Singhal) Page 7 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).

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).

public static void main ( String [] args ) { program statement 1; program statement 2; program statement 3; ……… ; ……… }

Begin execution of method called main

End execution of method called main

Header

Body Block

Page 8: Java_E_Book_Satish_Singhal

CS3 Java – Introduction to Java (Singhal) Page 8 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

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++.

Java class in package java.lang, which is automatically imported or included in all Java programs.

Public static final member data in class System of type class PrintStream

Overloaded method in PrintStream class, to print Java primitives, and string

Page 9: Java_E_Book_Satish_Singhal

CS3 Java – Introduction to Java (Singhal) Page 9 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.

Page 10: Java_E_Book_Satish_Singhal

CS3 Java – Introduction to Java (Singhal) Page 10 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:

Page 11: Java_E_Book_Satish_Singhal

CS3 Java – Introduction to Java (Singhal) Page 11 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

Page 12: Java_E_Book_Satish_Singhal

CS3 Java – Introduction to Java (Singhal) Page 12 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.

Page 13: Java_E_Book_Satish_Singhal

CS3 Java – Introduction to Java (Singhal) Page 13 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;

Page 14: Java_E_Book_Satish_Singhal

CS3 Java – Introduction to Java (Singhal) Page 14 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

(bytes) Minimum Value Maximum Value

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

Page 15: Java_E_Book_Satish_Singhal

CS3 Java – Introduction to Java (Singhal) Page 15 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

Page 16: Java_E_Book_Satish_Singhal

CS3 Java – Introduction to Java (Singhal) Page 16 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.

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! int val1; int val2 = 50; 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;

Compile error – val1 is used with out initialization!

Compiler reads the program declaration: short num1;

Contents = ? ? ?

Size = 2 bytes

Memory named num1 and of type short

Page 17: Java_E_Book_Satish_Singhal

CS3 Java – Introduction to Java (Singhal) Page 17 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.

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.

Compiler reads the program declaration: short num1 = 1000;

Contents = 1000

Size = 2 bytes

Memory named num1 and of type short

FIG. 2.8

Page 18: Java_E_Book_Satish_Singhal

CS3 Java – Introduction to Java (Singhal) Page 18 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.

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.

Outputting a character literal

Outputting floating point, integer, and boolean literals respectively

Outputting a string literal.

Page 19: Java_E_Book_Satish_Singhal

CS3 Java – Introduction to Java (Singhal) Page 19 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; val = 5; However, the following will cause a compile error! final int val; System.out.println (val);

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

Will not cause a compile error in Java.

Will cause a compile error in Java, as Val is not initialized.

Page 20: Java_E_Book_Satish_Singhal

CS3 Java – Introduction to Java (Singhal) Page 20 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! String Not_A_String = ‘H’ + 25 + ‘L’;

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.

Compile error. None of the expressions to be concatenated are String type!

FIG. 2.11

Page 21: Java_E_Book_Satish_Singhal

CS3 Java – Introduction to Java (Singhal) Page 21 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.

Page 22: Java_E_Book_Satish_Singhal

CS3 Java – Introduction to Java (Singhal) Page 22 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 ……..

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 argsFIG. 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

Invoking JVM

Name of class file to be executed!

Argument list passed to the program. Argument0 is stored in array element args[0] and so on.

Page 23: Java_E_Book_Satish_Singhal

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

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.

public class CommandLineArgs { public static void main(String [] args) { System.out.print(args[0]+ " " + args[1]); String Input = args[2]; int score = Integer.parseInt(Input); 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); } }//Listing 2.3

1. static method parseInt of class Integer returns the int value of String Input. Input is args [2].

2. static method parseDouble of class Double returns the double value of String Input. Input is args [10].

Page 24: Java_E_Book_Satish_Singhal

CS3 Java – Introduction to Java (Singhal) Page 24 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.

Page 25: Java_E_Book_Satish_Singhal

CS3 Java – Introduction to Java (Singhal) Page 25 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

Page 26: Java_E_Book_Satish_Singhal

CS3 Java – Introduction to Java (Singhal) Page 26 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);

Page 27: Java_E_Book_Satish_Singhal

CS3 Java – Introduction to Java (Singhal) Page 27 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)

Page 28: Java_E_Book_Satish_Singhal

CS3 Java – Introduction to Java (Singhal) Page 28 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:

Page 29: Java_E_Book_Satish_Singhal

CS3 Java – Introduction to Java (Singhal) Page 29 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.

Page 30: Java_E_Book_Satish_Singhal

CS3 Java – Introduction to Java (Singhal) Page 30 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.

Page 31: Java_E_Book_Satish_Singhal

CS3 Java – Introduction to Java (Singhal) Page 31 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:

Page 32: Java_E_Book_Satish_Singhal

CS3 Java – Introduction to Java (Singhal) Page 32 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!;

Page 33: Java_E_Book_Satish_Singhal

CS3 Java – Introduction to Java (Singhal) Page 33 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.

Page 34: Java_E_Book_Satish_Singhal

CS3 Java – Introduction to Java (Singhal) Page 34 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.

Page 35: Java_E_Book_Satish_Singhal

CS3 Java – Introduction to Java (Singhal) Page 35 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

Page 36: Java_E_Book_Satish_Singhal

CS3 Java – Introduction to Java (Singhal) Page 36 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.

Page 37: Java_E_Book_Satish_Singhal

CS3 Java – Introduction to Java (Singhal) Page 37 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

Page 38: Java_E_Book_Satish_Singhal

CS3 Java – Introduction to Java (Singhal) Page 38 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.

Page 39: Java_E_Book_Satish_Singhal

CS3 Java – Introduction to Java (Singhal) Page 39 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

Page 40: Java_E_Book_Satish_Singhal

CS3 Java – Introduction to Java (Singhal) Page 40 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( );

Page 41: Java_E_Book_Satish_Singhal

CS3 Java – Introduction to Java (Singhal) Page 41 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.

Page 42: Java_E_Book_Satish_Singhal

CS3 Java – Introduction to Java (Singhal) Page 42 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. }

Page 43: Java_E_Book_Satish_Singhal

CS3 Java – Introduction to Java (Singhal) Page 43 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. . .

Page 44: Java_E_Book_Satish_Singhal

CS3 Java – Introduction to Java (Singhal) Page 44 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 )

Page 45: Java_E_Book_Satish_Singhal

CS3 Java – Introduction to Java (Singhal) Page 45 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);

Page 46: Java_E_Book_Satish_Singhal

CS3 Java – Introduction to Java (Singhal) Page 46 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); } } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

Page 47: Java_E_Book_Satish_Singhal

CS3 Java – Introduction to Java (Singhal) Page 47 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”);

Page 48: Java_E_Book_Satish_Singhal

CS3 Java – Introduction to Java (Singhal) Page 48 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

Page 49: Java_E_Book_Satish_Singhal

CS3 Java – Introduction to Java (Singhal) Page 49 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?

Page 50: Java_E_Book_Satish_Singhal

CS3 Java – Introduction to Java (Singhal) Page 50 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);

Page 51: Java_E_Book_Satish_Singhal

CS3 Java – Introduction to Java (Singhal) Page 51 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 );

Page 52: Java_E_Book_Satish_Singhal

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

Make any notes below

Page 53: Java_E_Book_Satish_Singhal

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

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.

Page 54: Java_E_Book_Satish_Singhal

CS3 Java – Arithmetical Expressions (Singhal) Page 2 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.

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. boolean data = true*false; 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++.

Operand 2Operand 1

Compile error! boolean data types are not allowed to be operands to arithmetical operators in Java!

Page 55: Java_E_Book_Satish_Singhal

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

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

public class PrimitiveDivisions1 { 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); } }

1. Pure integer division

2. Division includes one or more floating point number(s)

Page 56: Java_E_Book_Satish_Singhal

CS3 Java – Arithmetical Expressions (Singhal) Page 4 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'); } }

Page 57: Java_E_Book_Satish_Singhal

CS3 Java – Arithmetical Expressions (Singhal) Page 5 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

Value ‘z’/’A’ = 122/65

‘z’%’A’ = 122%65

‘Z’/2 =90/2 ‘Z’%2 = 90%2

Z 90 1 57 45 0 A 65

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

Page 58: Java_E_Book_Satish_Singhal

CS3 Java – Arithmetical Expressions (Singhal) Page 6 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.

Page 59: Java_E_Book_Satish_Singhal

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

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.

Unary

Binary

Same preced-ence

Method call or forcing eval order

Page 60: Java_E_Book_Satish_Singhal

CS3 Java – Arithmetical Expressions (Singhal) Page 8 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

Page 61: Java_E_Book_Satish_Singhal

CS3 Java – Arithmetical Expressions (Singhal) Page 9 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.

Page 62: Java_E_Book_Satish_Singhal

CS3 Java – Arithmetical Expressions (Singhal) Page 10 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.

Page 63: Java_E_Book_Satish_Singhal

CS3 Java – Arithmetical Expressions (Singhal) Page 11 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; ++val; 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-

decrement Decrease the value of val by one after the 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

Pre-increment operator.

Page 64: Java_E_Book_Satish_Singhal

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

Pre-Increment/Decrement Operators in Java

int val = 5;

++val;

--val;

5val

5val

6val

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

Page 65: Java_E_Book_Satish_Singhal

CS3 Java – Arithmetical Expressions (Singhal) Page 13 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.

Page 66: Java_E_Book_Satish_Singhal

CS3 Java – Arithmetical Expressions (Singhal) Page 14 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

Page 67: Java_E_Book_Satish_Singhal

CS3 Java – Arithmetical Expressions (Singhal) Page 15 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.

Page 68: Java_E_Book_Satish_Singhal

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

Operator Description Associativity

( ) Method call or forcing evaluation order

- ++ --

Unary Negation Pre-Increment Pre-Decrement

Right-to-Left

* /

%

Multiply Divide

Modulus Left-to-Right

+ -

Plus Binary Minus Left-to-Right

= Assignment Right-To-Left

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.

HIGHER

LOWER

Page 69: Java_E_Book_Satish_Singhal

CS3 Java – Arithmetical Expressions (Singhal) Page 17 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.

Page 70: Java_E_Book_Satish_Singhal

CS3 Java – Arithmetical Expressions (Singhal) Page 18 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.

Page 71: Java_E_Book_Satish_Singhal

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

Operator (Space is not allowed between the operator symbols)

Description Example

+= Addition and then assignment

int Val =5; int Num = 10; Val+=Num; Value stored in Val is 15.

+= Addition then assignment for a String

String Name1 = “John”; String Name2 = “ Doe”;Name1+=Name2; Name1 stores “John Doe”

-= Subtraction and then assignment

int Val =5; int Num = 10; Val-=Num; Value stored in Val is -5.

*= Multiplication and then assignment

int Val =5; int Num = 10; Val*=Num; Value stored in Val is 50.

/= Division and then assignment

int Val =5; int Num = 10; Val/=Num; Value stored in Val is 0.

%= Get modulo and then assignment

int Val =5; 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);

Page 72: Java_E_Book_Satish_Singhal

CS3 Java – Arithmetical Expressions (Singhal) Page 20 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.

FIG.3.6

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.

Though char is 2 bytes and byte is 1 byte, they have the same highest value of 127. (For char we are using Unicode system).

Page 73: Java_E_Book_Satish_Singhal

CS3 Java – Arithmetical Expressions (Singhal) Page 21 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

Page 74: Java_E_Book_Satish_Singhal

CS3 Java – Arithmetical Expressions (Singhal) Page 22 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): //********************************************************* double a; double b; a = 8.5; 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; my_double= 8; //*********************************************************

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.

Value undefined

int 8 is coerced into double type 8.0 and is stored.

Type Coercion

8.5

9.37

No type coercion because both a and b are double type storage locations, and 8.5, 9.37 are also double types.

Page 75: Java_E_Book_Satish_Singhal

CS3 Java – Arithmetical Expressions (Singhal) Page 23 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) { int big = 1234567890; float approx = big; System.out.println (big - (int) approx); } } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

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

1. An integer is stored in memory called big.

2. The value of int big is assigned to the float type 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 float storage approx.

4. The output of Listing 3.6.

Page 76: Java_E_Book_Satish_Singhal

CS3 Java – Arithmetical Expressions (Singhal) Page 24 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: byte my_byte = 120; 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;

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

No compile error, as value 120 though an int, is lower than the maximum limit of byte type memory.

Compile error, as value 300 is higher than the maximum limit of byte type memory.

Page 77: Java_E_Book_Satish_Singhal

CS3 Java – Arithmetical Expressions (Singhal) Page 25 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; my_int= (int) 8.5; //********************************************************* 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.

Value undefined

8 is stored Explicit Type Casting

Page 78: Java_E_Book_Satish_Singhal

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

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. int val = int (4.8); One may use a form of type casting which will work both in Java and C++. This is shown below. 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):

Acceptable in C++ but compile error in Java.

Will work in both, Java and C++.

First evaluates integer expression 7/4 to int value 1

Then widens 1 to 1.0f

First widens 7 to 7.0f and 4 to 4.0f and then performs the float division.

1.75f

1.0f

5.0f

Page 79: Java_E_Book_Satish_Singhal

CS3 Java – Arithmetical Expressions (Singhal) Page 27 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)

Page 80: Java_E_Book_Satish_Singhal

CS3 Java – Arithmetical Expressions (Singhal) Page 28 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);

//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 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

Explicit narrowing conversion

Page 81: Java_E_Book_Satish_Singhal

CS3 Java – Arithmetical Expressions (Singhal) Page 29 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. short val = 90000; short val1 = (int)(90000);

Compile error!

No compile error! val1 have the number resulted from overflow.

Page 82: Java_E_Book_Satish_Singhal

CS3 Java – Arithmetical Expressions (Singhal) Page 30 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.

Page 83: Java_E_Book_Satish_Singhal

CS3 Java – Arithmetical Expressions (Singhal) Page 31 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.

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:

In Java functions are called methods.

Page 84: Java_E_Book_Satish_Singhal

CS3 Java – Arithmetical Expressions (Singhal) Page 32 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.

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.

May call square function or cube function as needed

Will return the value of square of number sent to it

Will return the value of the cube of number sent to it

Methods

Method

Method

Method

Page 85: Java_E_Book_Satish_Singhal

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

System.out.println ("The square of "+number+" is = " +square (number)); System.out.println ("The cube of "+number+" is = " +cube (number)); System.exit (0);

} public static double square(double number) {

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.

2. main temporarily transfers control to function square or cube

1. Call to the static member method with name square.

Page 86: Java_E_Book_Satish_Singhal

CS3 Java – Arithmetical Expressions (Singhal) Page 34 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.

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} public float myMethod (int val1, String name, double score) { //method body} 12 We shall discuss Java Objects in future chapters.

methods

Compile error

Page 87: Java_E_Book_Satish_Singhal

CS3 Java – Arithmetical Expressions (Singhal) Page 35 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. public int myMethod (int val1, String name, double score) { //method body} public int myMethod (String name, int val1, double score) { //method body} 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.

No Compile error as all methods have different signatures

Page 88: Java_E_Book_Satish_Singhal

CS3 Java – Arithmetical Expressions (Singhal) Page 36 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

Boolean The Boolean class wraps a value of the primitive type boolean in an object.

Byte The Byte class wraps a value of primitive type byte in an object.

Character The Character class wraps a value of the primitive type char in an object.

Double The Double class wraps a value of the primitive type double in an object.

Float The Float class wraps a value of primitive type float in an object.

Integer The Integer class wraps a value of the primitive type int in an object.

Long The Long class wraps a value of the primitive type long in an object.

Math

The class Math contains methods for performing basic numeric operations such as the elementary exponential, logarithm, square root, and trigonometric functions.

Page 89: Java_E_Book_Satish_Singhal

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

Short The Short class wraps a value of primitive type short in an object.

String The String class represents character strings.

System The System class contains several useful class 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.

Page 90: Java_E_Book_Satish_Singhal

CS3 Java – Arithmetical Expressions (Singhal) Page 38 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.

Page 91: Java_E_Book_Satish_Singhal

CS3 Java – Arithmetical Expressions (Singhal) Page 39 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 class

Example of call statement

Return value

abs ( i ) : i can be int, long, double or float.

Math.abs(-6) 6

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 int, long, float, and double

Math.min (20,55) 20

max ( x , y): x, y can be of type int, long, float, and double

Math.max (20.01f, 29.5f)

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

Page 92: Java_E_Book_Satish_Singhal

CS3 Java – Arithmetical Expressions (Singhal) Page 40 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.

FIG. 3.16

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”; 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.

Method arguments can be: • Literal constant

Math.sqrt (4); • Variable or named constant

Math.sqrt (x); • Legal expressions and call to other

methods Math.sqrt (Math.sqrt (x)); Math.sqrt (3 – 6*x);

Calling sqrt (x) with in the call to sqrt is OK, because according to precedence rules, the inner call will be made first, and then the outer call is made.

Name is an instance of class String, which stores “JOHN DOE” in it.

Page 93: Java_E_Book_Satish_Singhal

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

Name = Name.toLowerCase( ); 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.

Instance methods must be qualified by the instance, which is used to invoke them.

Instance name Instance method being invoked.

Page 94: Java_E_Book_Satish_Singhal

CS3 Java – Arithmetical Expressions (Singhal) Page 42 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.

Page 95: Java_E_Book_Satish_Singhal

CS3 Java – Arithmetical Expressions (Singhal) Page 43 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.

Page 96: Java_E_Book_Satish_Singhal

CS3 Java – Arithmetical Expressions (Singhal) Page 44 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 { public static void main(String [] args) { String Name = "John Q Public"; int length = Name.length( ); 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 { public static void main(String [] args) { String Name = "JOHN Q PUBLIC"; String Name_Lower = Name.toLowerCase( );

Finding the string length by calling the instance method length in String class.

1. Method toLowerCase converts all characters in its caller to lower case.

Page 97: Java_E_Book_Satish_Singhal

CS3 Java – Arithmetical Expressions (Singhal) Page 45 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) { long $long = 10000L; String Number = String.valueOf ($long*100.9); Number= " = " + Number; System.out.println ("The multiplication of "+$long+ " and " + 100.9+ Number);

Returns the String containing number $long*100.9

valueOf is a static or class method.

Page 98: Java_E_Book_Satish_Singhal

CS3 Java – Arithmetical Expressions (Singhal) Page 46 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) { String My_Name = "Adam JonesJ"; 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 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

1. Instance method indexOf is called on instance My_Name

Page 99: Java_E_Book_Satish_Singhal

CS3 Java – Arithmetical Expressions (Singhal) Page 47 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);

Page 100: Java_E_Book_Satish_Singhal

CS3 Java – Arithmetical Expressions (Singhal) Page 48 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

Page 101: Java_E_Book_Satish_Singhal

CS3 Java – Arithmetical Expressions (Singhal) Page 49 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.

Page 102: Java_E_Book_Satish_Singhal

CS3 Java – Arithmetical Expressions (Singhal) Page 50 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

Page 103: Java_E_Book_Satish_Singhal

CS3 Java – Arithmetical Expressions (Singhal) Page 51 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’ ;

Page 104: Java_E_Book_Satish_Singhal

CS3 Java – Arithmetical Expressions (Singhal) Page 52 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) {

Page 105: Java_E_Book_Satish_Singhal

CS3 Java – Arithmetical Expressions (Singhal) Page 53 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.

Page 106: Java_E_Book_Satish_Singhal

CS3 Java – Arithmetical Expressions (Singhal) Page 54 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.

Page 107: Java_E_Book_Satish_Singhal

CS3 Java – Arithmetical Expressions (Singhal) Page 55 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); } }

Page 108: Java_E_Book_Satish_Singhal

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

A. 4 4 8 6 B. 4 4 8 8 C. 4 4 6 6 D. 4 3 8 6 E. 4 3 8 8 F. 4 4 6 8

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;

Page 109: Java_E_Book_Satish_Singhal

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

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

Page 110: Java_E_Book_Satish_Singhal

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

Make Notes Here

Page 111: Java_E_Book_Satish_Singhal

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

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.

Page 112: Java_E_Book_Satish_Singhal

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 2 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.

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

“John Doe” 5000

5000

Name

Address of string “John Doe” in the memory.

Stores the address 5000 in it

Reference (pointer) called Name, which is capable of holding the address of String type data.

Page 113: Java_E_Book_Satish_Singhal

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 3 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”; double data = 5.005; String City = null;

6val

??num

2000Name “John”

2000

5.005data

nullCity

Heap MemoryStack memory

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.

FIG. 4.2

Beginning address of memory location, where “John” is stored.

Bottom of stack

Page 114: Java_E_Book_Satish_Singhal

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 4 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.

Page 115: Java_E_Book_Satish_Singhal

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 5 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 ( );

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:

Data type

Variable name

Java operator

Hidden “method” added to the class Customer by Java

Page 116: Java_E_Book_Satish_Singhal

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 6 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

Page 117: Java_E_Book_Satish_Singhal

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 7 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:

public Customer ( )

{

/*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.

Constructor has same name as the class and has no return type.

Page 118: Java_E_Book_Satish_Singhal

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 8 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: >java MyClass >java 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 { 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:");

1. Class Customer

Executes the main method in class MyClass

Executes the main method in YourClass

Page 119: Java_E_Book_Satish_Singhal

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 9 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);

Page 120: Java_E_Book_Satish_Singhal

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 10 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.

Page 121: Java_E_Book_Satish_Singhal

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 11 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).

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.

Object created by default constructor.

Data in object Cust after line 58 is executed

Data in object Cust after line 63 is executed

Page 122: Java_E_Book_Satish_Singhal

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 12 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) byte, short, int, long 0 float, double 0.0 boolean false 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).

Java provided default constructor initializes all object data members to null value.

Page 123: Java_E_Book_Satish_Singhal

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

S truc ture o f O b jec t C ust in H eap M em o ry

cred it_card_num

nam e

phone_num

credit_ra ting

address

city

z ip_code

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

Stores null Stores Zero

Stores ‘ ‘

Page 124: Java_E_Book_Satish_Singhal

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 14 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.

Page 125: Java_E_Book_Satish_Singhal

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 15 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

Page 126: Java_E_Book_Satish_Singhal

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 16 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

Page 127: Java_E_Book_Satish_Singhal

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 17 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.

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.

3000 cust

Reference Cust in the main method

Copy of Cust in main passed to method changeCustData

Page 128: Java_E_Book_Satish_Singhal

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

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.

Reference Cust in the main method

12000 cust

No longer a copy of Cust in main passed

to method changeCustData

New Customer Object

Now the object in main cannot be changed!

Page 129: Java_E_Book_Satish_Singhal

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 19 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.

Page 130: Java_E_Book_Satish_Singhal

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

String First_name; int length = First_name.length( ); 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; int length = First_name.length( );

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

Compile error. Attempting to use a local variable before its initialization.

No compile error. However, the program will crash when it is run.

Page 131: Java_E_Book_Satish_Singhal

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 21 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. Allocating the references does not allocate any pointees. (Lines 10,11)

IntObj x = null;

IntObj y=null;

2. Allocate a pointee and set x to point to it. (Line 13).

x = new IntObj( )

3. Store 43 into the value field of the pointee of x. (Line 15)

x.value = 42;

4. Try to store 13 in y.value. This crashes because y does not have a pointee -- it was never assigned one. (Line 18)

y.value = 13;

5. Assign y = x; so that y points to x's pointee. Now x and y point to the same pointee -- they

y = x;

Both x and y store null

Still stores null!

Page 132: Java_E_Book_Satish_Singhal

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

are "sharing". (Line 20) 6. Now try to store 13 in the value field of y. This time it works, because the previous assignment gave y a pointee. (Line 23)

y.value = 13;

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.

Page 133: Java_E_Book_Satish_Singhal

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 23 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 ( ); Cust1.credit_card_num = “12345667”; 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

Compile error! The field credit_card_num is no longer permitted direct access.

Page 134: Java_E_Book_Satish_Singhal

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 24 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; }

Page 135: Java_E_Book_Satish_Singhal

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 25 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. Customer Cust1 = new Customer ( ); Cust1. setCreditCardNumber (“12345667”); System.out.println (“The customer credit card number is = “ + Cust1.getCreditCardNumber( )); 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.

Invokes the code in method setCreditCardNumber and sets the private member credit_card_num to new value 12345667.

Invokes the code in method getCreditCardNumber to print the private member credit_card_num.

Page 136: Java_E_Book_Satish_Singhal

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 26 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

Page 137: Java_E_Book_Satish_Singhal

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 27 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.

Page 138: Java_E_Book_Satish_Singhal

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 28 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

Page 139: Java_E_Book_Satish_Singhal

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 29 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 //***********************************************

Page 140: Java_E_Book_Satish_Singhal

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 30 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);

Page 141: Java_E_Book_Satish_Singhal

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 31 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:");

Page 142: Java_E_Book_Satish_Singhal

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 32 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.

Page 143: Java_E_Book_Satish_Singhal

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

.

.

.

printCustomer private data:phone_num 423511

name 2003

zip_code 90009

City 3000

Other fields not shown toimprove clarity.

“Nell Dale”

2003

“Austin”

3000

getCustomer

Setters

getters

Customer ( )

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

Java provided default constructor

Page 144: Java_E_Book_Satish_Singhal

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

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 );

FIG. 4.12 ---------------------------------------------------------------------------------------------------

Fig. 4.11C Getter oval in Figure 4.11A

Self reference (pointer) to class Customer provided by Java

Selected non-static data member called name

Page 145: Java_E_Book_Satish_Singhal

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 35 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; } 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.

Qualified name of class instance variable called name

Local variable called name

Page 146: Java_E_Book_Satish_Singhal

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

------------------------------------------------------------------------------------------------------------ public void setName (String name) { name = name; }

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;

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

Not a compile error!

The address field of the instance that will call method transferData. Alternate syntax: this.address is also OK.

The address field of the Customer instance passed to method transferData

Instance of Customer class passed to method transferData

Page 147: Java_E_Book_Satish_Singhal

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 37 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) { zip_code = zip1.data; zip_code = zip1.getData ( ); } 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”.

Compile error! No direct read/write access to private data members of those classes which are not of type Customer.

This is OK, as the public interface to get the value of private member called data is being used.

Page 148: Java_E_Book_Satish_Singhal

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 38 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

Page 149: Java_E_Book_Satish_Singhal

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 39 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.

Page 150: Java_E_Book_Satish_Singhal

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 40 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.

Page 151: Java_E_Book_Satish_Singhal

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 41 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

Page 152: Java_E_Book_Satish_Singhal

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 42 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.

Page 153: Java_E_Book_Satish_Singhal

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 43 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.

Page 154: Java_E_Book_Satish_Singhal

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 44 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 Constructor Action by constructor java.lang.Math private Math ( ) Prevents instantiation

of Math class

java.lang.String

public String (String Str) Instantiates a String object with string Str

public String(StringBuffer buffer)

Instantiates a String object with contents same as String Buffer object buffer

java.lang.Integer

public Integer (int value) Sets the int field of Integer object to the value int

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.

Page 155: Java_E_Book_Satish_Singhal

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 45 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 { 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 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; 00066 credit_card_num = credit_card_num1; 00067 credit_rating = credit_rating1; 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

Sets the address field of the object to the argument address1.

Explicit constructor

Argument-less constructor is needed to compile/run to run the code like : Customer Cu = new Customer( )

Page 156: Java_E_Book_Satish_Singhal

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 46 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 ( ) ; 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.

Would cause a compile error if the argument-less constructor on lines 46 to 49 (Listing 4.7A) is not included.

Page 157: Java_E_Book_Satish_Singhal

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 47 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.

Page 158: Java_E_Book_Satish_Singhal

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 48 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 { private long num = 1000L; public long getLong() { return num; } } public class LongObjDriver { public static void main(String [] args) { 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 { private long num ; { num = 1000L; }

public long getLong( ){ return num; } } // add the code for class LongObjDriver from Listing 4.8A here //Listing 4.8B

1. Syntax for direct assignment.

2. Notice that the form of constructor call remains unchanged!

3. Initialization block.

Page 159: Java_E_Book_Satish_Singhal

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 49 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 { { num = 1000L; } 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.

4. Compile error! The variable being initialized is being defined after the initialization block.

Page 160: Java_E_Book_Satish_Singhal

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

00001 00002 class LongObj 00003 { 00005 public LongObj( ) 00006 { 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 00014 private long num = 1000L; 00015 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.

1. Cosntructor: prints the value of num assigned in initialization block and finally the new value set on line nine.

2. Direct assignment

3. Initialization block.

Page 161: Java_E_Book_Satish_Singhal

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 51 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.

Page 162: Java_E_Book_Satish_Singhal

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 52 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 java.lang.String

Name 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.

Page 163: Java_E_Book_Satish_Singhal

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 53 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; 00015 00020 public BankAccount( ) 00021 { 00022 this("name to be entered"); 00023 System.out.println ("From argument-less constructor."); 00024 } 00031 public BankAccount(String name1) 00032 { 00033 this(name1,0.0); 00034 System.out.println ("From one argument constructor."); 00035 }

1. Argument-less constructor

2. One argument constructor.

Page 164: Java_E_Book_Satish_Singhal

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

00042 public BankAccount(String name1, double balance1) 00043 { 00044 this(name1,balance1, 1); 00045 System.out.println ("From two argument constructor."); 00046 } 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.

3. Two Argument constructor

4. Three Argument constructor

Page 165: Java_E_Book_Satish_Singhal

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 55 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

Page 166: Java_E_Book_Satish_Singhal

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 56 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.

Page 167: Java_E_Book_Satish_Singhal

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 57 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.

Page 168: Java_E_Book_Satish_Singhal

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 58 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

Page 169: Java_E_Book_Satish_Singhal

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 59 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: public BankAccount( ) { System.out.println ("Argument-less constructor."); this("name to be entered"); } 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(setDefaultName( )); } 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.

Compile error! No statements can precede the call using this as a constructor.

This is OK! Call to static methods of same class or value returning methods of other classes can provide arguments passed to this.

Page 170: Java_E_Book_Satish_Singhal

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

In another rather contrived example we may write the two argument constructor for the BankAccount class in the following manner. public BankAccount(String name1, double balance1) { 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( ); //FIG 4.24

Call to intValue ( ) instance method of Integer class.

Cascaded calls to method deposit.

Page 171: Java_E_Book_Satish_Singhal

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 61 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 { // Code placed here }

Static initialization block.

Page 172: Java_E_Book_Satish_Singhal

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 62 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; 00005 static 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 00014 static 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

First static block

Second static block

Page 173: Java_E_Book_Satish_Singhal

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 63 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

Page 174: Java_E_Book_Satish_Singhal

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 64 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; private static int foo_bar = foo; 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.

Compile error! foo is not created before the creation and initialization of foo_bar

Page 175: Java_E_Book_Satish_Singhal

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 65 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; 00058 balance = balance1; 00059 num_acts = num_acts1; 00060 ++num_objects; 00061 } //Insert the code lines 62 to 70 from Listing 4.9B here public static int getNumObjects ( ) { return num_objects; } }Listing 4.11A

Incrementing the static variable num_objects in last chained constructor as this one is always called!

Page 176: Java_E_Book_Satish_Singhal

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 66 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;

Page 177: Java_E_Book_Satish_Singhal

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 67 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.

Page 178: Java_E_Book_Satish_Singhal

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 68 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! package 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.

Must be the first source code line for a class that would reside in a package named xyz

Page 179: Java_E_Book_Satish_Singhal

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 69 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 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.

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

Reverse domain name scheme for naming packages

In creating directory structure, replace the dots in package name by forward slash.

The location of folder net is not important

Page 180: Java_E_Book_Satish_Singhal

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 70 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 PRINT <DIR> 03-17-04 2:41p print 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

Command to get directory listing

Print folder located in the folder gandhi

Page 181: Java_E_Book_Satish_Singhal

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 71 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

Page 182: Java_E_Book_Satish_Singhal

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 72 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 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

Must include the full path to the folder in which the folder net is located.

Needed so that java can locate files in current directory as

Page 183: Java_E_Book_Satish_Singhal

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 73 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.

Page 184: Java_E_Book_Satish_Singhal

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 74 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 ( );

Page 185: Java_E_Book_Satish_Singhal

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 75 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)

Page 186: Java_E_Book_Satish_Singhal

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 76 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?

Page 187: Java_E_Book_Satish_Singhal

CS3 Java – Topic 4: Java Classes & Objects (Singhal) Page 77 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.

Page 188: Java_E_Book_Satish_Singhal

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

FIG. 4A.2 Why does the output in Figure 4A.2 show a different address for MyObject inside the method MyMethod now? Explain.

Different from other two addresses

Page 189: Java_E_Book_Satish_Singhal

Chapter 5 Selection Control Structures in Java

Chapter to be written ☺

Page 190: Java_E_Book_Satish_Singhal

Chapter 6 Looping Control Structure

This chapter is to be written ☺

Page 191: Java_E_Book_Satish_Singhal

Chapter 7 – Additional Control Structures And Scope Rules

This chapter is to be written ☺

Page 192: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 1 of 99

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).

Page 193: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 2 of 99

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!

Data inserted by operating system into standard output stream

Page 194: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 3 of 99

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.

Grants code in main exemption from special requirements to handle IO errors.

Page 195: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 4 of 99

-------------------------------------------------------------------------------------------- BufferedReader Key_Board = new BufferedReader ( ); 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). -------------------------------------------------------------------------------------------- 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.

Would take an appropriate object of type class Reader as an argument.

Needs an object, which will bind keyboard strokes to the object Isr.

Page 196: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 5 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.

Page 197: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 6 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 {

Page 198: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 7 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:

Page 199: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 8 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.

Page 200: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 9 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. -------------------------------------------------------------------------------------------- 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

Needs the file name string that will bind the file to the object Freader .

Page 201: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 10 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

Page 202: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 11 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.

Page 203: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 12 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

Page 204: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 13 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.

Page 205: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 14 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( );

Page 206: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 15 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:

Page 207: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 16 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. 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.

Needs the file name string that will bind the output file to the object FWriter.

Page 208: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 17 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.");

Page 209: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 18 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!

Page 210: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 19 of 99

FIG. 8.13

Page 211: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 20 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.

Page 212: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 21 of 99

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":

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.

Page 213: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 22 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 2 Doe 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 { public static void main(String[] args) { StringTokenizer St = new StringTokenizer("John Doe lives in Torrance, CA."); while (St.hasMoreTokens ( )) System.out.println (St.nextToken( )); } } //Listing8.4B

Binds the string in constructor argument with object St.

Returns true if there are more tokens Returns next

token

Output of Listing 8.4B (below)

Page 214: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 23 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

Page 215: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 24 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).

Page 216: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 25 of 99

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 = ' ';

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.

Page 217: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 26 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

Page 218: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 27 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.

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.

FIG. 8.15

Page 219: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 28 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);

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 (

Would allow append writing to the output file whose name is in String Line.

Page 220: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 29 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.");

Page 221: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 30 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

Page 222: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 31 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 package java.text

Purpose

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.

Page 223: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 32 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 " +

Page 224: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 33 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.

Page 225: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 34 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)); System.out.println (Currency.format (13.385)); System.out.println (Currency.format (13.38501)); System.out.println (Currency.format (13.3851)); System.out.println (Currency.format (13.3854)); System.out.println (Currency.format (13.3855)); System.out.println (Currency.format (13.3856)); System.out.println (Currency.format (13.386)); System.out.println (Currency.format (-13.386));

$13.38 $13.38 $13.39 $13.39 $13.39 $13.39 $13.39 $13.39 ($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

Page 226: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 35 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.

Page 227: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 36 of 99

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// DecimalFormat DF = new DecimalFormat (“Format String”); System.out.println (DF.format (number)); FIG. 8.17 ////////////////////////////////////////////////////////////////////////////////////////////////// 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.

Indicates the pattern to which the number outputted by format method must conform.

Outputted number would conform to the pattern dictated by the Format String.

Page 228: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 37 of 99

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

“0.0000”

“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.

Integer part of the number

Mantissa part of the number

Page 229: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 38 of 99

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

Output on Monitor

Page 230: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 39 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 = " +

Page 231: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 40 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.

Page 232: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 41 of 99

08 Displayed in format 0dot00 is 31.01 cm square. 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 (thus the area being equal to Pi3) 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……

Full integer part is displayed in spite of format string

Page 233: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 42 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.

Page 234: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 43 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)”

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

Positive sub pattern Negative sub

pattern

Page 235: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 44 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: (34.1) (34.1 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)

Both negative and positive sub patterns are identical, except for the prefix and postfix characters in negative sub pattern.

Loss of suffix or postfix when two sub patterns are different.

Page 236: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 45 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.101The 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.

Page 237: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 46 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

Page 238: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 47 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

Page 239: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 48 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);

Page 240: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 49 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

Page 241: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 50 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 {

Page 242: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 51 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.

Page 243: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 52 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.

Page 244: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 53 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"

Page 245: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 54 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 " +

Page 246: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 55 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 *.

Page 247: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 56 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

Page 248: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 57 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.

Page 249: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 58 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 this file would be: C:\_Courses\_Java\Topic02IntroductionToJava\HelloWorld.java On a Unix system, the corresponding abstract pathname may look like as follows: /_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:

DOS style abstract pathname

Unix style abstract pathname

Page 250: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 59 of 99

\\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 instance methods)

Return Type

Description

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.

Windows networked computers style abstract pathname

Page 251: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 60 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.

Page 252: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 61 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.

Page 253: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 62 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)

Page 254: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 63 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.

Page 255: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 64 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

Page 256: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 65 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)

Page 257: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 66 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

Page 258: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 67 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())

Page 259: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 68 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

Page 260: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 69 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

Page 261: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 70 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.

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:

Can choose the buffer size by calling proper constructor

Page 262: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 71 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

Page 263: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 72 of 99

The results of running the code in Listing 8.12 under various conditions is shown in Figure 8.26. Results from executing all lines in Listing 8.12 00003 Type the input file name and press enter key. 00004 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.

User either presses the enter key or presses Control + Z

Page 264: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 73 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

Page 265: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 74 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

Page 266: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 75 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

Page 267: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 76 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.

Page 268: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 77 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.

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.

Inventory Table

Inventory summary

Page 269: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 78 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.

Page 270: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 79 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 type/data type

Name Value

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

Page 271: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 80 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.

Page 272: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 81 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).

Page 273: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 82 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

Page 274: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 83 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 }

Page 275: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 84 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.

Page 276: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 85 of 99

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

InventoryTable

private: InventorySummary Summary //Other data members

2000

InventorySummary

2000

printInvSummary

private: Data members

Constructors Constructors

Member methods

Page 277: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 86 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.

Page 278: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 87 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.

Page 279: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 88 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.

Page 280: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 89 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.

Page 281: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 90 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 = '-';

Page 282: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 91 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 }

Page 283: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 92 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);

Page 284: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 93 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 {

Page 285: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 94 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

Page 286: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 95 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

Page 287: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 96 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

Page 288: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 97 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( );

Page 289: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 98 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 }

Page 290: Java_E_Book_Satish_Singhal

CS3 Java – Topic 8: Standard IO (Singhal) Page 99 of 99

00058 } //Listing A8.1 http://www.horstmann.com/

Page 291: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 1 of 134

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

Page 292: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 2 of 134

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.

5000 7000

Memory address

Variable names

Page 293: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 3 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.

Page 294: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 4 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. An array like the one in Figure 9.2 is called a one-dimensional array, whose characteristics are summarized in the Figure 9.3.

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.

ArrayName [index]

Largest index of in array of size N will be (N-1)!

Page 295: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 5 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.

Question: What is wrong with this manner of assigning Table 9.1 shows few examples of array declarations that would cause compile error. Array declaration which would cause compile error

Reason for 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.

• 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 in the array length expressions can be named or literal constants, initialized variables, or values returned from method calls.

FIG. 9.5

Page 296: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 6 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,

Page 297: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 7 of 134

then the state of array changes to the one in Figure 9.8

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.

groceryItems [0] = “cat food”; groceryItems [1] = “rice”; groceryItems [8] = “spinach”; groceryItems [9] = “butter”;

FIG. 9.7

Unassigned components are still null.

Page 298: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 8 of 134

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.

>javac CommonMistake_Array.java >java CommonMistake_Array Exception in thread "main" java.lang.NullPointerException at CommonMistake_Array.main(CommonMistake_Array.java:11)

Attempt to use an un-constructed null object.

Program will compile, but will crash at run time, throwing NullPointerException!

Page 299: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 9 of 134

Listing 9.2 Of course the ideal solution is to make a constructor call soon after the array is declared (Listing 9.3).

>javac CommonMistake_Array.java >java CommonMistake_Array 5

Constructor call is made and memory is allocated on heap.

Value 5 as expected is printed.

Page 300: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 10 of 134

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

ALL ARRAY COMPONENTS CONSTRUCTED NOW!

Page 301: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 11 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; Str_Arr1 = new String [10];

No memory assigned here. Str_Arr1 stores undefined value.

Array created on heap, Str_Arr1 stores the address of the first array cell.

Page 302: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 12 of 134

String [ ] Str_Arr2 = 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.

No memory assigned here. Str_Arr2 stores null.

Page 303: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 13 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. 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.

No length is specified when followed by initialization list.

Page 304: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 14 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.

Page 305: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 15 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

Page 306: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 16 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

Page 307: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 17 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:

arr.length

Array name length data member storing the array length

Page 308: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 18 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.

int_arr.clone( )

Array object int_arr

public member method clone.

Page 309: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 19 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( );

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.

Clones the array int_arr and returns a reference to it as a reference of type java.lang.Object

Casts the reference java.lang.Object to int array as int [ ].

Must be same types!

Page 310: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 20 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

Page 311: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 21 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

Page 312: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 22 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.

Page 313: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 23 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).

Page 314: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 24 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.

Page 315: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 25 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

Page 316: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 26 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();

Page 317: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 27 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 }

Page 318: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 28 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

Page 319: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 29 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 8 7 6 5 4 2 1 0 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. 9 8 7 6 5 4 2 1 0 00023 More data? [Y]es or [N]o? 00024 y

Page 320: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 30 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 2 3 4 5 6 7 8 9 00029 Printing your array to console. 1 2 3 4 5 6 7 8 9 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. 9 8 7 6 5 4 2 1 0 1 2 3 4 5 6 7 8 9 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

Page 321: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 31 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.

Page 322: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 32 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.

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

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

Page 323: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 33 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).

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.

Array reference storing the memory address of first element.

Using Arrays as Arguments to methods

methods

Page 324: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 34 of 134

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

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

Page 325: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 35 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.

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.

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

Page 326: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 36 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.

Page 327: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 37 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 ]; 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 ]; 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.");

Compile error because nums is passed as a final (unchangeable) parameter!!!

Now nums stores a new address, different from the one stored in the caller method!

Page 328: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 38 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";

Page 329: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 39 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 }

Page 330: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 40 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.

Page 331: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 41 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.

Page 332: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 42 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.

Page 333: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 43 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.

Page 334: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 44 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)

Page 335: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 45 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: const int arr[4] = {1,2,3,4}; arr[0] = 10; // 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}; arr_final[0] = 10; 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.

Compile error! The L value, the array name arr is a constant object.

No compile error! The only restriction is that arr_final is not re-assignable

Page 336: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 46 of 134

public class AnonymousArray { 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

static java.io.PrintStream Console

PrintStream object to facilitate printing to console.

private static int MAX A default length parameter for String array instance variable.

Anonymous array created on fly and passed to the method print

Page 337: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 47 of 134

private static java.lang.String[]

Presidents

An array of user defined length to store names of former American presidents.

private static final java.lang.String[]

Singers

An array of names of six American singers with values "Elvis","Maddona","Barry Manilow", "Rex Harrison", "Whitney", "Cindy Lauper"

private java.lang.String[]

Students

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.

Page 338: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 48 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

Page 339: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 49 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)

Page 340: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 50 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();

Page 341: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 51 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] + " ");

Page 342: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 52 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)

Page 343: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 53 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

Page 344: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 54 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 {

Page 345: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 55 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).

Page 346: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 56 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

Page 347: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 57 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<<. char Name[ ] = {‘J’,’a’,’m’,’e’,’s’,NULL}; 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'}; System.out.println (Name); 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. void swap (int & num1, int & num2)

Swap in C++ can be coded such that after method call the values stored in num1 and num2 are swapped.

Forms a string in C/C++

Prints James to console.

Page 348: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 58 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());

Page 349: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 59 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();

Page 350: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 60 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

Page 351: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 61 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

Page 352: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 62 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).

Page 353: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 63 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.

Page 354: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 64 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

Page 355: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 65 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).

Page 356: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 66 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).

Page 357: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 67 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.

Page 358: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 68 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)

Page 359: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 69 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

Page 360: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 70 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):

Page 361: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 71 of 134

C1 = new StringBuffer(new Integer(Data1).toString()); 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.

2. Returns the String form of Integer object. 3. Wraps the String form of Integer object

into a StringBuffer object.

1. Wraps the primitive (int) Data1 into it wrapper Integer.

Page 362: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 72 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).

Page 363: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 73 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.

Page 364: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 74 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.

Page 365: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 75 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).

Page 366: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 76 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.

Page 367: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 77 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.

Page 368: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 78 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

int capacityIncrement

The amount by which the capacity of the vector is automatically incremented when its size becomes greater than its capacity.

protected int

elementCount The number of valid components in this Vector object.

protected Object[]

elementData 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.

Page 369: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 79 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.

Page 370: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 80 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

Page 371: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 81 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,

Page 372: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 82 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.

Page 373: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 83 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. [ “John”, “Mary”, “Ted”, “Adam”, “Tom”, “Pete”] Then if we call the method add as follows: Vec1.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.

Vector Vec1

Vec1 after the call Vac1.add(3,”Marcy”);

Page 374: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 84 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”] 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. System.out.println (Vec1.set(2, “Margo”)); 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.

Vec1 expanded by calls to add and addElement

Replaces “Ted” with Margo and prints “Ted” on console.

Page 375: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 85 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. System.out.println (Vec1.indexOf (“Tom”)); System.out.println (Vec1.lastIndexOf (“Tom”)); 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.

Both will print 5 on console. Vec1 is described in Figure 9.33B

Page 376: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 86 of 134

System.out.println (Vec1.size( ) ); 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. String Str = Vec1.toString ( ); System.out.println (Str); 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!

Will print 9 on console. Vec1 is described in Figure 9.33B.

Will print the following on console [John, Mary, Ted, Marcy, Adam, Tom, Pete, Jefferson, Jeff] Vec1 is described in Figure 9.33B.

Page 377: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 87 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).

Page 378: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 88 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.

Page 379: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 89 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

Page 380: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 90 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).

Page 381: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 91 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).

Page 382: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 92 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.

Page 383: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 93 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(),};

Page 384: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 94 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 }

Page 385: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 95 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);

Page 386: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 96 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)

Page 387: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 97 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); Object Obj = I2; if (Obj instanceof Integer) 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. Integer I2 = new Integer(5); if(I2 instanceof Double) System.out.println (true);

9 Further details of RTTI are discussed in a separate chapter later.

Compile error because at compile time it can be determined unambiguously that I2 is not convertible to type Double.

Will print true as Obj stores address of Integer I2, which is indeed and Integer instance.

Page 388: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 98 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 5 1 8 3 3 00006 Before swapping values at index 1 and 4, the array is:

00007 7 3 2 0 4 7 8 00008 Calling the method swap6

Page 389: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 99 of 134

00009 After swapping values at index 1 and 4, the array is:

00010 7 4 2 0 3 7 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

Page 390: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 100 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 {

Page 391: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 101 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.

Page 392: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 102 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

Page 393: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 103 of 134

FIG. 9.37 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

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. If 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.

Page 394: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 104 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 }

Page 395: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 105 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 {

Page 396: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 106 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,

Page 397: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 107 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.

Page 398: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 108 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

Page 399: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 109 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 Double Val = Array.get(arr, index); 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.

Will return primitive double at location index as object Double

Page 400: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 110 of 134

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: Arr1 = Arr2; 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

Out of bound Index!!!! Compiler will not save you.

Will not copy Arr2 elements into Arr1, even though it will compile!!!!

Page 401: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 111 of 134

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.");

Will compile, but will only check for equality of addresses stored in Arr1 and Arr2.

Page 402: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 112 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) {

Page 403: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 113 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

Page 404: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 114 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

Page 405: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 115 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};

Page 406: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 116 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).

Page 407: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 117 of 134

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.

int [] freqCount = new int[91];

Page 408: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 118 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 {

Page 409: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 119 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.

Page 410: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 120 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.

Page 411: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 121 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).

Page 412: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 122 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

Page 413: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 123 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)

Page 414: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 124 of 134

Page 415: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 125 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());

Page 416: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 126 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"+

Page 417: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 127 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; } /** * */

Page 418: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 128 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] + " ");

Page 419: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 129 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)

Page 420: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 130 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);

Page 421: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 131 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();*/ }

Page 422: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 132 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:");

Page 423: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 133 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) {

Page 424: Java_E_Book_Satish_Singhal

CS3 Java – Topic 9: Arrays (Singhal) Page 134 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(); } }

Page 425: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 1 of 112

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: //************************************************* class MyClass { //---------------- }//Listing 10.1 //**********************************************

Note the absence of package name! This means that class is in an unknown package and is not accessible outside it!

Page 426: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 2 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: //*************************************************

package datastructures; public class MyClass2 { //---------------- } 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

Includes the package name of which the class is member.

Class is declared public.

Page 427: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 3 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. //************************************************* public class MyClass { int value; static int standard_num; static int findSquare(int val) { return val*val; } 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.

Instance field

Class field

Class method

Instance method

Page 428: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 4 of 112

//************************************************************* public class TestMyClass { public static void main(String[] args) { MyClass Temp1 = new MyClass( ); Temp1.value = -10; MyClass.standard_num = 100; MyClass Temp2 = new MyClass( ); Temp2.value = -30; System.out.println (Temp1.toString( )); System.out.println (Temp2.toString( )); int num = MyClass.findSquare (5); System.out.println ("Value of square of 5 = " + num); } } Listing 10.4 //**********************************************************************

Calling instance method.

Setting the value of an instance field. Field named “value” had no modifier attached to it.

Setting the value of a class field.

Calling class

TestMyClass is the client class residing in the same package as MyClass.

Page 429: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 5 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.

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.

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.

Page 430: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 6 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.

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.

Class “ a class” must be declared public. And must be in a named package.

Page 431: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 7 of 112

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.

Clients that lie outside the package also lie outside the area of visibility!

Also visible to clients inside the package, in which the class “a class” is !!

Need not lie inside the same package in which “ a class” is!

Page 432: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 8 of 112

FIG. 10.4

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!

Sub classes inherit the private fields and methods but they do not have direct access to them.

Page 433: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 9 of 112

The Figure 10.5 below shows how the visibility of package-private fields and methods work.

Package – Private or No M odifierPackage

boundary

a class

Field with no modifier

Client 1

Client 2

Subclass 1

Subclass 2

Area of visibility.

Clients and subclasses, both must 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).

Page 434: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 10 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.

Page 435: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 11 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

Page 436: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 12 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

Page 437: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 13 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). 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.

public class Vehicle { //Fields and Methods } public class Airplane extends Vehicle { //Fields and Methods }

Uses the keyword extends to establish inheritance!

Page 438: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 14 of 112

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.

public class Vehicle { protected double speed; } public class Airplane extends Vehicle { protected int numberOfwings; } public class Jet extends Airplane { protected double enginethrust; }

Visible to classes Airplane and Jet. However, invisible to client code, like main function, when doing black box testing and client lies outside the package.

Visible to class Jet, but invisible to client code, like main function, when doing black box testing and client lying outside the package.

Page 439: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 15 of 112

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

public class Vehicle { protected double speed; public Vehicle( ) { this (0.0); } public Vehicle (double init_speed) { speed = init_speed;

} public void describe( ) { System.out.println ("I am an abstract Vehicle\n"); } }

Chains the constructor with no argument to the constructor with speed as an argument! Keyword this refers to calling the constructor, in this case the one with one argument.

Page 440: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 16 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

Page 441: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 17 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

Page 442: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 18 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

Page 443: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 19 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

Page 444: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 20 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

Page 445: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 21 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

Page 446: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 22 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. 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.

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.

With exception of java class Object; ALL classes in java are derived classes!!!

Listing 10.6

Page 447: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 23 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 { public static void main(String[ ] args) { Vehicle Veh1 = new Jet(500,4, 200); Veh1.describe( ); Veh1 = new Airplane(400, 2); Veh1.describe( ); Veh1 = new Car ( 60, 4, 20); Veh1.describe( ); } } Listing 10.7 The output of the Listing 10.7 is shown in the Figure 10.14.

Veh1 points to an object of type Jet.

Jet class describe method is called.

Veh1 now points to an object of type Car.

Car class describe method is called.

Comment [p1]: Figure 10.13,

Page 448: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 24 of 112

FIG. 10.14

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).

Comment [p2]: Listing 10.7

Page 449: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 25 of 112

Sequence of Construction of Jet class instance

Object Constructor call

Vehicle Constructor call

Airplane Constructor call

Jet Constructor call

TimeObject part is created first!

Vehicle part is created

next

Jet part is created Last!

FIG. 10.15 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.

Comment [p3]: Listing 10.7

Page 450: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 26 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.

Page 451: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 27 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) { Object Temp = new Jet(500, 4, 200); if(Temp instanceof Jet) { Jet Jet1 = (Jet)(Temp); 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).

If Temp is type Jet, then instanceof will return true otherwise it will return false.

Now it is safe to cast Temp into Jet Type

Page 452: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 28 of 112

} } 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 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.

Comment [p4]: Figure 10.15

Comment [p5]: Listing 10.8

Page 453: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 29 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: 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

public final class FinalClass { //----------------------------- }

Page 454: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 30 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. 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).

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.*/ }

Page 455: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 31 of 112

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) { MyClass MC1 = null; MyClass MC2 = new MyClass( ); MC2.printHello(); } }//Listing 10.9 8 Abstract class cannot be instantiated, though it can be used as a reference type. We discuss abstract classes shortly.

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*/

}

If method printHello is commented out then all statements in main will give compile error!

Comment [p6]: Figure 10.16

Page 456: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 32 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 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:

Comment [p7]: Listing 10.9

Page 457: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 33 of 112

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 { public void open( ); public void close( ); }//Listing 10.10A public class CarDoor implements 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 { public static void main( String[ ] args ) { Door Instance1 = new CarDoor( );

public interface SomeInterface extends Interface1 { } public interface SomeInterface extends Interface1, Interface2 { }

Only abstract methods!!! Use of access specifier public is optional and can be left out.

A reference of type Door can point to an object of type CarDoor because CarDoor is-a Door.

Provides implementation for all the methods inherited from interface Door!

Page 458: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 34 of 112

Instance1.open( ); CarDoor Instance2 = new CarDoor( ); Instance2.close( ); } }//Listing 10.10C 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.

Comment [p8]: Figure 10.17

Page 459: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 35 of 112

FIG. 10.18 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 [p9]: Listing 10.10

Comment [p10]: Listing 10.10

Page 460: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 36 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.

Person

Student Voter

StudentVoter

FIG. 10.20 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).

In C++ Person, Student, Voter, and StudentVoter can all be classes!

Comment [p11]: Listing 10.10

Page 461: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 37 of 112

Student

StudentVoter

Person

Voter

FIG 10.21 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

In java, diamond inheritance as this Figure is possible by making entities Person and Voter as Interfaces.

Comment [p12]: Listing 10.10

Page 462: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 38 of 112

StudentVoter Shown on next page!

Page 463: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 39 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 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.

Comment [p13]: Figure 10.22

Page 464: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 40 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 After coding the two interfaces, now we can code the necessary classes. First, we 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;

Comment [p14]: Figure 10.22

Comment [p15]: Figure 10.22

Page 465: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 41 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 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.

Comment [p16]: Figure 10.22

Page 466: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 42 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;

Page 467: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 43 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 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.

Comment [p17]: Figure 10.22

Page 468: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 44 of 112

public class TestDiamond { public static void main(String[] args) { 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 */

StudentVoter type object being pointed to by same type reference.

Page 469: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 45 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

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.

Comment [p18]: Figure 10.22

Page 470: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 46 of 112

FIG. 10.23 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.

The polymorphic method selectionSort sorts the Person type array alphabetically.

Comment [p19]: Listing 10.11

Page 471: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 47 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. FIG. 10.24 Example of an abstract class and its extension. Let us consider the following inheritance hierarchy (Figure 10.25).

Abstract_Shape_Inher.ppt

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.

Comment [p20]: Listing 10.11

Page 472: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 48 of 112

FIG. 10.25 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.

Comment [p21]: Listing 10.11

Page 473: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 49 of 112

class Shape The Listing 10.12 below gives the code for the abstract class Shape.

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.

Abstract Method

Implemented Methods

Uses the keyword abstract

Comment [p22]: Figure 10.25

Page 474: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 50 of 112

class Point The source code for the class Point is given below in the Listing 10.13 public class Point extends Shape { protected int x; protected int y; public Point() { this(0); } public Point(int a) { this(a,0); } public Point(int a, int b) { this.x = a; this.y = b; } public String getName() { return "Point"; } public void setPoint(int a, int b) { this.x = a; this.y = b; } public void setX(int x1) { this.x = x1; } public void setY(int y1) { this.y = y1; } public int getX()

Fields are x and y coordinates for the Point.

Default and explicit constructors, all chained together.

abstract method from the parent class Shape implemented.

Other methods of class Point.

Page 475: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 51 of 112

{ return this.x; } public int getY() { return this.y; } public String toString( ) { return "[" + this.x + ", " + this.y + "]"; } } Listing 10.13 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; public Square() { this(0.0); } public Square(double edge1) { this(edge1,0,0); } public Square(double edge1, int a) { this(edge1, a, 0); } public Square(double m_edge, int a, int b) { super(a,b); setEdge(m_edge); } public void setEdge(double m_edge) {

New field edge is added. It inherits x and y.

Constructors

Methods

Overrides the toString method from Object class.

Comment [p23]: Figure 10.25

Page 476: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 52 of 112

this.edge = (m_edge >= 0 ? m_edge : 0 ); } public double getEdge() { return this.edge; } 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 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() { 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)

Constructors

Overrides the super class methods

Comment [p24]: Figure 10.25

Page 477: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 53 of 112

{ super(m_edge, a , b); } 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 The UML(Unified Modeling Language) diagram for all these classes is given on next page (Figure 10.26).

Overrides the super class methods.

Comment [p25]: Figure 10.25

Page 478: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 54 of 112

FIG. 10.26 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 {

Comment [p26]: Listing 10.15

Page 479: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 55 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

Page 480: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 56 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 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.

Comment [p27]: Figure 10.26

Page 481: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 57 of 112

FIG. 10.27 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,

Comment [p29]: Listing 10.16

Page 482: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 58 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.

Page 483: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 59 of 112

FIG. 10.28 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.

Comment [p28]: Listing 10.15

Page 484: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 60 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

Page 485: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 61 of 112

FIG 10.29 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.

Comment [p31]: Listing 10.17

Page 486: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 62 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: 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

Object of a class that would have event handling method is passed as an argument.

Page 487: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 63 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. import java.awt.*; 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 aWindow.setBounds (50,100,400,150); aWindow.setVisible (true); } }//Listing 10.18A 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.

1. Create object of Frame class.

2. Set Frame coordinates (bounds).

3. Make the Frame visible.

Comment [p32]: Figure 10.29

Page 488: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 64 of 112

java.lang.Object java.awt.Component java.awt.Container java.awt.Window java.awt.Frame FIG 10.30 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 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 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.

Comment [p33]: Listing 10.18A

Comment [p34]: Listing 10,18A

Comment [p35]: Listing 10.18A

Page 489: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 65 of 112

FIG. 10.33 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

Height = 150

Point 50, 100 in pixels from top left corner of screen.

Width = 400

Comment [p36]: Listing 10.18A

Comment [p37]: Figure 10.33

Page 490: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 66 of 112

FIG. 10.34 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

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

Comment [p38]: Listing 10.18B

Comment [p39]: Listing 10.18B

Page 491: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 67 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

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

Comment [p40]: Fig. 10.35, Listing 10.18B

Page 492: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 68 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. However, a nested class can be declared static. For example, the declaration like below is OK.

static class ExplicitStatic { }

Compile time error. A stand-alone class cannot be declared static.

public class Outer { static class NetsedClass { Can declare static variables and constants. } }

This is OK!!

public class Outer { class InnerClass { //Cannot declare static variables!! //Can declare static constants! } }

This is also OK!!

public class Outer { class InnerClass extends SomeClass { //Cannot declare static variables!! //Can declare static constants! } }

This is also OK!!

Page 493: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 69 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 { } public class InnerClass { } } public class TestOuter { public static void main(String[] args) { Outer.NestedClass Temp = new Outer.NestedClass(); Outer Temp_Outer = new Outer(); Outer.InnerClass Inst_Inner = Temp_Outer.new InnerClass( ); } } Listing 10.19

Needed because NestedClass is enclosed and needs to be qualified by its outer class. Since Nested class is static, just the class name is enough for qualification!

Data type for both also need to be qualified

Qualified name of the constructor of InnerClass needs dot operator with the instance of outer class to which the instance Inst_Inner belongs.

Comment [p41]: Fig. 10.35, Table 10.1,

Page 494: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 70 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): Outer.InnerClass Inst_Inner = Temp_Outer.new InnerClass( ); FIG. 10.36 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.

FIG. 10.37

Name of the Outer class object associated with the instance Inst_Inner

Constructor for the InnerClass.

Object Inst_Inner

Object Temp_Outer

Comment [p42]: Listing 10.19, Table 10.1

Comment [p43]: Listing 10.19, Table 10.1

Page 495: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 71 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.*; import java.awt.event.*; public class TryWindow1 { static Frame aWindow = new Frame("My awt Window!! Do Not Touch."); static class CloseWindow implements WindowListener { //code for bodies of 7 event handler methods from WindowListener Interface } public static void main(String[] args) { aWindow.addWindowListener (new CloseWindow( ) ); aWindow.setBounds (50,100,400,150); aWindow.setVisible (true); } }//Listing 10.20A 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

1. Needed because WindowListener interface is in java.awt.event package

2. Implements the bodies of seven event handlers from WindowListener interface.

3. Registration of Window component with the object containing event handlers!

Comment [p44]: Figure 10.37, Table 10.1

Comment [p45]: Figure 10.37, Table 10.1

Page 496: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 72 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 The sidebar below describes the overall functioning of Listing 10.20B.

Comment [p46]: Figure 10.37, Table 10.1

Page 497: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 73 of 112

In Listing 10.20 we accomplish the closing of program window as follows. 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 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

1. The Frame object is registered with a “listener” by calling its inherited 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.

Comment [p47]: Listing 10.20B, Table 10.1

Page 498: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 74 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.

Page 499: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 75 of 112

import java.awt.*; import java.awt.event.*; public class AwtWindowWithLabel extends Frame { private Label My_Label; public AwtWindowWithLabel() { super ("A Simple Window with a label in it!"); My_Label = new Label("Java Window Label"); add(My_Label); setSize(400,120); setVisible(true); } public static void main(String[] args) { final AwtWindowWithLabel Temp = new AwtWindowWithLabel(); class HelpCloseWindow extends WindowAdapter { public void windowClosing(WindowEvent Evt) { Temp.dispose(); System.exit(0); } } Temp.addWindowListener (new HelpCloseWindow( )); } }//Listing 10.21A

1. Uses inheritance as the class extends from Frame class.

2. Declares an instance variable of type Label

3. Calls the super class (Frame class) constructor.

4. Calls the Label class constructor to create the object My_Label.

5. Uses the add method inherited from super class Container to add the Label to the object of class AwtWindowWithLabel.

6. Uses the setSize method from super class Container to set the size of object of class AwtWindowWithLabel.

7. A variable to be used by a local class must be declared final!

8. Local class extends WindowAdapter class and implements the event handler method!

Comment [p48]: Listing 10.21A, Table 10.1, Fig. 10.38

Page 500: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 76 of 112

Figure 10.39 below shows the output of the Listing 10.21A.

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.

Comment [p49]: Listing 10.21A, Table 10.1, Fig.10.39

Page 501: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 77 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.

Page 502: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 78 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 ( ); Temp.addWindowListener ( new WindowAdapter( ) { public void windowClosing (WindowEvent Evt) { Temp.dispose ( ); System.exit(0); } } ); } }

1. Notice that when we use the anonymous class to be extended or implemented, the use of keyword extends or implements is omitted.

2. Pair of braces after the constructor call defines the body of anonymous class 3. The

unimplemented and other methods are now coded inside the pair of braces { }, which define the anonymous class.

4. The right parenthesis for the method addWindowListener seems out of place and awkward but is syntactically correct!

Listing 10.21B

Page 503: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 79 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.

Page 504: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 80 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.

12 Local definition means defining with in a stand-alone block, constructor, or a method.

public class LocalClasses { { class Class1 { } } static { class Class2 { } } public LocalClasses( ) { class Class3 { } } public static void main(String[ ] args) { class Class4 { } } } Listing 10.22

Class defined within a stand-alone non-static block.

Class defined within a stand-alone static block.

Class defined within a constructor.

Class defined within a static method. Same way the classes can be defined within non-static methods as well.

Page 505: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 81 of 112

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.

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. 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.

public class EncloseInterface { interface NestedInterface1 { } }

public class EncloseInterface { interface NestedInterface1 { } } class Class1 implements EncloseInterface.NestedInterface1 { }

Note that to access the nested interface it must be qualified with the class, which encloses it.

Comment [p50]: Table 10.1, Fig. 10.39, Listing 10.22

Page 506: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 82 of 112

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.

public class EncloseInterface { private interface NestedInterface1 { } { class someclass implements NestedInterface1 { } } }

Private nested interfaces are only visible within their member class.

Page 507: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 83 of 112

Listing 10.26

public interface InterfaceNesting { void method1( ); interface NestedInterface2 { void method2( ); } abstract class ClassInInterface { public abstract void method3 ( ); } } class MyClass implements InterfaceNesting { public void method1( ){ } } class YourClass implements InterfaceNesting.NestedInterface2 { public void method2( ){ } } class TheirClass extends InterfaceNesting.ClassInInterface implements InterfaceNesting.NestedInterface2, InterfaceNesting { public void method1( ){ } public void method2( ){ } public void method3 ( ) { } }

Only responsible to implement the method1.

Only responsible to implement method2.

Must implement all method1, method2 and method3.

Comment [p51]: Listing 10.26, Table 10.1, Figure 10.39

Page 508: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 84 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"); }

Page 509: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 85 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 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 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 [p52]: Listing 10.27, Table 10.1, Fig. 10.39

Comment [p53]: Fig. 10.40A, table 10.1, Listing 10.27

Comment [p54]: Fig. 10.40B, Table 10.1, Listing 10.27

Page 510: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 86 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 Object

clone() Creates and returns a copy of this object.

boolean equals(Object obj) Indicates whether some other object is "equal to" this one.

protected void

finalize() 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.

Page 511: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 87 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); the output could be of type: 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).

Default toString from Object class is called. The default toString only prints class name and hash code in hexadecimal.

Page 512: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 88 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 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 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

Comment [p55]: Listing 10.28, Table 10.2, Figure 10.40B

Comment [p56]: Listing 10.28, Figure 10.41, Table 10.2

Page 513: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 89 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 { public static void main(String [] args) { MyClass Temp1 = new MyClass ( ); MyClass Temp2 = Temp1; boolean are_same = Temp1.equals (Temp2); } }

Since MyClass does not override equals method, the Object class Equals method is called.

Page 514: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 90 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 " +

Page 515: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 91 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 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.

Comment [p57]: Listing 10.29, Figure 10.41, Table 10.2

Page 516: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 92 of 112

FIG. 10.42 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.

Comment [p58]: Listing 10.29, Fig. 10.42, Table 10.2

Page 517: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 93 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

Page 518: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 94 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 class member

Instance Name

Hash code Multiply with a prime number14

PrimitiveData15 variable new PrimitiveData(variable).hashCode( )

X

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 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.

Comment [p59]: Listing 10.29, Fig. 10.42, Table 10.3

Page 519: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 95 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 }

Page 520: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 96 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 }

Page 521: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 97 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 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).

Comment [p60]: Listing 10.30, Fig. 10.42, Table 10.3

Page 522: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 98 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);

Page 523: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 99 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

Page 524: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 100 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.

Page 525: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 101 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;

Page 526: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 102 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.

Page 527: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 103 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?

Page 528: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 104 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.

Page 529: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 105 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.

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:

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

Page 530: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 106 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 ; public CloseableWindow3( ) { 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); } } public static void main(String [] args) { CloseableWindow3 Instance = new CloseableWindow3( ); Instance.My_Window.setBounds(10,10,600,600); Instance.My_Window.setBackground(Color.blue); Instance.My_Window.setVisible(true); CloseableWindow3.WindowClosing Object_WindowClosing = Instance.new WindowClosing(); Instance.My_Window.addWindowListener(Object_WindowClosing);

A constructor to instantiate the object Frame is now needed. Otherwise the inner class WindowClosing will not know as to which My_Window to dispose.

Before the dispose can be called on My_Window, we need an object of type CloseableWindow3 to establish a binding between the outer class and inner class objects.

Creation of My_Window also needs an object of type ClosingWindow3.

Page 531: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 107 of 112

} } 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(); } public static void display1( ) { CloseableWindow4 Instance = new CloseableWindow4(); Instance.My_Window.setBounds(100,100,100,100); Instance.My_Window.setBackground(Color.yellow); Instance.My_Window.setVisible(true); CloseableWindow4.WindowClosing Object_WindowClosing = Instance.new WindowClosing();

Listing 10.18

Method display has the same code as the main method, except the window is smaller and yellow in color and its origin is located differently.

Listing 10.19

Page 532: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 108 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.

Page 533: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 109 of 112

Page 534: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 110 of 112

Page 535: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 111 of 112

Page 536: Java_E_Book_Satish_Singhal

Lecture Inheritance Page 112 of 112

Page 537: Java_E_Book_Satish_Singhal

Chapter 11 Multidimensional Arrays And Searching And Sorting

Chapter to be written ☺

Page 538: Java_E_Book_Satish_Singhal

Java Exception Handling Page 1 of 49

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.

Page 539: Java_E_Book_Satish_Singhal

Java Exception Handling Page 2 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) { if(den == 0) return 0; else { *result = (num/den); return 1; } } ////////////////////////////////////// void main( ) { int * result = (int*) malloc(sizeof(int)); int num = 5; int den = 0; 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

Caller method first checks the return value from the divide method, and then prints appropriate message.

Pointee of pointer result is unaltered for zero value of denominator.

Page 540: Java_E_Book_Satish_Singhal

Java Exception Handling Page 3 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.

Page 541: Java_E_Book_Satish_Singhal

Java Exception Handling Page 4 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

Page 542: Java_E_Book_Satish_Singhal

Java Exception Handling Page 5 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).

Page 543: Java_E_Book_Satish_Singhal

Java Exception Handling Page 6 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). 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 } catch(Exception Ex) { //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.

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.

Ex should be of type Exception or its sub type.

Page 544: Java_E_Book_Satish_Singhal

Java Exception Handling Page 7 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.

Page 545: Java_E_Book_Satish_Singhal

Java Exception Handling Page 8 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).

Page 546: Java_E_Book_Satish_Singhal

Java Exception Handling Page 9 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.

Page 547: Java_E_Book_Satish_Singhal

Java Exception Handling Page 10 of 49

public class ExceptionTypes { private ExceptionTypes ( ){ } /** * Method method1 throws an exception of type * 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.

Throws clause required because body of method1 throws an object, which needs to be broadcast.

Page 548: Java_E_Book_Satish_Singhal

Java Exception Handling Page 11 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: 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. 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

Compile error would be caused if throws clause is missing.

Syntax of a throw statement

Page 549: Java_E_Book_Satish_Singhal

Java Exception Handling Page 12 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 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); 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.

This call in Listing 12.5 main method would be a compile error.

This call will compile because method2 throws a run time exception. However, the program execution would terminate after the method call.

Page 550: Java_E_Book_Satish_Singhal

Java Exception Handling Page 13 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.

Page 551: Java_E_Book_Satish_Singhal

Java Exception Handling Page 14 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.

Page 552: Java_E_Book_Satish_Singhal

Java Exception Handling Page 15 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 code

Exception class object thrown Type of the Object thrown

int val = Integer.parseInt(“Hello”);

NumberFormatException1 RuntimeException

int [ ] arr = new int [5]; arr[10] = 10;

ArrayIndexOutOfBoundsException1 RuntimeException

String Str = null; Str.length ( );

NullPointerException1 RuntimeException

Vector V= new Vector ( ); V.firstElement( );

NoSuchElementException1 RuntimeException

Object I = new Integer(5); Double Dbl = (Double)(I);

ClassCastException1 RuntimeException

BufferedReader BR = null; try { BR = new BufferedReader (new FileReader("G:\\text.txt")); } catch(Exception ex) { System.out.println (ex); }

FileNotFoundException2 Exception (checked exception)

Assume that no drive with letter G exists.

Page 553: Java_E_Book_Satish_Singhal

Java Exception Handling Page 16 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.

Page 554: Java_E_Book_Satish_Singhal

Java Exception Handling Page 17 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

Page 555: Java_E_Book_Satish_Singhal

Java Exception Handling Page 18 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 Number

Class and method/constructor used

Name of the Exception thrown

Type of Exception (Checked or unchecked)

4 BufferedReader/readLine IOException checked 5 File/Constructor that takes

file name string as argument

NullPointerException unchecked

6 FileReader/Constructor that takes File object as argument

FileNotFoundException checked

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

that takes FileReader and integer as buffer size as arguments

IllegalArgumentException unchecked

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.

Page 556: Java_E_Book_Satish_Singhal

Java Exception Handling Page 19 of 49

Exception Names Inheritance Hierarchy

IllegalArgumentException, and NumberFormatException

java.lang.Object java.lang.Throwable java.lang.Exception java.lang.RuntimeException java.lang.IllegalArgumentException java.lang.NumberFormatException

NullPointerException

java.lang.Object java.lang.Throwable java.lang.Exception java.lang.RuntimeException java.lang.NullPointerException

SecurityException

java.lang.Object java.lang.Throwable java.lang.Exception java.lang.RuntimeException java.lang.SecurityException

IOException and FileNotFoundException

java.lang.Object java.lang.Throwable java.lang.Exception java.io.IOException 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).

Page 557: Java_E_Book_Satish_Singhal

Java Exception Handling Page 20 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 } catch(IOException ex) { //code } catch(FileNotFoundException ex) { //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.

“Unreachable” catch blocks as the first block also catches exceptions of type FileNotFoundException.

Compile error!

Page 558: Java_E_Book_Satish_Singhal

Java Exception Handling Page 21 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}

Page 559: Java_E_Book_Satish_Singhal

Java Exception Handling Page 22 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 {

Page 560: Java_E_Book_Satish_Singhal

Java Exception Handling Page 23 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;

Page 561: Java_E_Book_Satish_Singhal

Java Exception Handling Page 24 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 }

Page 562: Java_E_Book_Satish_Singhal

Java Exception Handling Page 25 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

Page 563: Java_E_Book_Satish_Singhal

Java Exception Handling Page 26 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

Page 564: Java_E_Book_Satish_Singhal

Java Exception Handling Page 27 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.

Page 565: Java_E_Book_Satish_Singhal

Java Exception Handling Page 28 of 49

FIG. 12.9

1. NullPointer Exception thrown/caught

2. FileNotFoundException thrown/caught

4. IllegalArgumentException thrown

3. NumberFormatException thrown.

Page 566: Java_E_Book_Satish_Singhal

Java Exception Handling Page 29 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.

Page 567: Java_E_Book_Satish_Singhal

Java Exception Handling Page 30 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 finally { //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

Always executed (As long as the preceding try and catch blocks do not call System.exit (0).

Page 568: Java_E_Book_Satish_Singhal

Java Exception Handling Page 31 of 49

following piece of code using a finally clause between the lines 129 and 130 (Figure 12.12). finally { try { BR.close ( ); } 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.

Unless an IOException is thrown again, the rescue code closes the file safely!

Page 569: Java_E_Book_Satish_Singhal

Java Exception Handling Page 32 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;

Page 570: Java_E_Book_Satish_Singhal

Java Exception Handling Page 33 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.

Page 571: Java_E_Book_Satish_Singhal

Java Exception Handling Page 34 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]; int val = arr[0];

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

Will throw ArrayIndexOutOfBoundsException since array size is zero and there are no elements in it.

Page 572: Java_E_Book_Satish_Singhal

Java Exception Handling Page 35 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

Page 573: Java_E_Book_Satish_Singhal

Java Exception Handling Page 36 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

Page 574: Java_E_Book_Satish_Singhal

Java Exception Handling Page 37 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)

Page 575: Java_E_Book_Satish_Singhal

Java Exception Handling Page 38 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); }

Page 576: Java_E_Book_Satish_Singhal

Java Exception Handling Page 39 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

Page 577: Java_E_Book_Satish_Singhal

Java Exception Handling Page 40 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] + " ");

Page 578: Java_E_Book_Satish_Singhal

Java Exception Handling Page 41 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 {

Page 579: Java_E_Book_Satish_Singhal

Java Exception Handling Page 42 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

Page 580: Java_E_Book_Satish_Singhal

Java Exception Handling Page 43 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

Page 581: Java_E_Book_Satish_Singhal

Java Exception Handling Page 44 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

Page 582: Java_E_Book_Satish_Singhal

Java Exception Handling Page 45 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

Page 583: Java_E_Book_Satish_Singhal

Java Exception Handling Page 46 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).

Page 584: Java_E_Book_Satish_Singhal

Java Exception Handling Page 47 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; }

Page 585: Java_E_Book_Satish_Singhal

Java Exception Handling Page 48 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

Page 586: Java_E_Book_Satish_Singhal

Java Exception Handling Page 49 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

Page 587: Java_E_Book_Satish_Singhal

Java Object Serialization• What is serialization?

Wh is seriali ation important?• Why is serialization important?• How is it done?

S l f j S i li ti• Some examples of java Serialization

Page 588: Java_E_Book_Satish_Singhal

What is Serialization?• So far you have been used to writing the details of

java objects into text files by breaking up thejava objects into text files, by breaking up the object details into ASCII format.

• Then to read such objects back you would needThen to read such objects 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.

Page 589: Java_E_Book_Satish_Singhal

What is Serialization?• Serialized objects can also be transmitted over the

network to other computers and then this othernetwork 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

himachine.

Page 590: Java_E_Book_Satish_Singhal

What is Serialization?• Process of writing an object to a file as an object

is called “serialization”is called serialization .• Process of reading an object from a file and

adding it in a program memory or object pool isadding it in a program memory or object pool is called de-serialization.

• Serialization writes a live object into a file.Se o w es ve objec o e.• De-serialization reads a object from a file and

makes it alive in the program.p g

Page 591: Java_E_Book_Satish_Singhal

Serialization allows Lightweight Object Persistence!Object Persistence!

• Object persistence means that Object‘s lifetime is not dependent on whether a program is innot 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.

Page 592: Java_E_Book_Satish_Singhal

How do we make an Object Serializable?Serializable?

• Java has an interface called “Serializable”Seriali able interface has no methods or static• Serializable interface has no methods or static constants in it.

• Serializable interface thus acts like a flag for the• Serializable interface thus acts like a flag for the objects that need to be serialized.

• The objects to be serialized must implement the• The objects to be serialized must implement the interface “Serializable”.

Page 593: Java_E_Book_Satish_Singhal

Java Serializable Interface

Serializable Interface

Page 594: Java_E_Book_Satish_Singhal

Simple Serialization Syntaximport java.io.*;

public class MyClass implements serializable{

//class code here//class code here}

Page 595: Java_E_Book_Satish_Singhal

What is the next Step?• Objects become serializable by implementing the

interface “Serializable”interface Serializable .• In order to perform the process of serialization/de-

serialization i e to write them as objects to a fileserialization, i. e. to write them as objects to a file and read them back, help is needed from few other java classes.

• These classes are:• ObjectOutputStreamj p• ObjectInputStream• Other Sub-classes of OutputStream ClassOther Sub classes of OutputStream Class

Page 596: Java_E_Book_Satish_Singhal

For example to write an Object to a File? ( step 1)a File? ( step 1)

• We create a FileOutputStream object as follows:FileO tp tStream File HandleFileOutputStream File_Handle = new FileOutputStream(“myoutput.dat”);

Th bj t l t it ill b itt t th• The object we plan to write will be written to the file myoutput.dat on the default drive.Th th bj t Fil H dl• Then we pass the object File_Handle as an argument to the an OutputStream object as follows:

ObjectOutputStream Out =ObjectOutputStream Out =new ObjectOutputStream (File_Handle );

Page 597: Java_E_Book_Satish_Singhal

For example to write an Object to a File? ( step 2)a File? ( step 2)

• The ObjectOutputStream class has a method called: writeObject which takes the serializable object towriteObject, which takes the serializable object to be written to a file as an argument.

• Therefore we simply write statements such asTherefore we simply write statements such asOut.writeObject(“String Object”);Out writeObject(new Integer(5));Out.writeObject(new Integer(5));Out.writeObject(new Double(5.5));• The above syntax allows the objects “String• The above syntax allows the objects String

Object”, object form of integer 5 and double 5.5 to be written to the file myoutput.datbe written to the file myoutput.dat

Page 598: Java_E_Book_Satish_Singhal

For example to write an Object to a File? ( step 3)a File? ( step 3)

The reason strings, Integer and Double can be written as objects to a file are because they all implementas objects to a file are because they all implement the serializable interface!

Page 599: Java_E_Book_Satish_Singhal

Object De-serialization• The serialized objects written to a file can be made

alive in a program memory by the process of de-alive in a program memory by the process of de-serialization.

• The steps in de-serialization are similar to the one’sThe steps in de serialization are similar to the one s that were used for serialization.

• We discuss the steps in the de-serialization process.We d scuss e s eps e de se o p ocess.• De-serialization needs help from the following java

classes:• Class FileInputStream• Class ObjectInputStreamClass ObjectInputStream• Sub classes of ObjectInputStream

Page 600: Java_E_Book_Satish_Singhal

Object De-serialization •Step –1 Prepare to read the file containing serialized objects.

• Bind the data input file with an object of class FileInputStream, as follows:

j

p• 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 bj f bjobject of type ObjectInputStream.

Page 601: Java_E_Book_Satish_Singhal

Object De-serialization •Step –2 Bind the object of type FileInputStream with an object of type ObjectInputStream.

• ObjectInputStream Input = new ObjectInputStream(In Handle);

j yp j p

ObjectInputStream(In_Handle);• The object Input can now read the objects from the

input file “myInput.dat”.p y p• Reading is done by a method of class

ObjectInputStream.j p• The method is readObject ( ).• Step 3 shows the syntax.p y

Page 602: Java_E_Book_Satish_Singhal

Object De-serialization •Step –3 Read the file by using the method readObject ( )

• Object obj1 = Input.readObject( );• Note that method readObject ( ) returns an object.

j

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.

Page 603: Java_E_Book_Satish_Singhal

Graphical User Interface (Singhal) Page 1 of 41

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.

Page 604: Java_E_Book_Satish_Singhal

Graphical User Interface (Singhal) Page 2 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

Page 605: Java_E_Book_Satish_Singhal

Graphical User Interface (Singhal) Page 3 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

Page 606: Java_E_Book_Satish_Singhal

Graphical User Interface (Singhal) Page 4 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.

Page 607: Java_E_Book_Satish_Singhal

Graphical User Interface (Singhal) Page 5 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

Page 608: Java_E_Book_Satish_Singhal

Graphical User Interface (Singhal) Page 6 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.*; 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.

1. Declaration

Page 609: Java_E_Book_Satish_Singhal

Graphical User Interface (Singhal) Page 7 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 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

00090 Button1.addActionListener(Handler);

2. Instantiation

3. Registration

Page 610: Java_E_Book_Satish_Singhal

Graphical User Interface (Singhal) Page 8 of 41

91 Button2.addActionListener(Handler); 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 javax.swing.JButton

Button2 Simple JButton to show on MyWindow.

private static int height The height in pixel chosen for the MyWindow object.

private static java.lang.String

Title 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 static java.awt.Color

Window_Background 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

4. Adding to the container part of window

Page 611: Java_E_Book_Satish_Singhal

Graphical User Interface (Singhal) Page 9 of 41

MyButton, as well as provides the "intelligence" to these buttons.

Nested Class Summary for class ButtonsInMyWindow

private static class

ButtonsInMyWindow.ButtonHandler 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 class

ButtonsInMyWindow.CloseWindow 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

Page 612: Java_E_Book_Satish_Singhal

Graphical User Interface (Singhal) Page 10 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

Page 613: Java_E_Book_Satish_Singhal

Graphical User Interface (Singhal) Page 11 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()

Page 614: Java_E_Book_Satish_Singhal

Graphical User Interface (Singhal) Page 12 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.

Page 615: Java_E_Book_Satish_Singhal

Graphical User Interface (Singhal) Page 13 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.

Page 616: Java_E_Book_Satish_Singhal

Graphical User Interface (Singhal) Page 14 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

Page 617: Java_E_Book_Satish_Singhal

Graphical User Interface (Singhal) Page 15 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

Page 618: Java_E_Book_Satish_Singhal

Graphical User Interface (Singhal) Page 16 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.

Page 619: Java_E_Book_Satish_Singhal

Graphical User Interface (Singhal) Page 17 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.

Page 620: Java_E_Book_Satish_Singhal

Graphical User Interface (Singhal) Page 18 of 41

ScrollPaneLayout

A layout manager specific to scrolling panes.

ViewportLayout

A layout manager specific to view ports within scrolling panes.

SpringLayout

Uses the concept of springs and struts to place widgets and containers. This layout is best used when one is using 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 private

javax.swing.JButton[] Buttons Array of JButtons

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 static java.lang.String

Title The title chosen for the MyWindow object. Win.

private static int width 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.

MyWindow (Listing 15.1)

Properties of MyWindow object Win

Page 621: Java_E_Book_Satish_Singhal

Graphical User Interface (Singhal) Page 19 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 void

setSwingLookAndFeel() 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 {

Page 622: Java_E_Book_Satish_Singhal

Graphical User Interface (Singhal) Page 20 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.

Page 623: Java_E_Book_Satish_Singhal

Graphical User Interface (Singhal) Page 21 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

Page 624: Java_E_Book_Satish_Singhal

Graphical User Interface (Singhal) Page 22 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),

Page 625: Java_E_Book_Satish_Singhal

Graphical User Interface (Singhal) Page 23 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.

Page 626: Java_E_Book_Satish_Singhal

Graphical User Interface (Singhal) Page 24 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

Page 627: Java_E_Book_Satish_Singhal

Graphical User Interface (Singhal) Page 25 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());

Page 628: Java_E_Book_Satish_Singhal

Graphical User Interface (Singhal) Page 26 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)

Page 629: Java_E_Book_Satish_Singhal

Graphical User Interface (Singhal) Page 27 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.

Page 630: Java_E_Book_Satish_Singhal

Graphical User Interface (Singhal) Page 28 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

Page 631: Java_E_Book_Satish_Singhal

Graphical User Interface (Singhal) Page 29 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

Page 632: Java_E_Book_Satish_Singhal

Graphical User Interface (Singhal) Page 30 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);

Page 633: Java_E_Book_Satish_Singhal

Graphical User Interface (Singhal) Page 31 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.

Page 634: Java_E_Book_Satish_Singhal

Graphical User Interface (Singhal) Page 32 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.

Page 635: Java_E_Book_Satish_Singhal

Graphical User Interface (Singhal) Page 33 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));

Page 636: Java_E_Book_Satish_Singhal

Graphical User Interface (Singhal) Page 34 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. Cont.setLayout (new GridLayout (0,1)); 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.

When used in Listing 15.5 to replace line #67, it will create five rows and one column.

Page 637: Java_E_Book_Satish_Singhal

Graphical User Interface (Singhal) Page 35 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 their derived classes

How many? Purpose Intelligence needed

JTextField Two JLabel Three JButton Six JPanel Five JFrame One

Table 15.4

Page 638: Java_E_Book_Satish_Singhal

Graphical User Interface (Singhal) Page 36 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.

Page 639: Java_E_Book_Satish_Singhal

Graphical User Interface (Singhal) Page 37 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 FIG. xxx 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 { CopyAction () { 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);

Action interface extends ActionListener and EventListener

More than one constructor may be provided as needed.

Page 640: Java_E_Book_Satish_Singhal

Graphical User Interface (Singhal) Page 38 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.

Page 641: Java_E_Book_Satish_Singhal

Graphical User Interface (Singhal) Page 39 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.

Page 642: Java_E_Book_Satish_Singhal

Graphical User Interface (Singhal) Page 40 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.

Page 643: Java_E_Book_Satish_Singhal

Graphical User Interface (Singhal) Page 41 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.

Page 644: Java_E_Book_Satish_Singhal

Java Applets•Growth of java and Internet technologies exploded simultaneouslysimultaneously.

•In early days of Internet Java Applets made web i ipages alive and animated.

•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.

Page 645: Java_E_Book_Satish_Singhal

Writing Applets

•Basically involves extending the class Applet (JApplet in swing), from java.applet package.

•Applets are run by Web browser, which means that pp y ,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 have some special features which makes pp ptheir look, feel , and coding different from stand alone java programs we have written so far.

Page 646: Java_E_Book_Satish_Singhal

Testing Applets• Testing Applets is as important as writing them.

• Three levels of testing.

1. Simple - Testing with appletviewer tool in Sun Java1. Simple Testing with appletviewer tool in Sun Java development environment.

2 Intermediate Testing with the dominant Internet2. Intermediate – Testing with the dominant Internet browser(unfortunately Internet Explorer these days).y )

3. Advanced – Testing with all browsers known to mankind so farmankind so far.

Page 647: Java_E_Book_Satish_Singhal

Testing Applets in CS 3• We will confine to testing our applets with simple

and intermediate levels onlyand intermediate levels only.

• Professional work will need advanced testing.

• Main browsers in vogue today:

1 Internet Explorer 4 5 61. Internet Explorer 4, 5, 6

2. Netscape 4, 5, 6

3. Opera 4, 5, 6

4 Mozilla 1 04. Mozilla 1.0

Page 648: Java_E_Book_Satish_Singhal

Java Applet Class

Applet Class API Documentationpp

Page 649: Java_E_Book_Satish_Singhal

Numerous MethodsBare 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)

Page 650: Java_E_Book_Satish_Singhal

Hello World Java Appletimport java.awt.*;

i t j l t *import java.applet.*;

public class HelloWorldApplet extends Applet{

public void init( ){

setBackground(new Color(250,0,100)); }

public void paint(Graphics g) {

g.setFont(new Font("Ariel", Font.BOLD, 48));g ( ( , , ));

g.setColor(Color.blue);

g drawString("Hello to World From El Camino!" 0 150);g.drawString( Hello to World From El Camino! ,0,150);}}

Page 651: Java_E_Book_Satish_Singhal

How Does it look?

Page 652: Java_E_Book_Satish_Singhal

Dissecting the Codeimports

Needs java.awt and java.applet packages

Page 653: Java_E_Book_Satish_Singhal

Dissecting the Code -2Extends the class Applet

public class HelloWorldApplet extends Applet

Page 654: Java_E_Book_Satish_Singhal

Dissecting the Code - 3init( ) method

•Sets the background color in this case

public void init( )

{

Takes Color object as argument

{

setBackground(new Color(250,0,100));setBackground(new Color(250,0,100));

}C ll tB k d th dCalls setBackground method

Page 655: Java_E_Book_Satish_Singhal

Dissecting the Code - 4paint( ) method Takes Font object as

argument

•Paints the applet on the frame

public void paint(Graphics g){

g.setFont(new Font("Ariel", Font.BOLD, 48));g.setFont(new 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

Page 656: Java_E_Book_Satish_Singhal

Code (HTML File) executed byCode (HTML File) executed by the Browser

<html>

<body>Needs the Applet tag

body

<applet code=HelloWorldApplet.class width=750 height=300>

</applet></applet>

</body>Needs the java class Applet</html> Needs the java class

information. In this case the html file and class file in the

Applet Height and

widthsame folder.

Page 657: Java_E_Book_Satish_Singhal

Browser Interprets the class file and runs on client machine!and runs on client machine!

Security Issues?

1. Low level Security Issues

2 Hi h L l S it i2. High Level Security issues

Page 658: Java_E_Book_Satish_Singhal

Low level Security Issues

•Browser java virtual machine is notBrowser java virtual machine is not allowed to run any code that may have an assembly language instructionassembly language instruction.•This is because by running the assembly code the server can get hold of randomcode the server can get hold of random chunks of client’s memory – a great security hazardsecurity hazard.

Page 659: Java_E_Book_Satish_Singhal

High level Security Issues•Before Applet is run, the browser loads a sec rit managersecurity manager.•If Applet code tries to read a file or write to

fil li hi h ia file on client machine, the security 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.

Page 660: Java_E_Book_Satish_Singhal

No main( ) method in the Applets•One can design java virtual machine to r n an method firstto run any method first.•In this case the method init ( ) is

ll d ficalled first!

Page 661: Java_E_Book_Satish_Singhal

Lifetime of a java Applet•init( ) method is called first!

•Then browser calls an applet method called start( )•Then browser calls an applet method called start( ).

•If user moves to another web page then the method stop( ) is called to free non-memory resources that applet may have beencalled to free non memory resources that applet may have been using.

•For example if Applet was doing an animation, and user moves p pp gto 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.

d t ( ) th d i ll d t d t th l t h ll•destroy( ) method is called to destroy the applet, when all browser windows are closed!

Page 662: Java_E_Book_Satish_Singhal

Why our code did not have thoseWhy our code did not have those methods?

•start, stop and destroy methods are called internally by the virtual machine so we do not need to include themvirtual machine, so we do not need to include them.

•But to show their functioning we can include them intentionally and show as to how they workintentionally and show as to how they work.

•This is done in the next example.

Page 663: Java_E_Book_Satish_Singhal

BasicEventApplet• In addition to init( ) and paint( ), the following methods are

added intentionally:

1. A constructor

2. start( )2. start( )

3. stop( )

4 destroy( )4. destroy( )

Page 664: Java_E_Book_Satish_Singhal

Sequence of Events• As soon as Applet is started, the constructor is called first.

• Then applet is initialized by calling the init( ) method• Then applet is initialized by calling the init( ) method.

• Then applet is started by calling the start( ) method.

Th i ( ) h d i h l• Then paint( ) method paints the applet.

• If other widows cover and uncover the applet, the paint method is called every time to paint the applet backmethod is called every time to paint the applet back.

Page 665: Java_E_Book_Satish_Singhal

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.

Page 666: Java_E_Book_Satish_Singhal

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

Page 667: Java_E_Book_Satish_Singhal

HTML code to include parametersparameters

• <APPLET

CODE "P t A l t l " WIDTH 450• CODE="ParameterApplet.class" WIDTH=450 HEIGHT=300>

• <PARAM NAME="name" VALUE="Satish Prakash• <PARAM NAME= name VALUE= Satish Prakash Singhal"> NAME

attribute

• <PARAM NAME="yourHeight" VALUE="5.5">

</APPLET> U

attribute

• </APPLET> Use param tag

VALUE attribute

Page 668: Java_E_Book_Satish_Singhal

How Applet gets the parameters?Uses its getParameter( ) method.

String getParameter(String name)R t th t i l f th d t i thReturns the string value of the named parameter in the

HTML tag.

For example the callFor example the call

getParameter("yourHeight")

Will h H i h l i l d d i h HTMLWill return the yourHeight value included in the HTML code.

Page 669: Java_E_Book_Satish_Singhal

Topic 19 Connecting to Databases (Singhal) Page 1 of 41

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.

Page 670: Java_E_Book_Satish_Singhal

Topic 19 Connecting to Databases (Singhal) Page 2 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. 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

In above flat file database, each row becomes one record, and each column in 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.

Column

Row or record

Page 671: Java_E_Book_Satish_Singhal

Topic 19 Connecting to Databases (Singhal) Page 3 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.

Page 672: Java_E_Book_Satish_Singhal

Topic 19 Connecting to Databases (Singhal) Page 4 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

Number

Number (precision)

Data type for integers, where precision gives the number of digits in the integer. The number may be positive, negative or zero.

Number (5) will allow storage of numbers from -99999 to +99999

Number (precision, scale)

Data types where fixed-point arithmetic is needed. Precision gives total number of digits (including the fractional part). Scale can be positive or negative. Positive value of scale defines maximum digits on the right of decimal point. If scale is negative then it defines the maximum number of digits on the left of decimal point.

NUMBER (9,3) May be any of these: 999999.999 123.4 123 0.001

Number

Data type for floating point type numbers with out any limitation of precision and scale. This matches Java double data type.

Number Could be in format0.12345E2 1.2345E1 12.345 12345E-3

Page 673: Java_E_Book_Satish_Singhal

Topic 19 Connecting to Databases (Singhal) Page 5 of 41

FLOAT No sub types

Same as Number. Used when Oracle need to be compliant with ANSI FLOAT data type

FLOAT 12.345

DECIMAL No sub type

Used as a fixed point number when compatibility with other data types such as DB2 is required

String5

Char

One character fixed length data type

‘x’ – note that in Oracle single quote is used for both character and string

Char ( n) String length is limited to n characters. n varies from 1 to 255

‘Hello World’

VARCHAR2 (n)

Variable length string. The value of n varies from 1 to 32K-1

As above.

Date No subtype

The standard date format (including time) is DD-MON-YY HH:MI:SS A.M . (or P.M.) with the 12-hour clock. MON is the first three alphabets in the month

01-SEP-00 12:01:00 A.M.

NULL No subtype

NULL data type in SQL is stored when a value is not assigned to a field in a record. 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.

Page 674: Java_E_Book_Satish_Singhal

Topic 19 Connecting to Databases (Singhal) Page 6 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

Page 675: Java_E_Book_Satish_Singhal

Topic 19 Connecting to Databases (Singhal) Page 7 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.

Page 676: Java_E_Book_Satish_Singhal

Topic 19 Connecting to Databases (Singhal) Page 8 of 41

CREATE TABLE US_ZIP_CODES ( ZIP VARCHAR2 (5) NOT NULL, STATE VARCHAR2 (2) NOT NULL, CONSTRAINT PK_US_ZIP_CODES PRIMARY KEY (ZIP) ); Table 19.3 gives the decisions made about the personal address table and its columns. Table Property

Property Value(s)

Table name

PERSONAL_ADDRESS_BOOK_US

Field

Field Name Data type Remarks ID_NUM VARCHAR2 (4) Primary key. Constraint name:

PK_ ADNAME VARCHAR2 (30) 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, NAME VARCHAR2(30) NOT NULL, CITY VARCHAR2(20) NOT NULL, ZIP_CODE VARCHAR2(5) NOT NULL, 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

Syntax for setting the ZIP column as primary key. The constraint name is optional but desirable.

Oracle some times cannot handle long names for constraints. Be sure to look up documentations.

Page 677: Java_E_Book_Satish_Singhal

Topic 19 Connecting to Databases (Singhal) Page 9 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:

Page 678: Java_E_Book_Satish_Singhal

Topic 19 Connecting to Databases (Singhal) Page 10 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’);

Page 679: Java_E_Book_Satish_Singhal

Topic 19 Connecting to Databases (Singhal) Page 11 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.

Page 680: Java_E_Book_Satish_Singhal

Topic 19 Connecting to Databases (Singhal) Page 12 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 SET ColumnName = expression [, …] [,ColumnNameN = expressionN] [WHERE condition]; 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

Name(s) of column whose value is to be updated.

The new value for the column. This can be a literal, another column name, an expression involving literals, strings, and column names.

Optional WHERE statement would make assignments only when condition is true for a row!

Page 681: Java_E_Book_Satish_Singhal

Topic 19 Connecting to Databases (Singhal) Page 13 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 [WHERE condition]; 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

The row or rows for which the condition is true are deleted. No deletions are done, if condition is not true.

Page 682: Java_E_Book_Satish_Singhal

Topic 19 Connecting to Databases (Singhal) Page 14 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.

Page 683: Java_E_Book_Satish_Singhal

Topic 19 Connecting to Databases (Singhal) Page 15 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.

Page 684: Java_E_Book_Satish_Singhal

Topic 19 Connecting to Databases (Singhal) Page 16 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.

Page 685: Java_E_Book_Satish_Singhal

Topic 19 Connecting to Databases (Singhal) Page 17 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.

Page 686: Java_E_Book_Satish_Singhal

Topic 19 Connecting to Databases (Singhal) Page 18 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: Class.forName (“sun.jdbc.odbc. JdbcOdbcDriver”); 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.

Argument to forName method must be a fully qualified class name.

Page 687: Java_E_Book_Satish_Singhal

Topic 19 Connecting to Databases (Singhal) Page 19 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.

10 On Windows XP, NT and 2000, the ODBC source icon can be reached as follows: Click on start Control Panel Administrative Tools ODBC Source.

Page 688: Java_E_Book_Satish_Singhal

Topic 19 Connecting to Databases (Singhal) Page 20 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.

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.

Click on create, after filling out the Data Source Name and brief description.

Page 689: Java_E_Book_Satish_Singhal

Topic 19 Connecting to Databases (Singhal) Page 21 of 41

7. Clicking on the create button will show the new dialog box shown by Figure 19.11C.

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

1. Fill the database file name.

2. Choose the directory where database will locate.

3. Click on OK

Page 690: Java_E_Book_Satish_Singhal

Topic 19 Connecting to Databases (Singhal) Page 22 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.

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

Click on select button after filling out the Data source name and description.

Fill out the data source name and description.

Page 691: Java_E_Book_Satish_Singhal

Topic 19 Connecting to Databases (Singhal) Page 23 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 Database identifier: cloudscape:db Then the database URL in this case is: “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.

Portion before colon gives the IP address and after the colon gives the port number.

Page 692: Java_E_Book_Satish_Singhal

Topic 19 Connecting to Databases (Singhal) Page 24 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:

Page 693: Java_E_Book_Satish_Singhal

Topic 19 Connecting to Databases (Singhal) Page 25 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.

Page 694: Java_E_Book_Satish_Singhal

Topic 19 Connecting to Databases (Singhal) Page 26 of 41

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

Methods needed by the client.

Page 695: Java_E_Book_Satish_Singhal

Topic 19 Connecting to Databases (Singhal) Page 27 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 java.sql.DatabaseMetaData

getDatabaseMetaData(java.sql.Connection Con)

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.

Page 696: Java_E_Book_Satish_Singhal

Topic 19 Connecting to Databases (Singhal) Page 28 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();

Page 697: Java_E_Book_Satish_Singhal

Topic 19 Connecting to Databases (Singhal) Page 29 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 }

Page 698: Java_E_Book_Satish_Singhal

Topic 19 Connecting to Databases (Singhal) Page 30 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

Page 699: Java_E_Book_Satish_Singhal

Topic 19 Connecting to Databases (Singhal) Page 31 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 }

Page 700: Java_E_Book_Satish_Singhal

Topic 19 Connecting to Databases (Singhal) Page 32 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.

Page 701: Java_E_Book_Satish_Singhal

Topic 19 Connecting to Databases (Singhal) Page 33 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?

Page 702: Java_E_Book_Satish_Singhal

Topic 19 Connecting to Databases (Singhal) Page 34 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:

Page 703: Java_E_Book_Satish_Singhal

Topic 19 Connecting to Databases (Singhal) Page 35 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.

Page 704: Java_E_Book_Satish_Singhal

Topic 19 Connecting to Databases (Singhal) Page 36 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

Page 705: Java_E_Book_Satish_Singhal

Topic 19 Connecting to Databases (Singhal) Page 37 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.

Page 706: Java_E_Book_Satish_Singhal

Topic 19 Connecting to Databases (Singhal) Page 38 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.

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.

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

Page 707: Java_E_Book_Satish_Singhal

Topic 19 Connecting to Databases (Singhal) Page 39 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.

Page 708: Java_E_Book_Satish_Singhal

Topic 19 Connecting to Databases (Singhal) Page 40 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

AddressBookForm • java.sql.Connection • ControlPanel • javax.swing.JTextArea • ScrollingPanel • javax.swing.JScrollPane

• java.lang.String • MyWindow

ControlPanel java.lang.Object

java.awt.Component

java.awt.Container

javax.swing.JComponent

javax.swing.JPanel ControlPanel

Five instances of class javax.swing.JButton. One for each function shown in top portion of Figure FYZ1.

ScrollingPanel java.lang.Object

java.awt.Component

java.awt.Container

javax.swing.JComponent

javax.swing.JPanel ScrollingPanel

• Five instances of javax.swing.JTextField, one for each text entry field shown in Figure FYZ1.

• An array of JLabel with five members, one for each text entry field.

• Two JPanel objects, one

Page 709: Java_E_Book_Satish_Singhal

Topic 19 Connecting to Databases (Singhal) Page 41 of 41

for labels and other for text fields.

AddRecord java.lang.Object

AddRecord implements ActionListener

• java.sql.Connection • ScrollingPanel • javax.swing.JTextArea • java.sql.ResultSet • java.sql.Statement

FindRecord java.lang.Object

FindRecord implements ActionListener

• java.sql.Connection • ScrollingPanel • javax.swing.JTextArea • java.lang.String

UpdateRecord java.lang.Object

UpdateRecord implements ActionListener

• java.sql.Connection • ScrollingPanel • javax.swing.JTextArea

ClearFields java.lang.Object

ClearFields implements ActionListener

ScrollingPanel

Help java.lang.Object

Help implements ActionListener

javax.swing.JTextArea

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.

Page 710: Java_E_Book_Satish_Singhal

Topic 20 Multithreading (Singhal) Page 1 of 52

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.

Page 711: Java_E_Book_Satish_Singhal

Topic 20 Multithreading (Singhal) Page 2 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.

Page 712: Java_E_Book_Satish_Singhal

Topic 20 Multithreading (Singhal) Page 3 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.

Page 713: Java_E_Book_Satish_Singhal

Topic 20 Multithreading (Singhal) Page 4 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 type

Data types or Methods signatures

public data members

static int MAX_PRIORITY , MIN_PRIORITY , NORM_PRIORITY;

Constructors

Thread() Thread(Runnable target) Thread(Runnable target, String name) Thread(String name) 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)

Static methods

int activeCount() Thread currentThread() void dumpStack() int enumerate(Thread[ ] tarray) boolean holdsLock(Object obj) boolean interrupted() void sleep(long millis) void sleep(long millis, int nanos) void yield()

Page 714: Java_E_Book_Satish_Singhal

Topic 20 Multithreading (Singhal) Page 5 of 52

Instance methods

void checkAccess() int countStackFrames() void destroy() ClassLoader getContextClassLoader() String getName() int getPriority() ThreadGroup getThreadGroup() void interrupt() boolean isAlive() boolean isDaemon() 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.

Page 715: Java_E_Book_Satish_Singhal

Topic 20 Multithreading (Singhal) Page 6 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

Page 716: Java_E_Book_Satish_Singhal

Topic 20 Multithreading (Singhal) Page 7 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(){ Thread Mom1 = new MomThread(); Runnable Dad = new DadThread(); Thread Dad1 = new Thread(Dad); System.out.println( "Starting the Mom thread."); Mom1.start(); System.out.println( "Starting the Dad thread."); Dad1.start(); }

Always same as below *********Starting the main thread Starting the Mom thread. Starting the Dad thread. **********Ending the main thread Message 1 From: Mom Message 2 From: Mom Message 3 From: Mom Message 4 From: Mom Message 1 From: Dad Message 2 From: Dad Message 3 From: Dad Message 4 From: Dad

Some variation of pattern below *********Starting the main thread!!!! Starting the Mom thread. Starting the Dad thread. **********Ending the main thread!!!! Message 1 From: Mom Message 1 From: Dad Message 2 From: Mom Message 2 From: Dad Message 3 From: Mom Message 3 From: Dad Message 4 From: Mom Message 4 From: Dad

private static void test2() { Thread Mom1 = new MomThread(); Mom1.setPriority(10); System.out.println("The priority of “ + ” Mom1 = " + Mom1.getPriority());

Always same. No variation *********Starting the main thread!!!! The priority of Mom1 = 10 The priority of Dad1 = 2 Starting the Dad thread.

Run #1 *********Starting the main thread!!!! The priority of Mom1 = 10 The priority of Dad1 = 2 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

Page 717: Java_E_Book_Satish_Singhal

Topic 20 Multithreading (Singhal) Page 8 of 52

Runnable Dad = new DadThread(); Thread Dad1 = new Thread(Dad); Dad1.setPriority(2); System.out.println("The priority of” + “ Dad1 = " + Dad1.getPriority()); System.out.println ( "Starting the Dad thread."); Dad1.start(); System.out.println( "Starting the Mom thread."); Mom1.start(); }

Starting the Mom thread. Message 1 From: Mom Message 2 From: Mom Message 3 From: Mom Message 4 From: Mom **********Ending the main thread!!!! Message 1 From: Dad Message 2 From: Dad Message 3 From: Dad Message 4 From: Dad

Starting the Mom thread. Message 1 From: Dad Message 2 From: Dad Message 1 From: Mom **********Ending the main thread!!!! Message 2 From: Mom Message 3 From: Dad Message 3 From: Mom 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() { Thread Mom1 = new MomThread(); Mom1.setPriority(10); System.out.println("The priority of Mom1 = " + Mom1.getPriority()); Runnable Dad = new DadThread(); Thread Dad1 = new Thread(Dad); Dad1.setPriority(2); System.out.println("The priority of Dad1 = " + Dad1.getPriority()); System.out.println( "Starting the Mom thread."); Mom1.start(); System.out.println( "Starting the Dad thread."); Dad1.start(); }

Result is always same. There is no variation *********Starting the main thread!!!! The priority of Mom1 = 10 The priority of Dad1 = 2 Starting the Mom thread. Message 1 From: Mom Message 2 From: Mom Message 3 From: Mom Message 4 From: Mom Starting the Dad thread. **********Ending the main thread!!!! Message 1 From: Dad Message 2 From: Dad Message 3 From: Dad Message 4 From: Dad

Slight variation in the type of output below. *********Starting the main thread!!!! The priority of Mom1 = 10 The priority of Dad1 = 2 Starting the Mom thread. Starting the Dad thread. Message 1 From: Mom Message 2 From: Mom Message 3 From: Mom **********Ending the main thread!!!! Message 1 From: Dad Message 4 From: Mom Message 2 From: Dad Message 3 From: Dad Message 4 From: Dad

private static void test4() { Thread Mom1 = new MomThread(); System.out.println( "Running (not starting) the Mom “ + “ thread."); Mom1.run(); System.out.println("The priority of Mom1 = " + Mom1.getPriority()); Runnable Dad = new DadThread(); Thread Dad1 = new Thread(Dad); System.out.println (

*********Starting the main thread!!!! Running (not starting) the Mom thread. Message 1 From: Mom Message 2 From: Mom Message 3 From: Mom Message 4 From: Mom The priority of Mom1 = 5 Running (not starting) the Dad thread. Message 1 From: Dad

*********Starting the main thread!!!! Running (not starting) the Mom thread. Message 1 From: Mom Message 2 From: Mom Message 3 From: Mom Message 4 From: Mom The priority of Mom1 = 5 Running (not starting) the Dad thread. Message 1 From: Dad

Page 718: Java_E_Book_Satish_Singhal

Topic 20 Multithreading (Singhal) Page 9 of 52

"Running (not starting) the Dad + “ thread."); Dad1.run(); System.out.println("The priority of Dad1 = " + Dad1.getPriority()); }

Message 2 From: Dad Message 3 From: Dad Message 4 From: Dad The priority of Dad1 = 5 **********Ending the main thread!!!!

Message 2 From: Dad Message 3 From: Dad Message 4 From: Dad The priority of Dad1 = 5 **********Ending the main 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

Page 719: Java_E_Book_Satish_Singhal

Topic 20 Multithreading (Singhal) Page 10 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

Page 720: Java_E_Book_Satish_Singhal

Topic 20 Multithreading (Singhal) Page 11 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.

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.

Or native threads

Page 721: Java_E_Book_Satish_Singhal

Topic 20 Multithreading (Singhal) Page 12 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.

Figure 20.4 A thread can have following states:

1. New thread 2. Runnable or yielded 3. Not Runnable (non-runnable) 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.

Sleep, wait, and blocked for I/O would make a thread non-runnable.

Thread can become runnable again by elapse of sleep time, by being notified that wait is over, or when I/O is over.

Page 722: Java_E_Book_Satish_Singhal

Topic 20 Multithreading (Singhal) Page 13 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(); }

Page 723: Java_E_Book_Satish_Singhal

Topic 20 Multithreading (Singhal) Page 14 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); 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); } } 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.

Gets the current thread.

Makes the current thread sleep for millis number of milliseconds

Also added to the run method of DadThread class.

Page 724: Java_E_Book_Satish_Singhal

Topic 20 Multithreading (Singhal) Page 15 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

Page 725: Java_E_Book_Satish_Singhal

Topic 20 Multithreading (Singhal) Page 16 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

Page 726: Java_E_Book_Satish_Singhal

Topic 20 Multithreading (Singhal) Page 17 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. 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; }

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.

Page 727: Java_E_Book_Satish_Singhal

Topic 20 Multithreading (Singhal) Page 18 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;

Page 728: Java_E_Book_Satish_Singhal

Topic 20 Multithreading (Singhal) Page 19 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

Page 729: Java_E_Book_Satish_Singhal

Topic 20 Multithreading (Singhal) Page 20 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"); } }

Page 730: Java_E_Book_Satish_Singhal

Topic 20 Multithreading (Singhal) Page 21 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.

Page 731: Java_E_Book_Satish_Singhal

Topic 20 Multithreading (Singhal) Page 22 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:

Page 732: Java_E_Book_Satish_Singhal

Topic 20 Multithreading (Singhal) Page 23 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: synchronized (obj) { //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) { if(balance >= amount) { pause(); balance -= amount; return true; } } return false; } //Listing 20.6A

Critical code that must complete by one thread at a time is placed in the synchronized block.

Object to be locked is passed as an argument following keyword synchronized

Page 733: Java_E_Book_Satish_Singhal

Topic 20 Multithreading (Singhal) Page 24 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

Page 734: Java_E_Book_Satish_Singhal

Topic 20 Multithreading (Singhal) Page 25 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() { synchronized(getClass()) { count--; } } 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.

When synchronizing operation on a static member, the argument to synchronization block is the Class object for that class. Method getClass returns a Class object.

Page 735: Java_E_Book_Satish_Singhal

Topic 20 Multithreading (Singhal) Page 26 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:

Page 736: Java_E_Book_Satish_Singhal

Topic 20 Multithreading (Singhal) Page 27 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”.

Page 737: Java_E_Book_Satish_Singhal

Topic 20 Multithreading (Singhal) Page 28 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( );

Page 738: Java_E_Book_Satish_Singhal

Topic 20 Multithreading (Singhal) Page 29 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()) { while (! the_condition_I_am_waiting_for) this.getClass().wait(); count--; } } 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).

The object being passed to the synchronized block must be the one to invoke wait method!

Figure 0.2 Figure 0.1

Page 739: Java_E_Book_Satish_Singhal

Topic 20 Multithreading (Singhal) Page 30 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.

Page 740: Java_E_Book_Satish_Singhal

Topic 20 Multithreading (Singhal) Page 31 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()+

Page 741: Java_E_Book_Satish_Singhal

Topic 20 Multithreading (Singhal) Page 32 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.

Page 742: Java_E_Book_Satish_Singhal

Topic 20 Multithreading (Singhal) Page 33 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.

Fig. 20.8A

Fig. 20.8B

Abstract class Extends Thread

Extends BankAccountOperations

Page 743: Java_E_Book_Satish_Singhal

Topic 20 Multithreading (Singhal) Page 34 of 52

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

BankAccount account The BankAccount object on which certain thread operation is performed.

protected double

amount Amount of money to be either deposited/transferred or debited. DELAY Delay in milliseconds to put the thread to sleep. protected

static int 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 }

Extends BankAccountOperations

Page 744: Java_E_Book_Satish_Singhal

Topic 20 Multithreading (Singhal) Page 35 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

Page 745: Java_E_Book_Satish_Singhal

Topic 20 Multithreading (Singhal) Page 36 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.

Page 746: Java_E_Book_Satish_Singhal

Topic 20 Multithreading (Singhal) Page 37 of 52

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()+

Data Type: BankAccount

Page 747: Java_E_Book_Satish_Singhal

Topic 20 Multithreading (Singhal) Page 38 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;

Page 748: Java_E_Book_Satish_Singhal

Topic 20 Multithreading (Singhal) Page 39 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.

Page 749: Java_E_Book_Satish_Singhal

Topic 20 Multithreading (Singhal) Page 40 of 52

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();

Data Type: BankAccount

Page 750: Java_E_Book_Satish_Singhal

Topic 20 Multithreading (Singhal) Page 41 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.

Page 751: Java_E_Book_Satish_Singhal

Topic 20 Multithreading (Singhal) Page 42 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

Page 752: Java_E_Book_Satish_Singhal

Topic 20 Multithreading (Singhal) Page 43 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

Page 753: Java_E_Book_Satish_Singhal

Topic 20 Multithreading (Singhal) Page 44 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

Page 754: Java_E_Book_Satish_Singhal

Topic 20 Multithreading (Singhal) Page 45 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 ( );

Page 755: Java_E_Book_Satish_Singhal

Topic 20 Multithreading (Singhal) Page 46 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. public void transfer (BankAccount From_Account, double amount, 1 BankAccount To_Account) throws InterruptedException//because of withdraw method 2 { 3 BankAccount First_Lock = null; 4 BankAccount Second_Lock =null; 5 6 if(amount<=0)//negative or zero amount is not transferred 7 { 8 notifyAll(); 9 return; 10 } 11 else if(From_Account.getAccountNumber() == To_Account.getAccountNumber()) 12 { 13 // Cannot transfer to the same account 14 notifyAll(); 15 return; 16 } 17 else if(From_Account.getAccountNumber() < To_Account.getAccountNumber()) 18 { 19 First_Lock = From_Account; 20 Second_Lock = To_Account; 21 } 22 23

Page 756: Java_E_Book_Satish_Singhal

Topic 20 Multithreading (Singhal) Page 47 of 52

else 24 { 25 First_Lock = To_Account; 26 Second_Lock = From_Account; 27 } 28 29 synchronized (First_Lock) 30 { 31 synchronized (Second_Lock) 32 { 33 if (From_Account.hasSufficientBalance(amount)) 34 { 35 From_Account.withdraw(amount); 36 To_Account.deposit(amount); 37 notifyAll(); 38 } 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.

Page 757: Java_E_Book_Satish_Singhal

Topic 20 Multithreading (Singhal) Page 48 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

Page 758: Java_E_Book_Satish_Singhal

Topic 20 Multithreading (Singhal) Page 49 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 }

Page 759: Java_E_Book_Satish_Singhal

Topic 20 Multithreading (Singhal) Page 50 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)

Page 760: Java_E_Book_Satish_Singhal

Topic 20 Multithreading (Singhal) Page 51 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() { //... } }

Page 761: Java_E_Book_Satish_Singhal

Topic 20 Multithreading (Singhal) Page 52 of 52

//Listing 20.10B ////////////////////////////////////////////////////////////////////////////////////////////////////////////

Page 762: Java_E_Book_Satish_Singhal

Chapter 21 Networking (Singhal) Page 1 of 36

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.

Page 763: Java_E_Book_Satish_Singhal

Chapter 21 Networking (Singhal) Page 2 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

Page 764: Java_E_Book_Satish_Singhal

Chapter 21 Networking (Singhal) Page 3 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.

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.

Internet applications combine these 3 layers in one and call them application!

Page 765: Java_E_Book_Satish_Singhal

Chapter 21 Networking (Singhal) Page 4 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 Number

Layer Name

Service performed Example(s) of service

7 Application Gets the data from the source or sends data to the destination.

Web page request, e-mail, files transfer requests.

6 Presentation Prepares data in the format that it can be transported on the network and can be understood by the receiver.

Conversion from Unicode to ASCII or ASCII to binary

5 Session Sets up an active connection between source and destination, maintains it, and when session is over tears it.

Shopping on an e-commerce site

4 Transport Manages the flow of data between the source and destination and control the quality of data communication. Handles the addressing of the messages.

If part of a message is lost, it can be resent.

Page 766: Java_E_Book_Satish_Singhal

Chapter 21 Networking (Singhal) Page 5 of 36

3 Network Handles the route from source to destination, manages the traffic problems including congestion.

Converting web address typed by the user to the domain address in numbers.

2 Datalink Manages the flow of data to next physical node in the route by determining its address and also prints this address on each portion of the message being sent.

Stamping the address of the next physical machine in the route.

1 Physical Carries the bits between source and destination. The signal can be analogue (like old phone line) or digital (Fiber optic link).

Flow of current in the copper communication 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 Number

Layer Name

Protocols and Examples

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

Page 767: Java_E_Book_Satish_Singhal

Chapter 21 Networking (Singhal) Page 6 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.

Page 768: Java_E_Book_Satish_Singhal

Chapter 21 Networking (Singhal) Page 7 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.

Page 769: Java_E_Book_Satish_Singhal

Chapter 21 Networking (Singhal) Page 8 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.

Page 770: Java_E_Book_Satish_Singhal

Chapter 21 Networking (Singhal) Page 9 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.

Page 771: Java_E_Book_Satish_Singhal

Chapter 21 Networking (Singhal) Page 10 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.

Page 772: Java_E_Book_Satish_Singhal

Chapter 21 Networking (Singhal) Page 11 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.

Page 773: Java_E_Book_Satish_Singhal

Chapter 21 Networking (Singhal) Page 12 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

Number Generic name for the server software or its use

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.

Page 774: Java_E_Book_Satish_Singhal

Chapter 21 Networking (Singhal) Page 13 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 upper case)

Description

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.

Page 775: Java_E_Book_Satish_Singhal

Chapter 21 Networking (Singhal) Page 14 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

Page 776: Java_E_Book_Satish_Singhal

Chapter 21 Networking (Singhal) Page 15 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 }

Page 777: Java_E_Book_Satish_Singhal

Chapter 21 Networking (Singhal) Page 16 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

Page 778: Java_E_Book_Satish_Singhal

Chapter 21 Networking (Singhal) Page 17 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.

Page 779: Java_E_Book_Satish_Singhal

Chapter 21 Networking (Singhal) Page 18 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.

Page 780: Java_E_Book_Satish_Singhal

Chapter 21 Networking (Singhal) Page 19 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:

Page 781: Java_E_Book_Satish_Singhal

Chapter 21 Networking (Singhal) Page 20 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

00003 HTTP/1.0 200 OK 00004 MIME-Version: 1.0 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

Protocol Status Code

Description

Header information about the server and the resource requested!

Page 782: Java_E_Book_Satish_Singhal

Chapter 21 Networking (Singhal) Page 21 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 Range

Meaning Selected Example(s)

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 request was successful

• 200 – The request succeeded and data sent.

• 206 – Server carried out partial GET request.

300 – 399 The client request was redirected and further action is necessary

• 301 – The requested resource has been moved to a new permanent URI9.

• 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.

Page 783: Java_E_Book_Satish_Singhal

Chapter 21 Networking (Singhal) Page 22 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.

Page 784: Java_E_Book_Satish_Singhal

Chapter 21 Networking (Singhal) Page 23 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.

Page 785: Java_E_Book_Satish_Singhal

Chapter 21 Networking (Singhal) Page 24 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

Page 786: Java_E_Book_Satish_Singhal

Chapter 21 Networking (Singhal) Page 25 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: 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.

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

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

‘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.

Page 787: Java_E_Book_Satish_Singhal

Chapter 21 Networking (Singhal) Page 26 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.

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

All member methods except contentType have void return type. Method contentType has String return type.

Page 788: Java_E_Book_Satish_Singhal

Chapter 21 Networking (Singhal) Page 27 of 36

processRequest method. Figure 21.13 shows the dependency diagram for the class HttpRequest.

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)

static java.lang.String CRLF A carriage return and line feed string used by method processRequest.

Depends upon

Page 789: Java_E_Book_Satish_Singhal

Chapter 21 Networking (Singhal) Page 28 of 36

(package private) java.net.Socket

Sock 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

java.lang.String contentType(java.lang.String File_Name) 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 static void

sendBytes(java.io.FileInputStream fis, 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);

Page 790: Java_E_Book_Satish_Singhal

Chapter 21 Networking (Singhal) Page 29 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

Page 791: Java_E_Book_Satish_Singhal

Chapter 21 Networking (Singhal) Page 30 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

Page 792: Java_E_Book_Satish_Singhal

Chapter 21 Networking (Singhal) Page 31 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).

Page 793: Java_E_Book_Satish_Singhal

Chapter 21 Networking (Singhal) Page 32 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.

Page 794: Java_E_Book_Satish_Singhal

Chapter 21 Networking (Singhal) Page 33 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

Page 795: Java_E_Book_Satish_Singhal

Chapter 21 Networking (Singhal) Page 34 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

Page 796: Java_E_Book_Satish_Singhal

Chapter 21 Networking (Singhal) Page 35 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

Page 797: Java_E_Book_Satish_Singhal

Chapter 21 Networking (Singhal) Page 36 of 36

• Automatic garbage collection • Dynamic architecture

Page 798: Java_E_Book_Satish_Singhal

Topic 23 Servlets and Java server Pages (Singhal) Page 1 of 42

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

Page 799: Java_E_Book_Satish_Singhal

Topic 23 Servlets and Java server Pages (Singhal) Page 2 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.

Page 800: Java_E_Book_Satish_Singhal

Topic 23 Servlets and Java server Pages (Singhal) Page 3 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

void doDelete(HttpServletRequest req, HttpServletResponse resp)

Called by the server (via the service method) to allow a servlet to handle a DELETE request.

protected void

doGet(HttpServletRequest req, HttpServletResponse resp) Called by the server (via the service method) to allow a servlet to handle a GET request.

protected void

doHead(HttpServletRequest req, HttpServletResponse resp) Receives an HTTP HEAD request from the protected service method and handles the request.

Page 801: Java_E_Book_Satish_Singhal

Topic 23 Servlets and Java server Pages (Singhal) Page 4 of 42

protected void

doOptions(HttpServletRequest req, HttpServletResponse resp)

Called by the server (via the service method) to allow a servlet to handle a OPTIONS request.

protected void

doPost(HttpServletRequest req, HttpServletResponse resp) Called by the server (via the service method) to allow a servlet to handle a POST request.

protected void

doPut(HttpServletRequest req, HttpServletResponse resp) Called by the server (via the service method) to allow a servlet to handle a PUT request.

protected void

doTrace(HttpServletRequest req, HttpServletResponse resp) Called by the server (via the service method) to allow a servlet to handle a TRACE request.

protected long

getLastModified(HttpServletRequest req)

Returns the time the HttpServletRequest object was last modified, in milliseconds since midnight January 1, 1970 GMT.

protected void

service(HttpServletRequest req, HttpServletResponse resp) 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

Page 802: Java_E_Book_Satish_Singhal

Topic 23 Servlets and Java server Pages (Singhal) Page 5 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

Page 803: Java_E_Book_Satish_Singhal

Topic 23 Servlets and Java server Pages (Singhal) Page 6 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.

Page 804: Java_E_Book_Satish_Singhal

Topic 23 Servlets and Java server Pages (Singhal) Page 7 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

Page 805: Java_E_Book_Satish_Singhal

Topic 23 Servlets and Java server Pages (Singhal) Page 8 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).

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.

No files mounted.

Page 806: Java_E_Book_Satish_Singhal

Topic 23 Servlets and Java server Pages (Singhal) Page 9 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.

Page 807: Java_E_Book_Satish_Singhal

Topic 23 Servlets and Java server Pages (Singhal) Page 10 of 42

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.

1. Node used to write JSP pages.

2. Node used to write servlets

Page 808: Java_E_Book_Satish_Singhal

Topic 23 Servlets and Java server Pages (Singhal) Page 11 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).

Page 809: Java_E_Book_Satish_Singhal

Topic 23 Servlets and Java server Pages (Singhal) Page 12 of 42

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

Fill fully qualified name of servlet class

Location of the servlet java and class files

Page 810: Java_E_Book_Satish_Singhal

Topic 23 Servlets and Java server Pages (Singhal) Page 13 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.

Page 811: Java_E_Book_Satish_Singhal

Topic 23 Servlets and Java server Pages (Singhal) Page 14 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(); /* TODO output your page here out.println("<html>"); out.println("<head>"); 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

1. This portion must be uncommented and modified to display the web page per specification.

Page 812: Java_E_Book_Satish_Singhal

Topic 23 Servlets and Java server Pages (Singhal) Page 15 of 42

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.

* @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

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:

Page 813: Java_E_Book_Satish_Singhal

Topic 23 Servlets and Java server Pages (Singhal) Page 16 of 42

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.

getOutputStream(), setCharacterEncoding(java.lang.String) FIG. 23.5

Page 814: Java_E_Book_Satish_Singhal

Topic 23 Servlets and Java server Pages (Singhal) Page 17 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.

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

Notice the URL

Page 815: Java_E_Book_Satish_Singhal

Topic 23 Servlets and Java server Pages (Singhal) Page 18 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

Page 816: Java_E_Book_Satish_Singhal

Topic 23 Servlets and Java server Pages (Singhal) Page 19 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> </body> </html> <!—Listing 23.2A The HTML page created by the browser from Listing 23.2A is shown in Figure 23.7A.

1. Tags to create radio buttons

2. Tags to create check boxes

3. Tag to create the submit button

Page 817: Java_E_Book_Satish_Singhal

Topic 23 Servlets and Java server Pages (Singhal) Page 20 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

Page 818: Java_E_Book_Satish_Singhal

Topic 23 Servlets and Java server Pages (Singhal) Page 21 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

Page 819: Java_E_Book_Satish_Singhal

Topic 23 Servlets and Java server Pages (Singhal) Page 22 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> 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

Pre-selects the radio button Pink.

Page 820: Java_E_Book_Satish_Singhal

Topic 23 Servlets and Java server Pages (Singhal) Page 23 of 42

bottom!</B><BR><BR> <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'>

1. Form tag. Notice the values of action and method attributes.

Page 821: Java_E_Book_Satish_Singhal

Topic 23 Servlets and Java server Pages (Singhal) Page 24 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' 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.

Protocol Web address

Port number

Path to servlet and servlet name

Page 822: Java_E_Book_Satish_Singhal

Topic 23 Servlets and Java server Pages (Singhal) Page 25 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

Page 823: Java_E_Book_Satish_Singhal

Topic 23 Servlets and Java server Pages (Singhal) Page 26 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”);

Page 824: Java_E_Book_Satish_Singhal

Topic 23 Servlets and Java server Pages (Singhal) Page 27 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

Page 825: Java_E_Book_Satish_Singhal

Topic 23 Servlets and Java server Pages (Singhal) Page 28 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

Page 826: Java_E_Book_Satish_Singhal

Topic 23 Servlets and Java server Pages (Singhal) Page 29 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.

Page 827: Java_E_Book_Satish_Singhal

Topic 23 Servlets and Java server Pages (Singhal) Page 30 of 42

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:

Hacked entry

Page 828: Java_E_Book_Satish_Singhal

Topic 23 Servlets and Java server Pages (Singhal) Page 31 of 42

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.JspPagejspDestroy, 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.

1. JSP page is translated into a servlet before being loaded.

Page 829: Java_E_Book_Satish_Singhal

Topic 23 Servlets and Java server Pages (Singhal) Page 32 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.

Page 830: Java_E_Book_Satish_Singhal

Topic 23 Servlets and Java server Pages (Singhal) Page 33 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.

Page 831: Java_E_Book_Satish_Singhal

Topic 23 Servlets and Java server Pages (Singhal) Page 34 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.

FIG. 23.15

1. <%@page %> t

2. JSP comment

Page 832: Java_E_Book_Satish_Singhal

Topic 23 Servlets and Java server Pages (Singhal) Page 35 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.

Page 833: Java_E_Book_Satish_Singhal

Topic 23 Servlets and Java server Pages (Singhal) Page 36 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.

Page 834: Java_E_Book_Satish_Singhal

Topic 23 Servlets and Java server Pages (Singhal) Page 37 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.*” %>

Page 835: Java_E_Book_Satish_Singhal

Topic 23 Servlets and Java server Pages (Singhal) Page 38 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:

<% @ page import = “java.util.*, java.text.*” %> 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:

< %@page import = “java.util.*” %>

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.

<%@ page import="java.util.*, java.text.*";%> 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.

Compile error because of space between <% and @

No longer a JSP code because there is space between < and %

JSP compile error because import directive is terminated by semicolon! Can be a single or double quote

Page 836: Java_E_Book_Satish_Singhal

Topic 23 Servlets and Java server Pages (Singhal) Page 39 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:

out.println (“Hello World” + <BR>); In JSP and HTML the same output would be made with code line: Hello World <BR> 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:

out.println (new java.util.Date () + <BR>); 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: <%= new java.util.Date () %> <BR> 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.

HTML Output done in servlet

Static HTML output

Expression outputted in Servlet

Expression outputted in JSP page.

Page 837: Java_E_Book_Satish_Singhal

Topic 23 Servlets and Java server Pages (Singhal) Page 40 of 42

<%= val ><BR> <%! private int val = 5; %> 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 if(val == 52){ %> Val = <%= val%> <BR> <%}else{ %> Val is not 52<BR> <%}%> 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.

Will compile and run fine because val is a class level variable and is visible every where, irrespective of the physical location of its declaration!

Under the scope of if selection structure

Under the scope of else selection structure.

Page 838: Java_E_Book_Satish_Singhal

Topic 23 Servlets and Java server Pages (Singhal) Page 41 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 " ); String Name = request.getParameter("firstname"); if(Name !=null) out.println ("to " + Name +" ");

Hello <%! String Name = null; %> <% Name = request.getParameter("firstname"); if(Name !=null)%> to <%=Name%>

Page 839: Java_E_Book_Satish_Singhal

Topic 23 Servlets and Java server Pages (Singhal) Page 42 of 42

Name = request.getParameter("lastname"); if(Name !=null) out.println (Name +" "); out.println ( " from Gandhi.net <BR>"); Name = request.getParameter("radio1"); if(Name !=null) out.println("<U>Your favorite color is:</U> "+Name +"<BR>"); String [] Str = {request.getParameter("check1"), request.getParameter("check2"), request.getParameter("check3"),request.getParameter("check4"), request.getParameter("check5"), request.getParameter("check6"), request.getParameter("check7")}; out.println("<U>List of your favorite food(s)/drink(s):</U><BR>"); if( Str[0]!=null) out.println(Str[0] + "<BR>"); if( Str[1]!=null) out.println(Str[1]+"<BR>"); if( Str[2]!=null) out.println(Str[2]+"<BR>"); if( Str[3]!=null) out.println(Str[3]+"<BR>"); if( Str[4]!=null) out.println(Str[4]+"<BR>"); if( Str[5]!=null) out.println(Str[5]+"<BR>"); if( Str[6]!=null) out.println(Str[6]+"<BR>"); out.println ("<U>Date and time are: </U>" + new java.util.Date() + "<BR>");

<% Name = request.getParameter("lastname"); if(Name !=null)%> <%=Name +" "%> from Gandhi.net <BR> <% Name = request.getParameter("radio1"); if(Name !=null)%> <U>Your favorite color is:</U> <%=Name %> <BR> <% String [] Str = {request.getParameter("check1"), request.getParameter("check2"), request.getParameter("check3"),request.getParameter("check4"), request.getParameter("check5"), request.getParameter("check6"), request.getParameter("check7")}; %> <U>List of your favorite food(s)/drink(s):</U><BR> <% if( Str[0]!=null)%> <%=Str[0] + "<BR>"%> <% if( Str[1]!=null)%> <%=Str[1]+"<BR>"%> <%if( Str[2]!=null)%> <%=Str[2]+"<BR>"%> <%if( Str[3]!=null)%> <%=Str[3]+"<BR>"%> <%if( Str[4]!=null)%> <%=Str[4]+"<BR>"%> <% if( Str[5]!=null)%> <%=Str[5]+"<BR>"%> <%if( Str[6]!=null)%> <%=Str[6]+"<BR>"%> <U>Date and time are: </U> <%= new java.util.Date()%> <BR>

Table 23.4