0% found this document useful (0 votes)
2 views193 pages

Let's Java

Chapter 15 discusses exception handling in Java, detailing the process of defining exception classes, throwing exceptions, and using try-catch blocks to manage errors. It emphasizes the importance of distinguishing between checked and unchecked exceptions, and provides guidelines for effective exception handling practices. The chapter also includes practical examples and outlines the structure of exception handling, including the use of finally blocks and nested try-catch scenarios.

Uploaded by

rajveerbarge2000
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
2 views193 pages

Let's Java

Chapter 15 discusses exception handling in Java, detailing the process of defining exception classes, throwing exceptions, and using try-catch blocks to manage errors. It emphasizes the importance of distinguishing between checked and unchecked exceptions, and provides guidelines for effective exception handling practices. The chapter also includes practical examples and outlines the structure of exception handling, including the use of finally blocks and nested try-catch scenarios.

Uploaded by

rajveerbarge2000
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Chapter 15: Exception Handling 291

}
catch ( StackException ex )
{
[Link] ( "Problem in stack" ) ;
[Link]( ) ;
}

try
{
while ( [Link]( ) > 0 )
[Link] ( [Link]( ) ) ;
}
catch ( StackException ex )
{
[Link] ( "Problem in stack" ) ;
[Link]( ) ;
}
}
}

Given below is the output that the program produces on execution:

Problem in stack
Stack full
25
Sanjay
Vinod

easier to trigger an exception while adding objects to the stack. We


would leave it for you to go through the program and figure out how it
produces this output, as an exercise. Also, you can try to implement the
Queue data structure on similar lines as stack.
From the above two programs Banking and Stack we can now
generalize how to deal with user-defined exceptions. There are four
parts involved in the exception handling mechanism. These are as
under:

Define the Exception Class


We have defined such exception classes in our programs
BankException and StackException. Both classes were inherited from
292 Let Us Java

Exception class and had a constructor using which an exception object


can be created. Additionally these classes had a method called inform( )
to report the error message.

Throw an Exception
When an exception situation occurs an exception object is created and
thrown. In our first program an exception could occur in one situation
when the balance goes below 500, whereas, in the second program
there were two exceptional situations when the stack becomes full
and we try to store another object in it, or when we try to remove an
object from an empty stack. In the first program, we create and throw a
BankException object, whereas in the second we create and throw a
StackException object. On throwing an exception the control is
transferred to the exception handler, i.e., the catch block.

The try Block


The statements that might cause the exceptions have been enclosed in a
pair of braces and preceded by the try keyword. This code is the

using exceptions. Note that all the code in the program need not be in a
try block. Just the code that anticipates occurrence of exceptional
condition during execution should be in try block..

The Exception Handler (catch Block)


The code that handles an exception is enclosed in braces, preceded by
the catch keyword, with the exception object that it proposes to catch
mentioned in parentheses.

How the Whole Thing Works?

(a) Code is executing normally outside a try block.


(b) Control enters the try block.
(c) A statement in the try block causes an error in a member function
called from it.
(d) The member function creates and throws an exception object.
(e) Control transfers to the exception handler (catch block) following
the try block.

You can appreciate how clean is this code. Just about any statement in
the try
Chapter 15: Exception Handling 293
one. The try-throw-catch arrangement handles it all for us,
automatically.

To round off all that we have learnt about exception handling, here are a
few finer points about it that you must note:

(a)
a catch block like this:
catch ( Exception e )
{
}
Programmers are tempted to write this when runtime errors occur
in their program and they wish to avoid displaying of an ugly and
elaborate stack trace of the exception.
(b)
the purpose of rectifying the exceptional situation or perform a
graceful exit.
(c) Always try to distinguish between types of exceptions by writing
multiple catch blocks wherever relevant.
(d) It is not necessary that the statement that causes an exception be
located directly in the try block. It may as well be present in a
function that is being called from the try block.
(e) A try block can be present inside another try block.
(f) If inner try catch block, then
the outer try catch handlers are inspected for a match when
an exception occurs.
(g) If we are writing a class library for somebody else to use, we should
anticipate what could cause problems to the program using it. At all
such places we should throw exceptions.
(h) If we are writing a program that uses a class library, we should
provide try and catch blocks for any exceptions that the library may
throw.
(i) Exceptions impose an overhead in terms of program size and (when
an exception occurs) in time. So we should not try to overuse it.
Make it optimally elaborate not too much, not too little.
294 Let Us Java

[A] State whether the following statements are True or False:

(a) The exception handling mechanism is supposed to handle compile


time errors.

(b) It is necessary to declare the exception class within the class in


which an exception is going to be thrown.

(c) Every thrown exception must be caught.

(d) For one try block there can be multiple catch blocks.

(e)
called.

(f) try blocks cannot be nested.

(g) Proper destruction of an object is guaranteed by exception handling


mechanism.

(h) All exceptions occur at runtime.

(i) Exceptions offer an object-oriented way of handling runtime errors.

(j) If an exception occurs, then the program terminates abruptly


without getting any chance to recover from the exception.

(k) No matter whether an exception occurs or not, the statements in


the finally clause (if present) will get executed.

(l) A program can contain multiple finally clauses.

(m) finally clause is used to perform cleanup operations like closing the
network/database connections.

(n) While throwing a user-defined exception multiple values can be set


Chapter 15: Exception Handling 295
(p) An exception must be caught in the same function in which it is
thrown.

(q) All values set up in the exception object are available in the catch
block.

(r) If our program does not catch an exception then the Java Runtime
catches it.

(s) It is possible to create user-defined exceptions.

(t) All types of exceptions can be caught using the Exception class.

(u) For every try block there must be a corresponding finally block.

[B] Answer the following:

(a) If we do not catch the exception thrown at runtime then who will
catch it?

(b) Explain in short most compelling reasons for using exception


handling over conventional error handling approaches.

(c) Is it necessary that all classes that can be used to represent


exceptions be derived from base class Exception?

(d) What is the use of a finally block in Java exception handling


sequence?

(e) How does nested exception handling work in Java?

While creating and executing a Java program things may go wrong at


3 different stages :
During Compilation : Reported by Compiler, Action Rectify
program
During Linking : Reported by Linker, Action Proper import
statements
296 Let Us Java

During Execution (runtime) : Reported by Java Runtime, Action


Tackle it on the fly
Examples of Runtime errors :
Memory Related - Stack / Heap overflow, Exceeding the bounds of an
array
Arithmetic Related - Divide by zero, Arithmetic over flow or under
flow
Others - Attempt to use an unassigned reference, File not found
2 Types of Exceptional conditions :
(a) Checked Exceptions - Compiler checks whether they have been
handled
Ex. File not found, Insufficient memory
(b) Unchecked exceptions - Up to us whether to handle them or not
2 Types of Unchecked Exceptions :
(a) Due to Internal Condition - k/a Runtime Exceptions
Ex. : Passing null instead of filename
(b) Due to External Condition - k/a Errors
Ex. : Disk failure while reading
How to determine - Checked or Unchecked
- Follow trail by clicking on exception
-
-

When a method called from client code is executing an Exceptional


Condition may occur. This condition can be tackled in 2 Ways :
(a) Pack exception information in an object and throw it
(b) Let Java Runtime pack exception information in an object and
throw it
Two things that can be done when the exception object is thrown :
(a) Throw it further
(b) Catch the object in client code
Chapter 15: Exception Handling 297

If we throw the exception object further - Default exception handler


Catches the object, Prints Stack Trace & terminates

If we catch the exception object in client code we can either perform a


Graceful exit or Rectify the exceptional situation & continue

2 ways to create Exceptional Condition objects


From Java API exception classes
From User-defined exception classes
Advantage of tackling exceptions in OO manner :
- More info can be packed into Exception objects
- Propagation of exception objects to caller is managed by Java
Runtime
How Java facilitates OO exception handling :
- By providing keywords - try, catch, finally, throw, throws
- By providing readymade exception classes - For Checked as well
as Unchecked Exceptions
- Advertise - Let methods advertise possibility of an exception
- Force - Make users handle advertised exception
How to use try - catch
try block - Enclose in it the code that you anticipate would cause an
exception
catch block - Catch the thrown exception in it. It must immediately
follow the try block
When exception is thrown control goes to catch block. Once catch
block is executed, control goes to the next line after catch block(s),
unless there is a return or throw in the catch block

When a method advertises that it will throw an exception, you have to


either catch or rethrow it.

try block :
- Can be nested inside another try block
- If inner try doesn't have a catch, outer try's catch handlers are
inspected for a match
298 Let Us Java

catch block :
- Multiple catch blocks for one try block are OK
- At a time only one catch block goes to work
- Order of catch blocks is important - Derived to Base
finally block :
- finally clause is optional
- Code in finally always runs, no matter what! Even if a return or
break occurs first
- it is placed after catch blocks (if they exist)
- try block must have catch block and/or finally block
Exception handling tips :
-
-
types of exceptions
- Make it optimally elaborate - Not too much, not too little
No point in creating a program that tells secrets to itself. Input /
Output with the outside world is the way of life for a program...

299
300 Let Us Java

Expectations from an I/O System


File, Directory and Drive Operations
The Java Streams Solution
Stream Classes
Byte and Character Operations
Reading Strings from a File
Record I/O
User-defined Streams
File Encryption/Decryption
Exercises
KanNotes
Chapter 16: Effective Input/Output 301

A lmost all programs have to perform Input/Output (I/O) in some


form or the other. There is not much use of writing a program that
spends all its time telling a secret to itself. And since all languages have
been dealing with input/output since the very first program came into
existence, it is quite natural to expect that a modern object-oriented
language like Java provides a mature input/output system. This chapter
proposes to explore the ways provided by Java to effectively carry out
I/O needs of a program.

Expectations from an I/O System


Since mankind has been creating software and writing programs for
more than five decades now, a programmer has begun to expect some
solid support from a language's I/O system to cater to his/her program's
I/O needs. These expectations are as follows:
(a) Communication with different sources and destinations: A Java
program should be able to carry out reading operations from input
devices like keyboard, port, disk, etc., and perform writing
operations to disk, printer, port, etc.
(b) Capability to I/O varied entities: A Java program should be able to
I/O byte, char, numbers of all kinds, strings, records and objects.
(c) Multiple means of communication: A Java program should be able
to carry out I/O in different modes like sequential and random.
(d) Communication with file system: A Java program should be able to
interact with file system entities like files and directories and be
able to access and manipulate paths, times, dates, access
permissions, etc.
Let us now see how Java meets these expectations.

File, Directory and Drive Operations


We are often required to programmatically perform operations on files,
directories and drives. For example, we may wish to create, copy,
delete, move, or open a file. Similarly, we may wish to create, move, and
navigate through directories and subdirectories. To carry out such
operations Java library provides a ready-made class called File. Based on
the requirement, we can appropriately use the methods of this class to
carry out the relevant file/directory operations.
Let us now create programs that use the File class. We would begin with
one that receives name of a file as input and then checks whether such a
302 Let Us Java

file exists or not. If it does, then it reports the relevant information

// Obtain information about a file


package fileinfoproject ;

import [Link].* ;
import [Link] ;

public class FileInfoProject


{
public static void main ( String[ ] args ) throws Exception
{
String str ;
try
{
BufferedReader br = new BufferedReader ( new
InputStreamReader ( [Link] ) ) ;
[Link] ( "Enter filename: " ) ;
str = [Link]( ) ;

File f ;
f = new File ( str ) ;
if ( [Link]( ) )
{
String dname = [Link]( ) ;
[Link] ( "Directory name: " + dname ) ;
String fname = [Link]( ) ;
[Link] ( "File name: " + fname ) ;
String abspath = [Link]( ) ;
[Link] ( "Full Name: " + abspath ) ;

long size = [Link]( ) ;


[Link] ( "Size: " + size ) ;
String ext ;
int dot = [Link] ( "." ) ;
ext = [Link] ( dot ) ;
[Link] ( "Extension = " + ext ) ;
[Link] ( "Last Modified = " +
new Date ( [Link]( ) ) ) ;
}
}
Chapter 16: Effective Input/Output 303
catch ( IOException e )
{
[Link] ( "Error in input" ) ;
}
}
}

Enter filename: c:\[Link]


Directory name: c:\
File name: [Link]
Full Name: c:\[Link]
Size: 2748
Extension = .txt
Last Modified = Tue Feb 09 16:29:24 IST 2010

The program is pretty straight-forward. To begin with, it receives the


name of the file "C:\[Link]" (you may give any other file's path as input).
Next, it creates a File object for this file and then extracts all the details
of this file using different methods of the File class. To be able to use the
File class and the Date class it is necessary to add the suitable import
statements at the beginning of the program.
In addition to the methods used here, there are several other methods
in the File class. You may explore them on your own.
Let us now create a program that gives a listing of all files in a directory.
Here is the program...

// Recursive listing of files in directories


package directorylisterproject ;
import [Link].* ;

public class DirectoryListerProject


{
public static void main ( String[ ] args )
{
File d ;
d = new File ( "." ) ;
ListFiles ( d, "" ) ;
}
static void ListFiles ( File d, String indent )
304 Let Us Java

{
String str ;
[Link] ( indent + [Link]( ) + "/" ) ;
for ( File fi : [Link]( ) )
{
str = indent + " " + [Link]( ) ;
[Link] ( str ) ;
}

// implement accept function of FileFilter interface


FileFilter dirFilter = new FileFilter( )
{
public boolean accept ( File file )
{
return [Link]( ) ;
}
}

for ( File di : [Link] ( dirFilter ) )


ListFiles ( di, indent + " " ) ;
}
}

On executing the program on my machine it produced the following


output:

./
build
[Link]
[Link]
nbproject
src
build/
classes
classes/
.netbeans_automatic_build
.netbeans_update_resources
directorylisterproject
directorylisterproject/
DirectoryListerProject$[Link]
[Link]
nbproject/
Chapter 16: Effective Input/Output 305
[Link]
[Link]
private
[Link]
[Link]
private/
[Link]
src/
directorylisterproject
directorylisterproject/
[Link]

In the output every directory has been purposefully marked with a / to


help identify an entry as a directory. Each nested directory is indented to
the right to show the hierarchy clearly.
At the heart of the program is the function ListFiles( ). This function is
first called from main( ) with two arguments "." and "". The first
argument indicates from where to start the listing and second indicates
the starting indentation level. "." means current directory. Thus, for our
program DirectoryListerProject is the starting directory. In the
ListFiles( ) function we have first obtained and printed all files in this
directory. In course of this, if we came across any directory then we
have called ListFiles( ) recursively to list files in this directory.
Let us now look at another interesting program. This one obtains and
reports information about all the drives present in a machine. To obtain
the list of drives, it uses the listRoots( ) method of the File class. Then
through a for loop it iterates through this list, gathering details of each
drive using the methods of the File class. Rest of the program is pretty
straight-

// Obtain information about all drives


package driveinfoproject ;
import [Link].* ;

public class DriveInfoProject


{
public static void main ( String[ ] args )
{
for ( File d : [Link]( ) )
{
[Link] ( "Drive = " + d ) ;
306 Let Us Java

[Link] ( "Total Space = "+ [Link]( ) ) ;


[Link] ( "Free Space = "+ [Link]( ) ) ;
[Link] ( " " ) ;
}
}
}

The machine on which I executed this program had 6 drives. Out of


these 3 were hard disk drives whereas the other 3 were DVD reader,
DVD read/write drive and a virtual drive. The output that I got on this
machine is given below.

Drive = C:\
Total Space = 179583315968
Free Space = 18052345856
Drive = D:\
Total Space = 59624124416
Free Space = 20760801280
Drive = E:\
Total Space = 10737414144
Free Space = 6717689856
Drive = F:\
Total Space = 0
Free Space = 0
Drive = G:\
Total Space = 0
Free Space = 0
Drive = H:\
Total Space = 0
Free Space = 0

The Java Streams Solution


To meet the expectations of a mature I/O system Java designers decided
that all I/O should be performed using I/O Streams. A stream is a
sequence of bytes that travel from source to destination over a
communication path. A program can read data from a stream or write
data to a stream. The streams are linked to physical devices by Java I/O
system. Most of the communication details are hidden from us by the
I/O system and we are required to concentrate only on what we wish to
Chapter 16: Effective Input/Output 307
read from where, and what we wish to write where. Figure 16.1 should
help you understand this concept better.

Figure 16.1
Streams are implemented using classes in [Link] package. This
abstraction of I/O operations using streams offers one important
benefit no matter from where we are reading or where we are writing,
stream behaves similarly. For example, whether we are reading from a
keyboard or a disk we call the same readLine( ) method. The
implementation of the readLine( ) method is different for different
devices. Thus because of stream-
have to worry about the specific details of the operating system and
underlying devices while performing I/O as shown in Figure 16.2. The
differences in the devices and the OS are hidden away from us into
different stream classes in the [Link] package.

Figure 16.2
The two fundamental operations that can be performed on a stream are
Reading and Writing. Reading involves transfer of data from a stream
into a data structure, such as an array of bytes. Writing consists of
transfer of data from a data source into a stream.
308 Let Us Java

Every stream may not support reading and writing. Most stream classes
contain methods called canRead( ) and canWrite( ) using which we can
determine which operations that stream supports.

Stream Classes
There are two fundamental types of streams Byte streams and
Character streams. Byte streams perform I/O 1 byte at a time, whereas
Character streams perform I/O one char (2 bytes) at a time. For
example, an integer 235 when written to a byte stream would involve
transfer of 4 bytes, since an integer is 4 bytes long. The same integer
when written to character stream would need transfer of 6 bytes 2
bytes per character.
There are several classes available in the Java library to perform stream-
based input/output of bytes/characters. Figure 16.3 and Figure 16.4
show the hierarchy of these classes.

Figure 16.3
The classes InputStream and OutputStream are abstract classes. From
these classes FileInputStream and FileOutputStream are derived. As
their names suggest, these classes read/write streams of bytes from/to
file. The FilterInputStream class uses some input stream as source of
data and filters it based on some criterion. The BufferedInputStream
class provides the buffering ability. Buffering is used to improve
read/write performance of a stream. The DataInputStream class
provides ability to read Java primitives.
Chapter 16: Effective Input/Output 309
Figure 16.4 shows the hierarchy of classes used for performing character
based input/output.

Figure 16.4
The classes Reader and Writer are abstract classes. The classes
InputStreamReader and OutputStreamWriter are used to read/write
character from/to stream. The FileReader and FileWriter classes are
used to read/write from/to file. The PrintWriter class is used to carry
out formatted writing in text representation.

Byte and Character Operations


Let us now create programs that use the different stream classes. We
would begin with a program that writes an integer in multiple ways into

package byteandcharacterstreams ;
import [Link].* ;

public class ByteAndCharacterStreams


{
public static void main ( String[ ] args )
{
int i = 123456 ;
try
{
310 Let Us Java

rawWrite ( i ) ;
charWrite ( i ) ;
unicodeWrite ( i ) ;
}
catch ( IOException e )
{
[Link] ( "IO error" ) ;
}
}
static void rawWrite ( int i ) throws IOException
{
DataOutputStream ds = new DataOutputStream (
new FileOutputStream ( "[Link]" ) ) ;
[Link] ( i ) ;
[Link]( ) ;
[Link] ( "Wrote 123456 as an integer" ) ;
[Link] ( "Length of file = " ) ;
[Link] ( new File ( "[Link]" ).length( ) ) ;
}
static void charWrite ( int i ) throws IOException
{
FileWriter fw = new FileWriter ( new File ( "[Link]" ) ) ;
[Link] ( ( ( Integer ) i ).toString( ) ) ;
[Link]( ) ;
[Link] ( "Wrote 123456 as a string" ) ;
[Link] ( "Length of file = " ) ;
[Link] ( new File ( "[Link]" ).length( ) ) ;
}
static void unicodeWrite ( int i ) throws IOException
{
OutputStreamWriter ow = new OutputStreamWriter (
new FileOutputStream ( "[Link]" ), "UTF-16" ) ;
[Link] ( ( ( Integer ) i ).toString( ) ) ;
[Link]( ) ;
[Link] ( "Wrote 123456 as a Unicode string" ) ;
[Link] ( "Length of file = " ) ;
[Link] ( new File ( "[Link]" ).length( ) ) ;
}
}

On executing this program, it produces the output shown below.


Chapter 16: Effective Input/Output 311
Wrote 123456 as an integer
Length of file = 4
Wrote 123456 as a string
Length of file = 6
Wrote 123456 as a Unicode string
Length of file = 14

The program writes the same integer into 3 files in different ways. For
example, it is written as an int in the first file, as a string in the second
and as a Unicode string in the third. These writing operations are done
through three methods defined in the program rawWrite( ),
charWrite( ) and unicodeWrite( ).
Note that after writing the same integer value (123456), the sizes of the

14 bytes, respectively. This indicates that during raw write, each byte
value of the 4-byte integer is written. Unlike this, during character
writing,
written to the file character-by-character. In Unicode writing, each
character of the string was written as a 2-byte character.
Before writing to a file, the file is opened using either the
FileOutputStream or File object. While writing the integer as an int, a
DataOutputStream object is used, whereas, while writing it as a string
or a Unicode string, a FileWriter and OutputStreamWriter, respectively
are used. Objects of these writers are created before using them to call
the writeInt( ) and write( ) methods. Instead of the statement,

DataOutputStream ds = new DataOutputStream (


new FileOutputStream ( "[Link]" ) ) ;

we can split it into two parts

fos = new FileOutputStream ( "[Link]" ) ;


DataOutputStream ds = new DataOutputStream ( fos ) ;

The close( ) function is called at the end of writing operations to close


the current stream and release any resources associated with the
current stream.
Rest of the program is simple to understand. You can modify this
program to write float values to a file.
312 Let Us Java

Reading Strings from a File


Let us now create a program which can read a file's contents and display
them on screen. For this we would read the file contents a line at a time,

package displayfilecontents ;
import [Link].* ;

public class DisplayFileContents


{
public static void main ( String[ ] args ) throws IOException
{
File f ;
f = new File ( "D:\\DisplayFileContents\\src\\
displayfilecontents\\[Link]" ) ;

if ( [Link]( ) && [Link]( ) )


{
BufferedReader br = null ;
try
{
br = new BufferedReader ( new FileReader ( f ) ) ;
String line ;
while ( ( line = [Link]( ) ) != null )
[Link] ( line ) ;
}
catch ( FileNotFoundException ex )
{
[Link] ( "Can't open " + [Link]( ) ) ;
}
finally
{
if ( br != null )
[Link]( ) ;
}
}
}
}

When we run this program it displays the contents of the file


DisplayFileContents have
Chapter 16: Effective Input/Output 313
created a File object, and then using it, we have checked whether the
file exists, and whether we have a permission to read the file. If so, we
have proceeded to read the file a line at a time using the
BufferedReader object that has a FileReader object reference stored in
it. Every line read is displayed on the screen using println( ).

Record I/O
Suppose we wish to write records of employees into a file and then read
them back from the file and display them on the screen. Each record
contains

// receives employee records, writes them to file,


// reads them back and displays them on screen
package recordio ;
import [Link].* ;

public class RecordIO


{
public static void main ( String[ ] args ) throws IOException
{
// prepare for writing records
FileOutputStream fos ;
fos = new FileOutputStream ( "[Link]" ) ;
OutputStreamWriter osw ;
osw = new OutputStreamWriter ( fos ) ;

// prepare for console input


InputStreamReader isr1 ;
isr1 = new InputStreamReader ( [Link] ) ;
BufferedReader br1 = new BufferedReader ( isr1 ) ;

// receive employee data, write it to file


String choice = "y", temp1, temp2, temp3 ;
while ( [Link] ( "y" ) )
{
[Link] ( "Enter employee id: " ) ;
temp1 = [Link]( ) ;

[Link] ( "Enter employee salary: " ) ;


temp2 = [Link]( ) ;
314 Let Us Java

[Link] ( "Enter employee name: " ) ;


temp3 = [Link]( ) ;

[Link] ( temp1 + "@" + temp2 + "@" + temp3 + "\n" ) ;


[Link] ( "Want another ( y/n ): " ) ;

choice = [Link]( ) ;
}
[Link]( ) ;

// prepare for reading records


FileInputStream fis ;
fis = new FileInputStream ( "[Link]" ) ;
InputStreamReader isr2 ;
isr2 = new InputStreamReader ( fis ) ;
BufferedReader br2 ;
br2 = new BufferedReader ( isr2 ) ;

String rec, str[ ] ;

// read employee data, display it on screen


[Link] ( "\nEmployees Info: " ) ;
while ( true )
{
try
{
rec = [Link]( ) ;
str = [Link]("@", 3) ;
[Link] ( "Id: " + str[ 0 ] ) ;
[Link] ( "Salary: " + str[ 1 ] ) ;
[Link] ( "Name: " + str[ 2 ] ) ;
}
catch ( Exception e )
{
if ( fis != null )
[Link]( ) ;
}
}
}
}
Chapter 16: Effective Input/Output 315
To begin with we have created objects of FileOutputStream, and
OutputStreamWriter classes. Of these, the FileOutputStream object is
used to write employee data to a file. To carry out this writing we have
used the function write( ). Once a set of records are written, we have
closed the stream.
In the next part of the program, we have done the reverse we have
read the data from the same file "[Link]" and displayed it on the
screen. While reading, each record is read as a string. Hence to split it
into id, salary and name we have used the split( ) function. Here is the

Enter employee id: 101


Enter employee salary: 12000
Enter employee name: Dinesh
Want another ( y/n ): y
Enter employee id: 201
Enter employee salary: 13500
Enter employee name: Shailesh
Want another ( y/n ): y
Enter employee id: 301
Enter employee salary: 13300
Enter employee name: Seema
Want another ( y/n ): n
Employees Info:
101
12000.0
Dinesh
201
13500.0
Shailesh
301
13300.0
Seema

User-defined Streams
Apart from using the standard streams Java permits us to define our
own streams and their behavior. For example, we can define a filter
stream called UppercaseFilterStream which would convert all
characters passed through it into uppercase characters. Such a stream
316 Let Us Java

class should be derived from FilterStream class. The following program


illustrates how this can be done:

// Converts all chars read from a file into uppercase using a filter stream
package filterstreamproject ;
import [Link].* ;

class UppercaseFilterReader extends FilterReader


{
public UppercaseFilterReader ( Reader s )
{
super ( s ) ;
}
public int read ( char[ ] cbuf, int off, int count ) throws IOException
{
int nb = [Link] ( cbuf, off, count ) ;

for ( int i = off ; i < off + nb ; i++ )


cbuf[ i ] = transform ( cbuf[ i ] ) ;

return nb ;
}
private char transform ( char ch )
{
if ( [Link] ( ch ) )
return [Link] ( ( char ) ch ) ;

return ch ;
}
}
public class FilterStreamProject
{
public static void main ( String[ ] args ) throws
FileNotFoundException, IOException
{
File f = new File ( "C:\\[Link]" ) ;
if ( [Link]( ) )
{
UppercaseFilterReader ufr ;
BufferedReader br ;

ufr = new UppercaseFilterReader (


Chapter 16: Effective Input/Output 317
new FileReader ( "C:\\[Link]" ) ) ;
br = new BufferedReader ( ufr ) ;

String line ;
while ( ( line = [Link]( ) ) != null )
[Link] ( line ) ;

[Link]( ) ;
[Link]( ) ;
}
}
}

On executing this program it opens the \ and converts


the text in it into uppercase. The uppercase characters are then
displayed on the screen. In my

I CDNUOLT BLVEIEE TAHT I CLUOD AULACLTY UESDNATNRD WAHT I


WAS RDANIEG. THE PHAONMNEAL PWEOR OF THE HMUAN MNID,
AOCCDRNIG TO A RSCHEEARCH AT CMABRIGDE UINERVTISY, IT DSENO'T
MTAETR IN WAHT OERDR THE LTTERES IN A WROD ARE, THE OLNY
IPROAMTNT TIHNG is TAHT THE FRSIT AND LSAT LTTEER BE IN THE
RGHIT PCLAE.. THE RSET CAN BE A TAOTL MSES AND YOU CAN SITLL
RAED IT WHOTUIT A PBOERLM. TIHS IS BCUSEAE THE HUAMN MNID
DEOS NOT RAED ERVEY LTETER BY ISTLEF, BUT THE WROD AS A WLOHE.
AZANMIG HUH? YAEH AND I AWLYAS TGHUHOT SLPELING WAS
IPMORANTT!

The UppercaseFilterReader class is derived from the abstract class


FilterReader. We have added three methods to the
UppercaseFilterReader class. These are constructor, read( ) and
transform( ). In the constructor, we simply pass the FileReader object
passed to it, to the base class constructor. The read( ) function reads the
specified number of bytes from a given offset position in the stream and
stores them in a buffer. It then calls the transform( ) function to
transform each character in the buffer into corresponding uppercase
character.
In main( ) we have first created a FileReader object. This object has then
been passed to the constructor of UppercaseFilterStream, which passed
it to the constructor of its base class FilterReader. This class's
318 Let Us Java

constructor stores the object reference in a private variable. Next we


have created a BufferedReader object and stored in it the
UppercaseFilterStream object's reference. In both cases containership is
being used as shown in Figure 16.5.

Figure 16.5
Once the construction of objects is over, we have called the readLine( )
method of BufferedReader class. This method in turn calls the read( )
method of the UppercaseFilterStream class. Here firstly the characters
are read from the input stream by calling the read( ) method of
FileReader class. These characters are collected in the buffer cbuf. This
buffer's contents are then converted to uppercase by calling the
transform( ) function for each character in the buffer. Thus we are able
to change the behavior of a stream by implementing the desired
behavior through a filter stream class.

File Encryption/Decryption
Security has gained paramount importance in the digital world. Often
we wish to secure our data from others. There are various techniques
through which this can be done. One of the most common techniques is
to encrypt the data in such a fashion that even if the encrypted data falls
into other people's hands they are unable to obtain the original data
from it. At the same time we should be able to get back the original data
by decrypting the encrypted data. Many Encryption/Decryption schemes
are popularly used today to secure the data from misuse. Our intention
here is not to discuss these schemes. Instead, we wish to evolve a very
simple encryption/decryption scheme. In this scheme during encryption
we would replace every lowercase alphabet in the source stream with
another predetermined lowercase character. During decryption we
would do the reverse. This type of encryption/decryption scheme is
often called a Substitution Cipher. Given below is the program which
implements the Substitution Cipher.
Chapter 16: Effective Input/Output 319

// Substitution Cipher implementation


package substitutioncipherproject ;
import [Link].* ;

interface ITransform
{
public char transform ( char ch ) ;
}
class Encrypt implements ITransform
{
String str = "xyfagchbimpourvnqsdewtkjzl" ;

public char transform ( char ch )


{
if ( [Link] ( ( char ) ch ) )
ch = [Link] ( ch - ( char ) 'a' ) ;

return ch ;
}
}
class Decrypt implements ITransform
{
String str = "xyfagchbimpourvnqsdewtkjzl" ;

public char transform ( char ch )


{
if ( [Link] ( ( char ) ch ) )
ch = ( char ) ( [Link] ( ( char ) ch ) + 'a' ) ;

return ch ;
}
}
class TransformWriter extends FilterWriter
{
private ITransform trans ;

public TransformWriter ( Writer s, ITransform t )


{
super ( s ) ;
[Link] = t ;
}
320 Let Us Java

public void write ( char[ ] buf, int off, int len )


{
for ( int i = off ; i < off + len ; i++ )
buf [ i ] = [Link] ( buf[ i ] ) ;

try
{
[Link] ( buf, off, len ) ;
}
catch ( IOException ex )
{
[Link] ( "IO error" ) ;
}
}
}
public class SubstitutionCipherProject
{
public static void main ( String[ ] args ) throws IOException
{
doEncDec ( "C:\\[Link]", "[Link]", true ) ;
doEncDec ( "[Link]", "[Link]", false ) ;
}
static void doEncDec ( String source, String target,
boolean IsEncrypt ) throws IOException
{
ITransform trans ;

if ( IsEncrypt )
trans = new Encrypt( ) ;
else
trans = new Decrypt( ) ;

FileReader sstream ;
BufferedReader sr ;

sstream = new FileReader ( new File ( source ) ) ;


sr = new BufferedReader ( sstream ) ;

FileWriter tstream ;
TransformWriter tw ;
BufferedWriter sw ;
Chapter 16: Effective Input/Output 321

tstream = new FileWriter ( new File ( target ) ) ;


tw = new TransformWriter ( tstream, trans ) ;
sw = new BufferedWriter ( tw ) ;

String line ;
while ( ( line = [Link]( ) ) != null )
[Link] ( line + "\r\n" ) ;

[Link]( ) ;
[Link]( ) ;
}
}

We have three classes in this program Encrypt, Decrypt and


TrasformWriter. Of these, the Encrypt and Decrypt classes implement
an interface called ITransform. This interface contains a function
transform( ) which is implemented to do encryption in the Encrypt class
and decryption in the Decrypt class.
Let us see how it does the encryption. It maintains an arbitrary string of
lowercase characters. Once it receives a character to be encrypted it
obtains an index value by doing the operation ch 'a', where ch is the
character to be encrypted. It then uses this index value to pick a
character from the arbitrary string. Thus this character is used as a
substitute for the character to be encrypted. Decryption works in exactly
the reverse way. The character to be decrypted is searched in the same
arbitrary string (as the one used for encryption). Once this character is
found, 'a' is added to its index value to obtain the original character.
That forms the crux of our substitution cipher.
The TransformWriter class uses the substitution cipher by calling the
transform( ) function of either the Encrypt class or the Decrypt class
depending on whether encryption or decryption is being carried out.
A helper function doEncDec( ) is called from main( ) twice first time to
carry out the encryption and second time to carry out the decryption.
The files used in these calls are shown in Figure 16.6.
322 Let Us Java

Figure 16.6
Rest of the program is similar to the uppercase filter stream program
that we discussed in the last section. So I would not repeat the
explanation here.
From this program and the one that we discussed in the last section we
can make the following important observations:
(a) Stream is a very important abstraction for data modelling in a
variety of applications. Being able to manipulate stream data
effectively is immensely important in Java programming. The
streams implementation in Java enables us to do that quite
effectively. For example, the data that we are manipulating in our
stream may come from a file stored on disk, a network socket or
simply a buffer in memory.
(b) We too can create our customized stream classes. When we do so,
we need to implement the abstract methods inherited from the
base class.

[A] State whether the following statements are True or False:

(a) [Link] refers to standard output stream (console).

(b) [Link] refers to standard input stream (keyboard).

(c) [Link] refers to standard error stream (console).

(d) Standard output/input/error streams are already open and ready to


supply/accept input/output data.
Chapter 16: Effective Input/Output 323
(g) All stream classes of Java library are defined in the [Link] package.

(h) InputStreamReader and OutputStreamWriter classes are used to


perform character-oriented I/O.

(i) FileInputStream and FileOutputStream classes are used to perform


byte-oriented I/O.

(j) If we wish to write characters to a file in Unicode, then we should


use the enum [Link] while creating the
OutputStreamWriter object.

(k) It is possible to create user-defined filter streams by inheriting our


stream class from FilterReader / FilterWriter class.

(l) The streams implementation in Java is such that the stream doesn't
have to know source or destination of the data.

[B] Answer the following:

(a) What are the common expectations from a mature input/output


system?

(b) Can we inherit new classes from File class available in the Java
library?

(c) How would you check whether a given file exists or not?

(d) Is it possible to check the number of drives, the type of each drive
and the drive format type through a Java program? If yes, how?

(e) What is a stream?

(f) What are the two fundamental types of I/O streams?

(g) Consider the following code snippet:


File f = new File ( " d:\\[Link]" ) ;
BufferedReader b = new BufferedReader ( new FileReader ( f ) ) ;
String s ;
// add statement here
Which statement will you add to read the file line-by-line and print
each line?
324 Let Us Java

[C] Pick up the correct alternative for each of the following questions:
(a) A number 485000 when written to a file using byte stream will
occupy
(1) 4 bytes
(2) 8 bytes
(3) 12 bytes
(4) 2 bytes

(b) A number 485000 when written to a file using character stream will
occupy
(1) 4 bytes
(2) 8 bytes
(3) 6 bytes
(4) 2 bytes

(c) Given a File object fobj, how will you determine whether it
represents a file or a directory?
(1) [Link] ( fobj ) ;
(2) if ( [Link]( ) )
(3) if ( [Link]( ) )
(4) if ( [Link]( ) )

(d) Which import statement should be used to avail classes that use
character stream?
(1) import [Link].*
(2) import [Link].*
(3) import [Link].*
(4) import io.*

(e) Which import statement should be used to avail classes that use
character stream?
(1) import [Link].*
(2) import [Link].*
(3) import [Link].*
(4) import io.*

Expectations from an IO System :


- I should be able to communicate with sources & destinations
Chapter 16: Effective Input/Output 325
- I should be able to I/O varied entities
- I should be able to communicate in multiple ways
- I should be able to deal with underlying file system
Java solution - Perform all IO using Streams

Stream is a sequence of bytes that travel from source to destination


over a communication path

Streams are implemented by classes in [Link] package

Linking of Streams to physical devices is done by Java IO system

Java program performs IO by reading / writing from / to a stream

Benefits of using Streams


- Streams hide details of communication from programmer
- Methods are same, implementation changes as per device
Types of streams : 1) Byte Streams 2) Character streams

Byte stream perform i/o one byte at a time. They are used to i/o
binary data

Character streams perform i/o one char (2 bytes) at a time. Used to


i/o textual data

To write 485000 to a file as sequence of bytes use byte stream

character stream

Byte Stream classes


- FileInputStream, FileOutputStream - R/W streams of bytes from
file
- FilterInputStream, FilteroutputStream - Filters data being read
or written
- BufferedInputStream - Provides buffering ability
- DataInputStream - Provides ability to read Java primitives
Character stream classes
326 Let Us Java

- InputStreamReader, OutputStreamWriter - R/W char from/to


stream
- FileReader, FileWriter - R/W characters from/to file
- PrintWriter - Formatted writing in text representation
System class contains 3 predefined public static variables - in, out,
err which are accessible from any part of the program
- out refers to standard output stream (screen)
- in refers to standard input stream (keyboard)
- err refers to standard error stream (screen)
These streams are already open and are ready to receive/send
input/output data

- System - class
- out - PrintStream object reference
- out - public static member of System class
- println( ), print( ) Members of PrintStream class
How to decide which classes to use when :
- What is your data format - text or binary
Binary InputStream, OutputStream
Text Reader, Writer
- Do you want random access capability?
Use RandomAccessFile class
- Dealing with objects or non-objects?
ObjectInputStream, ObjectOutputStream
- What are your sources and sinks for data?
Sockets, files, strings - All can be used by Byte and Character
Streams
- Do you need to use filtering?
Ability to do multiple things simultaneously is a great asset in
life. So also in programming...

327
328 Let Us Java

Multitasking and Multithreading


Multithreading in Java
Launching Threads
Launching Multiple Threads
Another Way to Launch Threads
A Practical Multithreading Example
Synchronization
The Synchronized Block
Inter-thread Communication
Thread Priorities
Exercises
KanNotes
Chapter 17: Multithreading 329

M ultithreading is the ability to perform several jobs simultaneously.


Knowingly or unknowingly we make use of multithreading
frequently in everyday life. For example, while driving a car we carry out
several activities in parallel we listen to music, we follow the traffic
rules, and we talk to the co-passengers. All this, without losing the main
focus, i.e. driving. There can be several such examples where we carry
out several activities at the same time. Since programmers are people

natural that in programming in general, and in Java in particular, too,


there is an effort to do several activities simultaneously.

Multitasking and Multithreading


Most modern OSs can execute several tasks in memory at a time. This
ability to execute several tasks simultaneously is known as Multitasking.
For example, while using Windows we can simultaneously print a
document on the printer, receive e-mails, download files and compile
programs. All these operations are carried out through different
programs that are being executed in memory at the same time.
This ability of Windows to execute several tasks can be taken a step
further, whereby we execute different parts of a program
simultaneously. This can be experienced while working with many
popular Windows software.

(a) While copying s the


copying progress through a green-colored progress bar, whereas,
another part of the program carries out the actual copying.
(b) While working with MS-Word one part of the program lets us type
the document, whereas two other parts perform the spelling check
and grammar check.
(c) In anti-viral software one part of the program scans the disk files for
viruses, whereas other part lets us interact with the user interface
of the software.
This ability to execute different parts of the same program
simultaneously is known as Multithreading.
If a multithreaded program is executing on a machine with a single
microprocessor, though it may appear that several tasks are being
performed by the processor simultaneously, in actuality it is not so.
What happens is that the processor divides the execution time equally
amongst all the running threads. Thus each thread gets the processor
330 Let Us Java

attention in a round robin manner. Once the time-slice allocated for a


thread expires, the operation that it is currently being performed is put
on hold and the processor now directs its attention to the next thread.
Thus, at any given moment, if we take the snapshot of memory, only
one thread is being executed by the processor. The switching of
attention from one thread to another happens so fast that we get the
effect as if the processor is executing several threads simultaneously.
In modern machines with multiple processors, the threads would
actually be executed simultaneously, as each processor can execute a
separate thread.
Multithreading has several advantages to offer. These are listed below.
(a) Responsiveness: Take MS-Word example again. Had the spell
checker and the grammar checker not run as different threads, we
would have been required to write documents and submit it to the
checkers from time to time. This would have resulted in low
responsiveness. Since the checkers run in different threads, our
document gets checked as we type, thereby increasing the
responsiveness of the application.
(b) Organization: Threading simplifies program organization. In the
displaying the progress
bar and the actual copying run in the same thread, then after
copying a few thousand bytes we would be required to advance the
progress bar. If we run the copying code and the progress bar code
in separate threads, we can avoid cluttering the copying code with
progress bar code and vice versa.
(c) Performance: Many a times it happens that a program needs to
wait for user input or has to give some output. The I/O devices are
generally slower than the processor. So the application waits for the
I/O operation to finish. Instead, if we use another thread for the I/O
operation, the processor time can be allotted to other important
tasks that can work independent of the I/O operation, thereby
improving the performance.

Multithreading in Java
To help you appreciate the challenges of multithreading you can try a
simple experiment. Make two phone calls to your friends and try to
carry out conversation with both of them concurrently. This would
involve major challenges talking to one friend, putting him on hold,
remembering where you left off, picking up the other receiver, talking to
Chapter 17: Multithreading 331
the other friend, putting him on hold, picking up the first receiver,
carrying on the conversation from the point where you left off, and
above all making the conversation sensible for everybody involved.
Java offers features that let you run multiple threads in a program. To
create multiple threads the programmer has to specify which parts of
the program he intends to execute concurrently. Although on the face of
it this might appear simple, rest assured that often multithreaded
programs are tricky and demand a substantial effort on your part to
master all the issues involved in multithreading.
Any simple Java program has a single thread of execution. This running
thread has a name called main, a priority and a group to which it
belongs. If we wish we can change the name of the thread. This has
been demonstrated in the program given below.

package mainthread ;
public class MainThread
{
public static void main ( String args[ ] )
{
Thread t = [Link]( ) ;
[Link] ( "Current thread: " + t ) ;
[Link] ( "mythread" ) ;
[Link] ( "After name change: " + t ) ;
String s = [Link]( ) ;
[Link] ( "Thread name: " + s ) ;
}
}

Current thread: main, 5, main


After name change: mythread, 5, main
Thread name: mythread

The object representing the running thread is obtained by calling the


static method currentThread( ) of the Thread class. If we print this
object using println( ) we get the name of the thread, its priority and its
thread group. Note from the output that 5 is the default priority. 1
represents the lowest priority and 10 the highest, thus 5 is the average
priority.
332 Let Us Java

Once we have obtained the Thread object, we can set or get the name
of the current thread using the methods setName( ) and getName( )
respectively.
It is possible to make multiple threads to belong to one group. If this is
done, then it is possible to manipulate all those threads together, rather
than individually. For example, we can start or suspend all
the threads within a group with a single method call.

Launching Threads
There are two mechanisms to launch new threads in a Java program.
These are:
(a) By extending the Thread class
(b) By implementing the Runnable interface
We wish to learn both these ways to launch a thread and assess the
utility of each. Let us begin with a program that uses the first way.

package sample ;
public class Sample
{
public static void main ( String args[ ] )
{
Ex t = new Ex( ) ;
[Link]( ) ;
for ( int i = 0 ; i < 5 ; i ++ )
[Link] ( "Main thread" ) ;
}
}
class Ex extends Thread
{
public void run( )
{
for ( int i = 0 ; i < 5 ; i++ )
[Link] ( "New thread" ) ;
}
}

Here we have derived the Ex class from the Thread class and defined a
run( ) method inside it. The method simply pr
main( ) we have created an object of Ex class, called
Chapter 17: Multithreading 333
the start( )
times.
The start( ) method is defined in Thread class and by inheritance is
available to Ex objects. Once we call the start( ) method, the thread gets
scheduled. This means we are informing the thread scheduler that the
new thread is ready to run. When the thread scheduler deems fit, it
would start executing this new thread by calling its run( ) method.
The output of the program is shown below.

Main thread
Main thread
Main thread
Main thread
Main thread
New thread
New thread
New thread
New thread
New thread

inter-mingled. But this did not happen because once the time slot got
allotted to the main thread, in that time slot it printed all the messages,
before the time slot could be snatched away and allotted to the new
thread. Had each loop been executed 1000 times, then during each
time-slot allocated to the two threads, each would not have been able
to print all 1000 messages. This would have resulted in inter-mingling of
messages.
Another way to get the inter-mingled messages is to put each thread to
sleep for 1000 milliseconds when they get the time slot. This would
ensure that in the first time-
entire printing. This change is shown below.

package sample ;
public class Sample
{
public static void main ( String args[ ] )
{
Ex t = new Ex( ) ;
[Link]( ) ;
334 Let Us Java

try
{
for ( int i = 0 ; i < 5 ; i ++ )
{
[Link] ( "Main thread" ) ;
[Link] ( 1000 ) ;
}
catch ( Exception e )
{
}
}
}
}
class Ex extends Thread
{
public void run( )
{
try
{
for ( int i = 0 ; i < 5 ; i++ )
{
[Link] ( "New thread" ) ;
[Link] ( 1000 ) ;
}
}
catch ( Exception e )
{
}
}
}

The static sleep( ) method of the Thread class postpones the execution
of next instruction by 1000 milliseconds. As a result, now the output is
inter-mingled as shown below.

Main thread
Main thread
Main thread
New thread
New thread
Main thread
Main thread
Chapter 17: Multithreading 335
New thread
New thread
New thread

Notice that the call to sleep( ) method has to be present in the try block,
as it is likely to throw an exception. Though, not the best of the ways, for
the sake of simplicity we have used an empty catch block to catch the
exception that sleep( ) may throw.

Launching Multiple Threads


Do not be under the impression that we can create only one thread
from the class derived from the Thread class. It is possible to create
multiple threads from the same class. This is illustrated in the following
program.

package sample ;
public class Sample
{
public static void main ( String args[ ] )
{
Ex t1 = new Ex( ) ;
[Link]( ) ;
[Link] ( "First" ) ;
Ex t2 = new Ex( ) ;
[Link]( ) ;
[Link] ("Second" ) ;
Ex t3 = new Ex( ) ;
[Link]( ) ;
[Link] ( "Third" ) ;
try
{
for ( int i = 0 ; i < 10 ; i ++ )
{
[Link] ( "Main thread" ) ;
[Link] ( 500 ) ;
}
}
catch ( Exception e )
{
}
}
336 Let Us Java

class Ex extends Thread


{
public void run( )
{
Thread t ;

t = [Link]( ) ;
String s = [Link]( ) ;

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


[Link] ( s ) ;
}
}

Given below is the output of the program.


First
First
First
First
First
Third
Third
Third
Third
Third
Third
Main thread
Second
Second
Second
Second
Main thread
Main thread
Main thread
:::

Here, while launching the three threads we have given a name to each,
which is displayed in a loop, when those threads get a time slot. In which
situation we would want to launch multiple threads from the same
Chapter 17: Multithreading 337
class? Imagine if the thread is to display an animation from a GIF file.
Then by launching different threads we can display different animations
in different parts of the screen simultaneously.
When we launch several threads from the main thread there is a
possibility that the main thread ends whereas the launched threads
continue to execute. If we wish that main thread should be the last
thread to finish execution, then we can employ the join( ) method of the
Thread class to ensure this, as shown below.

package sample ;
public class Sample
{
public static void main ( String args[ ] )
{
Ex t1 = new Ex( ) ;
[Link]( ) ;
[Link] ( "First" ) ;
Ex t2 = new Ex( ) ;
[Link]( ) ;
[Link] ("Second" ) ;
Ex t3 = new Ex( ) ;
[Link]( ) ;
[Link] ( "Third" ) ;
try
{
for ( int i = 0 ; i < 10 ; i ++ )
{
[Link] ( "Main thread" ) ;
[Link] ( 500 ) ;
}
}
catch ( Exception e )
{
}

[Link] ( [Link]( ) ) ;
[Link] ( [Link]( ) ) ;
[Link] ( [Link]( ) ) ;
[Link]( ) ;
[Link]( ) ;
[Link]( ) ;
338 Let Us Java

[Link] ( [Link]( ) ) ;
[Link] ( [Link]( ) ) ;
[Link] ( [Link]( ) ) ;
}
}

On execution, out of the calls to isAlive( ) some threads may return false
if those threads have finished execution. By calling join( ) the main
thread would wait for the alive threads to finish their execution, before
it terminates. Naturally, the second set of calls to isAlive( ) would return
false for each call.

Another Way to Launch Threads


So far we have been extending the Thread class and implementing the
run( ) method in it to launch new threads. This method has one
important limitation. Once our class is derived from Thread class we

inheritance. If we wish to keep our class open for derivation from some
other class and still be able to launch new threads, we should do so by
implementing a Runnable interface in it. This method of launching new
threads is given below.

package sample ;
public class Sample
{
public static void main ( String args[ ] )
{
Ex t = new Ex ( "One" ) ;
[Link]( ) ;
for ( int i = 0 ; i < 10 ; i ++ )
[Link] ( "Main thread" ) ;
}
}
class Ex implements Runnable
{
public Thread x ;

Ex ( String n )
{
x = new Thread ( this, n ) ;
}
Chapter 17: Multithreading 339

public void run( )


{
int i ;
for ( i = 0 ; i < 10 ; i++ )
[Link] ( [Link]( ) ) ;
}
}

Note that here we have not derived Ex from Thread class. Instead, we
are implementing the Runnable interface in it. The Runnable interface
has only one method in it run( ).
While creating an object of the Ex class, in the constructor we have
created an object of the Thread class and stored its address in a public
reference called x. Then, from main( ) we have used this x to call the
start( ) method of the Thread class. By doing this, we are informing JVM
to schedule this thread. As a result, the run( ) method gets called. In the
run( ) method we have simply printed the name of the thread.
Here is one more program that uses Runnable interface to launch
threads. The difference is that this one launches multiple threads for
each instance of the Ex class.

package sample ;
public class Sample
{
public static void main ( String args[ ] )
{
Ex t1 = new Ex ( "First" ) ;
[Link]( ) ;

Ex t2 = new Ex ( "Second" ) ;
[Link]( ) ;

Ex t3 = new Ex ( "Third" ) ;
[Link]( ) ;

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


[Link] ( "Main thread" ) ;
}
}
class Ex implements Runnable
340 Let Us Java

{
Thread x ;

Ex ( String n )
{
x = new Thread ( this, n ) ;
}

public void run( )


{
String s = [Link]( ) ;
int i ;
for ( i = 0 ; i < 10 ; i++ )
[Link] ( s ) ;
}
}

A Practical Multithreading Example


Suppose we wish to copy the contents of one folder into another.
Naturally, if the source folder contains multiple files, each file has to be
opened and its contents copied into a file in the target folder. If this
operation is done in a loop in a single thread, then unless copying of the
first file is over, the copying of second file cannot begin. Instead, a
better approach would be to do the copying in multiple threads. Given
below are two programs that follow the single thread and the
multithread approach. To simplify things, instead of copying files, we
simply open each source file, read it to the end and report the number
of lines present in each file.

// Approach 1 : Read files in a single thread


package singlethread ;
import [Link].* ;

public class SingleThread


{
static public void main ( String args[ ] ) throws Exception
{
[Link] ( "Starting Time: " +
[Link]( ));
for ( int i = 0 ; i < [Link] ; i++ )
{
Chapter 17: Multithreading 341
FileReader fr = new FileReader ( args[ i ] ) ;
BufferedReader br = new BufferedReader ( fr ) ;
LineNumberReader l = new LineNumberReader ( br ) ;

while ( [Link]( ) != null )


[Link] ( 10 ) ;

[Link] ( "Lines in " + args[ i ] + ":" +


[Link]( ) ) ;
}
[Link] ( "Ending Time: " +
[Link]( ) ) ;
}
}

The program reads three files [Link], [Link] and [Link] that are provided to
it as command-line arguments. To add these files to your project in
NetBeans, right click on the project folder and select New | Empty File
from the menu that pops up. Give the name of the file (say, [Link]) and
type a few lines in it. Similarly add [Link] and [Link] to your project. Once
this is done, add these filenames as command-line arguments through
Right-click project name | Properties | Run | Arguments.
In the program, we print the current time in milliseconds before we start
reading the files and after the reading is finished. This is done using the
function [Link]( ). The actual reading of a file is done
by using the LineNumberReader class. This class has a method
getLineNumber( ) which reports the number of lines present in the file
that it has read.
When I executed this program I got the following output:

Starting Time: 1484131339431


Lines in [Link]
Lines in [Link]
Lines in [Link]
Ending Time: 1484131340184

Your output may vary as depending on the contents of the three files
their reading times may vary. A quick calculation would show the
difference in times to be 753 milliseconds.
342 Let Us Java

Now let us look at the program that follows the multithreaded approach

// Approach 2 : Read files in multiple threads


package multithread ;
import [Link].* ;
public class Multithread
{
static public void main ( String args[ ] ) throws Exception
{
[Link] ( "Starting time: " +
[Link]( ) ) ;
linecounter t[ ] = new linecounter [ [Link] ] ;
for ( int i = 0 ; i < [Link] ; i++ )
{
t[ i ] = new linecounter ( args[ i ] ) ;
t[ i ].start( ) ;
}
for ( int i = 0 ; i < [Link] ; i++ )
t[ i ].join( ) ;
[Link] ( "Ending Time: " +
[Link]( ) ) ;
}
}
class linecounter extends Thread
{
String fname ;
linecounter ( String str )
{
fname = str ;
}
public void run( )
{
try
{
FileReader fr = new FileReader ( fname ) ;
BufferedReader br = new BufferedReader ( fr ) ;
LineNumberReader l = new LineNumberReader ( br ) ;
while ( [Link]( ) != null )
[Link] ( 10 ) ;
[Link] ( "Lines :" + fname + " : " +
[Link]( ) ) ;
Chapter 17: Multithreading 343
}
catch ( Exception e )
{
}
}
}

This time on execution the following times are reported:

Starting Time: 1484196850259


Lines: [Link] : 13
Lines: [Link] : 25
Lines: [Link] : 37
Ending Time: 1484196850646

This time the time difference is 387 milliseconds. Clearly the


multithreaded approach is a better option than the single-threaded
approach in such situations.

Synchronization
Software development is a team effort. Unless team members
cooperate with one another and synchronize their work with the rest of
the team, the team
several threads running, unless their activities are synchronized with one
another the disaster is not far away. For example, if a program
instantiates two threads and if both the threads use the same resource
and both of them change it simultaneously the situation would become
unreliable and erratic.
Let me illustrate the need for synchronization of threads using a simple
example. Consider the following method.

void display ( String msg )


{
[Link] ( "[" ) ;
[Link] ( msg ) ;
[Link] ( 1000 ) ;
[Link] ( "]" ) ;
}

Suppose three different threads decide to call this method to display a


message. It is expected that this method would display the message
344 Let Us Java

passed to it within a pair of [ ]. However, in reality it produces the


following output if the strings passed to it from three threads are KICIT,
Nagpur and India respectively.

[India[Nagpur[KICIT]
]
]

To rectify this, we need to synchronize the activities of each thread. How


this can be achieved is shown in the following program.

package sample ;
public class Sample
{
static public void main ( String args[ ] ) throws Exception
{
Output c = new Output( ) ;
Ex t1 = new Ex ( c, "KICIT" ) ;
[Link]( ) ;
Ex t2 = new Ex ( c,"Nagpur" ) ;
[Link]( ) ;
Ex t3 = new Ex ( c,"India" ) ;
[Link]( ) ;
[Link]( ) ;
[Link]( ) ;
[Link]( ) ;
}
}
class Ex extends Thread
{
private Output o ;
private String message ;

public Ex ( Output c, String msg )


{
o=c;
message = msg ;
}
public void run( )
{
[Link] ( message ) ;
}
Chapter 17: Multithreading 345
}
class Output
{
synchronized void display ( String msg )
{
[Link] ( "[" + msg ) ;
try
{
[Link] ( 1000 ) ;
}
catch ( InterruptedException e )
{
}
[Link] ( "]" ) ;
}
}

On execution, this program produces the desired output shown below.

[KICIT]
[NAGPUR]
[INDIA]

In this program we have defined two classes Ex and Output. In main( )


we have created one object of Output class and three objects of Ex
class. The Ex class is derived from the Thread class. When objects of Ex
class are created, along with object of Output class, a message to be
printed is passed to its constructor. It stores this message in a private
string message. This message is passed to the display( ) method of
Output class, when display( ) is called from run( ).
I want you to note a standard technique here. Since we do not explicitly
call the run( ) method, any objects that run( ) needs should be passed to
the constructor of the class to which run( ) belongs, so that run( ) can
access them. In our case, we needed the Output object to call display( )
from the run( ) method. That is why we passed it to the constructor
while creating the Ex objects.
Note that the display( ) function in the Output class has been marked as
synchronized. This ensures that once one thread makes a call to
display( ), unless the execution of display( ) in this thread is finished, the
call by other threads to display( ) would be put on hold. This results in
producing the systematic output that we desire.
346 Let Us Java

The Synchronized Block


At times it may so happen that a class has been developed with a view
to use it in single thread situation. But later on a need arises to use it in
a multithreaded situation. If we do not have an access to its source
code, we cannot mark the methods in it as synchronized. In such
situations, the solution is to use a syncronized block.
In the context of our program in the previous section, suppose we do
not have an access to source code of Output class. So we cannot mark
display( ) as synchronized method. In this case we need to simply make
the call to display( ) in a synchornized block as shown below, to get the
desired output.

public void run( )


{
synchronized ( o )
{
[Link] ( message ) ;
}
}

Inter-thread Communication
The programs in the Synchronization section unconditionally blocked
other threads from asynchronous access to certain methods. To improve
the overall performance of the program there should be a mechanism to
notify a waiting thread that it can start running. This means that one
thread should be able to communicate with the other. To achieve this
Java provides three methods wait( ), notify( ) and notifyAll( ). Given
below is the purpose of each of these methods.

Figure 17.1
Chapter 17: Multithreading 347
One of the places where usage of this method makes sense is in
implementing a classical Computer Science algorithm called Producer -
Consumer algorithm. This algorithm is described in the Exercise at the
end of this chapter.

Thread Priorities
If we wish, we can assign priorities to each running thread. This helps
the scheduler to determine the order in which these threads are
executed. Threads with higher priority are more important to a program
and are allocated processor time before lower-priority threads. A Java
thread can have three standard Priorities MIN_PRIORITY,
MAX_PRIORITY, NORM_PRIORITY. These represent numbers 1, 10 and 5.
Java provides following functions to set a new priority for a thread and

final void setPriority ( int level )


final int getPriority( )

[A] State whether the following statements are True or False:

(a) Multithreading always improves the speed of execution of the


program.

(b) A running task may have several threads running in it.

(c) Multitasking is same as multithreading.

(d) If we create a class that inherits from the Thread class, we can still
inherit our class from some other class.

(e) Default thread priority is 10.

(f) A higher priority thread can preempt a lower priority thread.

(g) It is possible to change the name of the running thread.


348 Let Us Java

(i) To launch a thread we must explicitly call the run( ) method defined
in a class that extends the Thread class.

(j) To synchronize a method defined in a class, we must have an access


to the source code of the class.

[B] Pick up the correct alternative for each of the following questions:

(a) What will happen if a Java program that launches 5 threads is


executed on a machine which has a single processor?
(1) 5 threads will get launched
(2) 1 thread will get launched
(3) 0 thread will get launched
(4) Error will occur since a single processor cannot handle 5 threads
(b) Which of the following are the CORRECT way to create a thread?
(1) Create a class and inherit it from Thread class
(2) Implement the Runnable interface
(3) Create a class and inherit it from CWinThread
(4) A and B
(c) Consider the following code snippet:
class Ex extends Thread
{
}
Ex t = new Ex( ) ;
[Link]( ) ;

Which of the following should be done to create a multithreaded


program?
(1) Define a run( ) method in the Ex class
(2) Define a run( ) method in the Ex class and call it using [Link]( )
(3) Implement the Runnable interface in class Ex
(4) Derive class Ex from the Runnable class
(d) Which of the following statement is CORRECT about the code
snippet given below:
class Ex extends Thread
{
public void run( )
{
}
Chapter 17: Multithreading 349
}
(1) run( ) method gets called when the thread gets a time slot
(2) We need to call run( ) explicitly
(3) start( ) will call run( )
(4) run( ) will be called by a method present in a class that
implements the runnable interface
(e) If in a Java program one thread lets you type a document and
another thread performs spellcheck on the same document then the
two threads
(1) should be synchronized
(2) need not be synchronized
(3) should be executed one after the other
(4) should be launched through 2 separate programs
(f) We wish to synchronize the working of methods present in a legacy
Java program whose source code is not available. How will you
achieve this?
(1) Hunt for the source code
(2) Use synchronized block
(3) Mark the methods from where legacy methods are called as
synchronized
(4) Reimplement the legacy code and then mark methods in it as
synchronized
(g) Suppose we wish to copy contents of one directory into another and
display the progress in copying through a green-colored progress
bar. Which of the following will be the CORRECT way to implement
this requirement?
(1) Create one program to copy and another program to display
progress bar. Run two programs simultaneously
(2) Create two threads in one program do copying in one thread
and display progress bar in another thread
(3) Create a single threaded program which performs both the tasks
(4) Create two programs, call one from the other

[C] Answer the following:

(a) Which are the two methods available for launching threads in a
Java program?

(b) What are the pros and cons of using two different methods of
launching threads in a Java program?
350 Let Us Java

(c) Which methods should be used to improve the performance of a


multithreaded Java program that uses synchronization?

(d) If Ex class implements the Runnable interface, then can we launch


multiple threads for objects of Ex class? If yes, how?

(e) Write a multithreaded program that copies contents of one folder


into another. The source and target folder paths should be input
through keyboard.

(f) Producer - Consumer algorithm is a popularly used algorithm in


Computer Science. It is a technique for generating requests (by
producer) and processing the generated requests (by consumer).
Write a program to implement this algorithm to meet following
specifications:

Consumer consumes the produced numbers by printing them


Both Producer and Consumer work as independent threads
Consumer must wait while Producer is producing
Once Producer has produced it would send a signal to Consumer
Producer must wait while Consumer is consuming
Once Consumer has consumed it should send a signal to
Producer

Multitasking - Ability to execute multiple tasks at a time


Task = Process
Multithreading - Ability to execute multiple parts of a program at a
time
Part = Thread = separate path of execution
Examples of Multitasking :
- Several Windows applications running in memory
- Multiple instances of Paint or Notepad in memory
Examples of Multitasking :
- Scroll Web page as graphic continues to load
- Printing one Word document while opening another
Chapter 17: Multithreading 351
- Replying an email while downloading another
Advantages of Multithreading
- Improves application's responsiveness
- Simplifies program organization
- Do other things while waiting for slow I/O operations
- Exploitation of Multiple Processors
Thread is a Java API class. It contains following useful methods :
- currentThread( ) -
- setName( ) - sets up name for a thread
- getName( ) - returns name of the specified thread
- sleep( ) - Postpone execution of next instruction by specified
milliseconds
Two methods to launch a thread :
- By extending the Thread class
- By implementing Runnable interface
Extending Thread class
- Easy to use
- Thread related functions can be overridden
- Disadvantage : Cannot use in Multiple Inheritance situations
Implementing Runnable Interface
Can be used in Multiple Inheritance situations
Disadvantage : Cannot override Thread class functions
If multiple files are to be read then the reading time can be reduced by
carrying out the reading in multiple concurrent threads

When >= 2 threads access same shared resource if we wish to ensure


that the resource is used by only 1 thread at a time, then it can be
achieved using Synchronized methods

If a method is declared as Synchronized then when it is called by


multiple threads, when the first thread is executing it others are
made to wait
352 Let Us Java

For older classes Synchronized blocks can be used to achieve the


same results

Often threads unconditionally block other threads from


asynchronous access to certain methods - hampers performance

To improve Performance - use wait( ), notify( ), notifyAll( ) methods

wait( ) - Tells calling thread to go to sleep till notified

notify( ) - Wakes up thread that called wait( ) on same object

notifyAll( ) - Wakes up all threads that called wait( ) on same obj.

Producer - Consumer algorithm is a technique for Generating


requests and Processing the pending requests

Producer produces requests, Consumer consumes generated


requests

Both work as independent threads

Working :
- Consumer must wait while Producer is producing
- Once Producer has produced it would send signal to Consumer
- Producer must wait while Consumer is consuming
- Once Consumer has consumed it would send signal to Producer
Thread priorities are used to schedule thread execution

Higher priority threads get more CPU time and may preempt lower
priority threads

Standard Priorities :
- MIN_PRIORITY, MAX_PRIORITY, NORM_PRIORITY
- These are constants with values 1, 10, 5
Functions to set and get priorities :
- final void setPriority ( int level )
- final int getPriority( )
Generalizations are good. Especially so, when the Compiler
handles the specializations...

353
354 Let Us Java

Generic Functions
Multiple Argument Types
Generic Classes
Bounded Generics
Exercises
KanNotes
.

Chapter 18: Generics 355

G enerics are a mechanism that make it possible to use one function


or class to handle many different data types. By using generics, we
can design a single function/class that operates on data of many types,
instead of having to create a separate function/class for each type. In
this chapter we would first look at using generics with functions and
then move on to using generics with classes.

Generic Functions
Suppose you wish to print contents of an integer array. To achieve this
we can write a function as shown below:

void printIntArr ( int [ ] arr )


{
for ( int i : arr )
[Link] ( i ) ;
}

Here the function printIntArr( ) is defined to receive an int array and


then print all its elements through a for loop. What if we wish to print
a float array we would be required to write a completely new
function printFloatArr( ). Similarly, to print a char array we would be
required to write printCharArr( ) a separate version of the same
function.
You would agree that this is a suitable case for overloaded functions,
as all these functions have different names but essentially carry out
the same activity printing elements of an array passed to them. This
way, at least the names of all these functions can be same. These
overloaded functions are given below:

// printArr for ints


void printArr ( int [ ] arr )
{
for ( int i : arr )
[Link] ( i ) ;
}

// printArr for floats


void printArr ( float [ ] arr )
{
for ( float i : arr )
[Link] ( i ) ;
356 Let Us Java

// printArr for chars


void printArr ( char [ ] arr )
{
for ( char i : arr )
[Link] ( i ) ;
}

// etc...
Have we gained anything by writing these overloaded functions? Not
much, because we still have to write a separate definition for each type.
This results into three disadvantages:

(a) Rewriting the same function body over and over for different types
is time consuming.
(b) The program consumes more disk space.
(c) If we decide to modify one such function, we need to remember to
make the modification in other overloaded functions.
e if we could write such a function just once, and make it
work for many different data types. This is exactly what function
generics do for us.
The following program shows how to write the printArr( ) function as a
generic function, so that it will work with any standard type. We have
invoked this function from main( ) for different data types.

package genericfunction ;
public class GenericFunction
{
public static <T> void printArray ( T[ ] arr )
{
for ( T i : arr )
[Link] ( "%s ", i ) ;

[Link]( ) ;
}
public static void main ( String args[ ] )
{
Integer[ ] intarr = { 10, -2, 37, 42, 15 } ;
Float[ ] floatarr = { 3.14f, 6.28f, -1.5f, -3.44f, 7.234f } ;
Chapter 18: Generics 357
Character[ ] chararr = { 'Q', 'U', 'E', 'S', 'T' } ;

printArray ( intarr ) ;
printArray ( floatarr ) ;
printArray ( chararr ) ;
}
}

Here's the output of the program:

10 -2 37 42 15
3.14 6.28 -1.5 -3.44 7.234
QUEST

As you can see, the printArr( ) function now works with different data
types that we use as arguments.

way to reuse object code. Generics provide a way to reuse the source
code. Generics can significantly reduce source code size and increase
code flexibility.
Let us now understand what grants the generic function the flexibility to
work with different data types. Here is the definition of the printArr( )

public static <T> void printArray( T[ ] arr )


{
for ( T i : arr )
[Link] ( "%s ", i ) ;

[Link]( ) ;
}

In this generic function a data type has been represented by a name (T


in our case) that can stand for any type. There's nothing special about
the name T. We can use any other name like type, mytype, etc.
Throughout the definition of the function, wherever a specific data
type would ordinarily be written, we substitute it with type T.
Notice that while calling printArr( ) function, we have passed to it an
array of Integers, Floats and Characters and not an array of ints, floats
and chars. This is because a generic function can work only with
reference types and not with primitives like int, float, double, char, etc.
358 Let Us Java

To help you fix your ideas about generics, here is another program that
uses a generic function. This one obtains the minimum of two quantities
using a generic minimum( ) function.

package minusinggenerics ;
public class MinUsingGenerics
{
public static <T extends Comparable <T> > T minimum ( T a, T b )
{
if ( [Link] ( b ) < 0 )
return a ;
else
return b ;
}
public static void main ( String[ ] args )
{
Float a = 3.14f, b = -6.28f, c ;
c = minimum ( a, b ) ;
[Link] ( c ) ;

Character ch = 'A', dh = 'Z', eh ;


eh = minimum ( ch, dh ) ;
[Link] ( eh ) ;

Double d = 1.1, e = 1.11, f ;


f = minimum ( d, e ) ;
[Link] ( f ) ;
}
}

Given below is the output that the program produces on execution.

-6.28
A
1.1

Note how we have defined the generic minimum( ) function.

public static < T extends Comparable <T> > T minimum ( T a, T b )


{

}
Chapter 18: Generics 359
The above definition means that this function would work with all those
types which implement the Comparable interface. In our case the
classes Integer, Float and Character classes implement this interface, so
we can use the minimum( ) function with these types.
Note that this function cannot compare two Integer or two Float objects
using relational operators like >, <, etc. Hence to actually carry out the
comparison we have used the compareTo( ) function of Integer / Float /
Character class.
We can extend the same comparison logic and write a program that
sorts Integers, Floats, Characters using a generic sorting function. Here

package genericsorting ;
public class GenericSorting
{
public static void main ( String[ ] args )
{
Float num[ ] = { 5.4f, 3.23f, 2.15f, 1.09f, 34.66f } ;
Integer arr[ ] = { -12, 23, 14, 0, 245, 78 , 66, -9 } ;
int i ;

sort ( num, 5 ) ;
for ( i = 0 ; i <= 4 ; i++ )
[Link] ( num[ i ] + " " ) ;
[Link]( ) ;
sort ( arr, 8 ) ;
for ( i = 0 ; i <= 7 ; i++ )
[Link] ( arr[ i ] + " " ) ;
}
public static <T extends Comparable <T> > void sort ( T[ ] n, int size )
{
int i, j ;
Tt;

for ( i = 0 ; i <= size - 2 ; i++ )


{
for ( j = i + 1 ; j <= size - 1 ; j++ )
{
if ( n[ i ].compareTo ( n[ j ] ) > 0 )
{
360 Let Us Java

t = n[ i ] ;
n[ i ] = n[ j ] ;
n[ j ] = t ;
}
}
}
}
}

The output of the program is given below:

1.09 2.15 3.23 5.4 34.66


-12 -9 0 14 23 66 78 245

I do not intend to explain the actual working of the sorting logic. This
topic has been dealt with thoroughly in all the standard books on Data
Structures. What you need to concentrate here is, how to write generic
functions that can work for variety of data types.

Multiple Argument Types


In all the programs that we have seen so far in this chapter, the generic
functions worked only with one type. But we can as well write a generic
function that takes different types of arguments during a call. The
following code shows such a generic function.

package mulitpletypesgenericfunction ;
public class MulitpleTypesGenericFunction
{
public static void main ( String[ ] args )
{
Integer i = 10 ;
Float j = 3.14f ;
Character ch = 'A' ;
printTypes ( i, j, ch ) ;
}
public static <T, S, Z> void printTypes ( T a, S b, Z c )
{
[Link] ( "a = " + a ) ;
[Link] ( "b = " + b ) ;
[Link] ( "c = " + c ) ;
}
}
Chapter 18: Generics 361
The printTypes( ) function can receive three different types of
arguments represented by T, S and Z. It simply prints all the arguments
that it receives. Would the function work, if we pass to it arguments of
same types? Yes, it will. So the following call would be perfectly valid.

Integer i = 10, m = 20, n = 30 ;


printTypes ( i, m, n ) ;

Generic Classes
The concept of generics can be extended even to classes. Generic
classes are often used for data storage. In fact Java provides a library of
container classes that implement data structures like stack, queue,
linked lists, binary tree, hash map, etc. These implementations are based
on generic classes.
Let us try implementing a Stack class as a generic class. This class should
be able to maintain a stack of Integers, Floats, Characters etc. Here is a
program with this generic stack class in action.

package genericstack ;
public class GenericStack
{
public static void main ( String[ ] args )
{
Stack <Integer> s1 ;
s1 = new Stack <Integer> ( 10 ) ;

if ( ! [Link]( ) )
[Link] ( 10 ) ;
if ( ! [Link]( ) )
[Link] ( 20 ) ;
if ( ! [Link]( ) )
[Link] ( 30 ) ;

int data1 ;
if ( ! [Link]( ) )
{
data1 = [Link]( ) ;
[Link] ( data1 ) ;
}
if ( ! [Link]( ) )
362 Let Us Java

{
data1 = [Link]( ) ;
[Link] ( data1 ) ;
}

Stack <Float> s2 ;
s2 = new Stack <Float> ( 10 ) ;

if ( ! [Link]( ) )
[Link] ( 10.5f ) ;
if ( ! [Link]( ) )
[Link] ( 20.5f ) ;
if ( ! [Link]( ) )
[Link] ( 18.5f ) ;

float data2 ;

if ( ! [Link]( ) )
{
data2 = [Link]( ) ;
[Link] ( data2 ) ;
}
if ( ! [Link]( ) )
{
data2 = [Link]( ) ;
[Link] ( data2 ) ;
}

Stack <Complex> s3 ;
s3 = new Stack <Complex> ( 10 ) ;

Complex c1 = new Complex ( 1.1f, 2.2f ) ;


Complex c2 = new Complex ( 3.3f, 4.4f ) ;
Complex c3 = new Complex ( 5.5f, 6.6f ) ;

if ( ! [Link]( ) )
[Link] ( c1 ) ;
if ( ! [Link]( ) )
[Link] ( c2 ) ;
if ( ! [Link]( ) )
[Link] ( c3 ) ;
Chapter 18: Generics 363

Complex c ;

if ( ! [Link]( ) )
{
c = [Link]( ) ;
[Link]( ) ;
}
if ( ! [Link]( ) )
{
c = [Link]( ) ;
[Link]( ) ;
}
}
}

class Stack <T>


{
private T arr[ ] ;
private int top ;
private int size ;

Stack ( int sz )
{
size = sz ;
top = -1 ;
arr = ( T[ ] ) new Object[ sz ] ;
}
boolean isFull( )
{
if ( top == size )
return true ;
else
return false ;
}
void push ( T data )
{
top++ ;
arr [ top ] = data ;
}
boolean isEmpty( )
364 Let Us Java

{
if ( top == -1 )
return true ;
else
return false ;
}
T pop( )
{
T val ;
val = arr [ top ] ;
top-- ;
return val ;
}
}

class Complex
{
float r, i ;

public Complex ( float rr, float ii )


{
r = rr ;
i = ii ;
}
public void printData( )
{
[Link] ( "Real = " + r + " Imag = " + i ) ;
}
}

We have created three stacks here s1, s2 and s3 and pushed three
objects on each one. Then we have popped the values from the three
stacks and displayed them on the screen. s1 and s2 maintain a stack of
objects of ready-made classes Integer and Float. We have also declared
a class called Complex and then pushed/ popped Complex objects
to/from stack s3

30
20
18.5
20.5
Chapter 18: Generics 365
Real = 5.5 Imag = 6.6
Real = 3.3 Imag = 4.4

You can observe that the order in which the elements are popped from
the stack is exactly reverse of the order in which they were pushed on
the stack.
The way to build a generic class is similar to the one used for building a
generic function. The <T> signals that the class is going to be a generic
class. This is precisely how we have defined the Stack class. Its skeleton
is shown below.

class Stack <T>


{
// code that uses the type T
}

It the Stack class, the type T is used at every place in the class where
there is a reference to the type of the array arr. There are four such
places the definition of arr, the constructor, the argument type of the
push( ) function, and the return type of the pop( ) function. Do take a
look at these four functions in our program.
To create objects of this generic class we have used the statements like,

Stack <Integer> s1 ;
s1 = new Stack <Integer> ( 10 ) ;

While creating the object s1 we are passing 10 to the constructor of


generic stack class. The value 10 indicates the size of the array that is
going to hold the values pushed into the stack. In the constructor we
have created this array through the statement

arr = ( T[ ] ) new Object[ sz ] ;

Here, firstly an array of Objects is created and the address of this array is
typecasted into an address of array of type T.
In the constructor, to indicate emptiness of stack we have initiated top
to a value -1. This variable is going to act as an index into the array in
which the values pushed into the stack are going to be stored. We have
also preserved the value of array size in the variable size. Later, in
functions isEmpty( ) and isFull( ) we have used these values to check
whether stack is empty or full.
366 Let Us Java

Note that it is also possible to inherit a new class from a generic class.

Bounded Generics
Let us now define and use a generic class called Statistics. This class
obtains average of Integers or Floats. This should be fairly simple.
However, the twist here is, we should not be allowed to find average of

This means that the Statistics class should not work for strings. Such
classes are known as Bounded Generics. It is very simple to accomplish
this. While defining the Statistics class we should define it through the
statement

class Statistics <T extends Number>

This ensures that Statistics class can work only with those types that are
derived from Number. Incidentally, Integer and Float both are derived
from Number class, so Statistics can work with objects of these classes.
Here is the full-fledged program.

package statsdemo ;
public class StatsDemo
{
public static void main ( String[ ] args )
{
Integer iarr[ ] = { 1, 2, 3, 4, 5 } ;
Statistics <Integer> iobj ;
double avg1 ;

iobj = new Statistics <Integer> ( iarr ) ;


avg1 = [Link]( ) ;
[Link] ( "avg1 = " + avg1 ) ;

Float farr[ ] = { 1.1f, 2.1f, 1.0f } ;


Statistics <Float> fobj ;
double avg2 ;

fobj = new Statistics <Float> ( farr ) ;


avg2 = [Link]( ) ;
[Link] ( "avg2 = " + avg2 ) ;
}
}
Chapter 18: Generics 367
class Statistics <T extends Number>
{
private T arr[ ] ;

Statistics ( T[ ] obj )
{
arr = obj ;
}
public double getAverage( )
{
double sum = 0.0 ;

for ( int i = 0 ; i < [Link] ; i++ )


sum = sum + arr[ i ].doubleValue( ) ;

return ( sum / [Link] ) ;


}
}

The program is pretty straight-forward and I think you can understand it


easily. The doubleValue( ) method returns the value of the specified
number as a double.

[A] State True or False:

(a) Java supports generic classes but not generic functions.

(b) We can inherit a new class from a generic class.

(c) Using generic functions saves memory.

(d) Generic functions cannot work for primitives like int, float, char,
etc.

(e) A generic function can receive multiple argument types.


368 Let Us Java

(i) Generic classes describe the functionality without being bound to


any type.

[B] Answer the following:

(a) Write a program that will implement a linked list through a generic
class.

(b) Write a program that has a generic class that can sort dates and
strings apart from integers and floats.

[C] Pick up the correct alternative for each of the following questions:

(a) If printArray( ) is a generic function capabale of printing any numeric


array then which of the following is the CORRECT way to call it?
(1) int[ ] arr = { 10, 20, 30, 40, 50 } ;
printArray ( arr ) ;
(2) float[ ] arr = { 1.1, 1.2, 1.3, 1.4, 1.5 } ;
printArray ( arr ) ;
(3) Integer[ ] arr = { 10, 20, 30, 40, 50 } ;
printArray ( arr ) ;
(4) char[ ] arr = { 'A', 'B', 'C', 'D', 'E' } ;
printArray ( arr ) ;

(b) A generic function can work with


(1) byte
(2) char
(3) float
(4) Float

(c) Which of the following statement is CORRECT about the fun( )


function given below:

public static < T > void fun ( T[ ] arr )


{
for ( T i : arr )
[Link] ( i ) ;
}
(1) It is a generic function.
(2) It is receiving an array of any reference type
(3) It is printing all elements of the array that it is receiving
(4) (1), (2) and (3)
Chapter 18: Generics 369

(d) Which of the following statement is CORRECT about the code


snippet given below:

public static < T > T minimum ( T a, T b )


{
if ( [Link] ( b ) < 0 )
return a ;
else
return b ;
}

(1) It returns the smaller of the 2 arguments that it receives


(2) It works only with those types that are derived from Number
class
(3) It works only with those types which implement a Comparable
interface
(4) It can work with any type of primitive

Generics promote source-code level reuse, whereas Inheritance


promotes byte-code level reuse

It is possible to create generic functions as well as generic classes

Once the generic function / class is ready we can use them with any
reference type

Primitives are often called value types, whereas classes are called
reference types

Syntax of defining and calling a generic function :


// call to generic function
Integer[ ] intarr = { 10, -2, 37, 42, 15 } ;
printArray ( intarr ) ;

// generic function definition


public static <T> void printArray ( T[ ] arr )
370 Let Us Java

{
..
}
Generic function that can work with types that implements a
Comparable interface
public static <T extends Comparable <T> > T min ( T a, T b )
{

}
Generic function that can receive multiple types
public static <T, S, Z> void printTypes ( T a, S b, Z c )
{
[Link] ( "a = " + a + " b = " + b + " c = " + c ) ;
}
Syntax for using and defining a generic class :
// using generic class
stack <Integer> s1 ;
s1 = new stack <Integer> ( 10 );
[Link] ( 10 ) ;

// defining generic class


class stack <T>
{
..
}
Bounded generic class restricts its usage only by those reference
types which are derived from the specified type

For example, the following class would work only for those types
that are derived from the Java API Number class :
class Statistics <T extends Number>
{
..
}
There are many standard ways of storing and accessing data.
Let Java Collections handle that, so that you can concentrate on
building something bigger using them...

371
372 Let Us Java

Why a New Approach?


Array of Names and Numbers
Maintaining a Stack
Maintaining a Linked List
Maintaining a Tree
Maintaining a HashMap
Using the Algorithms
Exercises
KanNotes
Chapter 19: Java Collections 373

A s Java became a popular choice amongst programmers to


implement solutions, a need was felt to have a standard way to
handle the data in the program. So a set of classes were made available
to handle the data. These included classes like Vector, Stack, Dictionary,
etc. However, these classes lacked a unified approach in the sense, the
usage of each class was not consistent with the usage of other. When
Generics were introduced in Java a completely new set of classes and
interfaces were created in Java API for handling data. These classes
came to be known as Java Collections Framework. Let us now get to the
root of it.

Why a New Approach?


Suppose in a program we wish to store, retrieve and manipulate
numbers and strings. An easy and intuitive way to handle this situation
would be to create arrays of numbers and strings. However, this
approach has following limitations:

(a) We may not want fixed-size arrays. We may want arrays to grow in
size dynamically as we keep adding new elements to it. This
requirement cannot be met by normal arrays, at least not without
an effort of allocating space for bigger-sized array, copying existing
elements into this space, etc.
(b) There may be a need to maintain data in different ways like
Dictionary (where order is important), Key-Value maps, like cell
number (key) and name (value).
(c) There may be a need to access data in different ways Last In First
Out (as in a stack), First In First Out (as in a queue), or sorted order.

To handle all these dynamics a completely new Java library based on


Generics, called Java Collections Framework was introduced. This
collections framework contains Collection classes, Interfaces and
Algorithms (set of static functions in the Collections class). Some of the
highlighting features of this collection framework are:

(a) Since the collections framework is based on generics it lets you


handle virtually any type of data.
(b) The collections framework provides a set of very efficient classes to
carry out most data management functionality. Do not confuse this
with database management, which involves management of data
374 Let Us Java

on disk. As against this, collections framework primarily manages


data in memory.
(c) It contains readymade classes for most Data Structures like stack,
queue, linked list, binary tree, hashmap, etc.
(d) There is a lot of consistency in usage of the collection classes. For
example, the same add( ) function is available for adding new data
to different collections. So no matter how a queue or a linked list
organizes the data internally, the call that the programmer has to
make for adding a new element to them remains same.
(e) Rather than doing the entire implementation from scratch, it is
easily possible to extend the collections framework using the usual
inheritance rules, to suit our specific needs.

Given in Figure 19.1 is a very short list of classes and interfaces available
in the collections framework. This list is by no means exhaustive or
complete, but is given here just to give you an idea of how the
collections framework is organized.
The classes and interfaces of the collections framework are defined in
[Link] package.
In summary, we can say that collections framework provides
prepackaged data structures plus the algorithms to manipulate them.

Figure 19.1
Chapter 19: Java Collections 375

Array of Names and Numbers


Let us now see how to use the collections framework. We would begin
with managing a set of names and a set of numbers. This can be done
using the ArrayList collection class. Given below is a program that shows
how this can be done.

package arraylistdemo ;
import [Link].* ;
public class ArrayListDemo
{
public static void main ( String[ ] args )
{
ArrayList <String> alnames ;

alnames = new ArrayList <> ( ) ;


[Link] ( "Shashank" ) ;
[Link] ( "Prasanna" ) ;
[Link] ( "Nimesh" ) ;
[Link] ( "Karun" ) ;
[Link] ( "Rajgopal" ) ;

[Link] ( "contents of al: " + alnames ) ;


[Link] ( 2, "Aditya" ) ;
[Link] ( 3 ) ;
[Link] ( "Karun" ) ;
[Link] ( "contents of al: " + alnames ) ;

if ( [Link] ( "Aditya" ) )
[Link] ( "Aditya is present in the array list" ) ;

ArrayList <Integer> alnums ;


alnums = new ArrayList <> ( ) ;
[Link] ( 10 ) ;
[Link] ( 20 ) ;
[Link] ( 30 ) ;
[Link] ( 40 ) ;

int sum = 0 ;
for ( int i = 0 ; i < [Link]( ) ; i++ )
sum = sum + [Link] ( i ) ;
376 Let Us Java

[Link] ( "sum = " + sum ) ;

Integer arr[ ] = new Integer [ [Link]( ) ] ;


arr = [Link] ( arr ) ;

sum = 0 ;
for ( int n : arr )
sum += n ;

[Link] ( "sum = " + sum ) ;


}
}

Here is th

contents of alnames: [Shashank, Prasanna, Nimesh, Karun, Rajgopal]


contents of alnames: [Shashank, Prasanna, Aditya, Rajgopal]
Aditya is present in the array list
sum = 100
sum = 100

The program begins by creating an ArrayList object for storing strings


and then adding a few names to it using add( ) function. If we wish, we
can also pass the initial size of the array list by passing the size to the
constructor while creating the ArrayList object. After creating the
object, we have added a new name at a specific position (using the
overloaded add( ) function) and removed name from a specific position
(using the remove( ) function). Thus addition, insertion and deletion
operations are straight-forward.
There is a very simple way to print the entire ArrayList contents using
println( ). Note that the ArrayList maintains the list in a dynamic fashion.
Nowhere have we specified its size. It keeps growing as we keep adding
new elements. The contains( ) function helps us figure out whether a
specific element is present in the array list or not.
What is important for you to notice is that the usage of ArrayList class

instead of names.
We have obtained the sum of all integers by retrieving each integer
using the get( ) function. Note that get( ) returns an Integer, not an int.
The size( ) function yields the current size of the array list.
Chapter 19: Java Collections 377
The array maintained by array list can be converted into the normal Java
array using the toArray( ) function. This array can then be iterated over
using the special for loop as shown in the program.

Maintaining a Stack
A Stack is a data structure in which addition of new element or deletion
of an existing element always takes place at the same end. This end is
often known as top of stack. This situation can be compared to a stack
of plates in a cafeteria where every new plate added to the stack is
added at the top. Similarly, every plate taken off the stack is also from
the top of the stack. Thus stack is a last-in-first-out (LIFO) list. When an
item is added to a stack, the operation is called push, and when an item
is removed from the stack the operation is called pop.
Given below is a program that maintains a stack of city names using the
collection class called Stack. Note that before calling the pop( ) function
we need to ascertain whether the stack has any element left in it. This is
done by calling the isEmpty( ) function.

package stackdemo ;
import [Link].* ;
public class StackDemo
{
public static void main ( String args[ ] )
{
Stack < String > s ;
s = new Stack <> ( ) ;
[Link] ( "Delhi" ) ;
[Link] ( "Nagpur" ) ;
[Link] ( "Indore" ) ;
[Link] ( "Raipur" ) ;
[Link] ( "Mysore" ) ;
[Link] ( "Mumbai" ) ;

String str ;

if ( ! [Link]( ) )
{
str = [Link]( ) ;
[Link] ( str ) ;
}
378 Let Us Java

if ( ! [Link]( ) )
{
str = [Link]( ) ;
[Link] ( str ) ;
}
}
}

Maintaining a Linked List


Linked list is a very common data structure often used to store similar
data in memory. While the elements of an array occupy contiguous
memory locations, those of a linked list are not constrained to be stored
in adjacent locations. The individual elements are stored "somewhere"
in memory, rather like a family dispersed, but still bound together. The
order of the elements is maintained by explicit links between them. For
instance, the marks obtained by different students can be stored in a
linked list as shown in Figure 19.2.

Figure 19.2
Observe that the linked list is a collection of elements called nodes, each
of which stores two items of information an element of the list and a
link. A link is a reference or an address that indicates explicitly the
location of the node containing the successor of the list element. In
Figure 19.2, the arrows represent the links. The data part of each node
consists of the marks obtained by a student, and the link part is a
pointer to the next node. The NULL in the last node indicates that this is
the last node in the list.
Instead of marks, we can maintain a linked list of names. If we want, we
can maintain both in each node. The program given below uses the
collection class LinkedList to maintain a linked list of names of students.
Most of the operations in the program are self-explanatory. Go through
the program carefully, a step at a time.
Chapter 19: Java Collections 379
package linkedlistdemo ;
import [Link].* ;
public class LinkedListDemo
{
public static void main ( String[ ] args )
{
LinkedList <String> ll ;
ll = new LinkedList <> ( ) ;
[Link] ( "Subhash" ) ;
[Link] ( "Rahul" ) ;
[Link] ( "Joe" ) ;
[Link] ( "Vineeta" ) ;
for ( String s : ll )
[Link] ( s ) ;

[Link] ( 2, "Neha" ) ;
[Link] ( ll ) ;

String name = [Link] ( 2 ) ;


[Link] ( "String at position 2 = " + name ) ;
[Link] ( 3, "Sanjay" ) ;
[Link] ( ll ) ;
[Link] ( 1 ) ;
[Link] ( ll ) ;
}
}

Subhash
Rahul
Joe
Vineeta
[Subhash, Rahul, Neha, Vineeta]
String at position 2 = Neha
[Subhash, Rahul, Neha, Sanjay, Vineeta]
[Subhash, Neha, Sanjay, Vineeta]

Maintaining a Tree
The data structures such as linked lists, stacks and queues are linear
data structures. As against this, trees are non-linear data structures. In a
380 Let Us Java

linked list each node has a link which points to another node. In a tree
structure, however, each node may point to several other nodes (which
may then point to several other nodes, etc.). Thus a tree is a very flexible
and powerful data structure that can be used for a wide variety of
applications. For example, suppose we wish to use a data structure to
represent a person and all of his or her descendants. Assume that the
person's name is Rahul and that he has 3 children, Sanjay, Sameer and
Nisha. Also suppose that Sameer has 3 children, Abha, Ram and Madhu
and Nisha has one child Neha. We can represent Rahul and his
descendants with the tree structure shown in Figure 19.3.

Figure 19.4
Notice that each tree node contains a name for data and one or more
pointers to the other tree nodes.
Although the nodes in a general tree may contain any number of
pointers to the other tree nodes, a large number of data structures have
at the most two pointers to the other tree nodes. This type of a tree is
called a Binary Tree.
Many algorithms that use binary trees proceed in two phases. The first
phase builds a binary tree, and the second traverses the tree. Suppose
we wish that while traversing the binary tree we should be able to
access the elements in it in ascending order. To ensure this we need to
arrange the elements properly during insertion. A simple logic to do so
would be to compare the element to be inserted with the element in the
root node and then take the left branch if the element is smaller than
the element in the node, and a right branch if it is greater or equal to
the element in the node. Thus if the input list is

3, 9, 1, 4, 7, 11
Chapter 19: Java Collections 381
then using this insertion method the binary tree shown in Figure 19.4
would be produced.

Figure 19.4
Such a binary tree has the property that all the elements in the left sub-
tree of any node n are less than the contents of n. And all the elements
in the right sub-tree of n are greater than or equal to the contents of n.
A binary tree that has these properties is called a Binary Search Tree.
If a binary search tree is traversed in in-order, i.e., in the order left child,
root, and right child and the contents of each node are printed as each
node is visited, the numbers are printed in ascending order. This is
demonstrated in the program given below.

package treesetdemo ;
import [Link].* ;
public class TreeSetDemo
{
public static void main ( String args[ ] )
{
TreeSet <Integer> ts ;
ts = new TreeSet <> ( ) ;
[Link] ( 3 ) ;
[Link] ( 9 ) ;
382 Let Us Java

[Link] ( 1 ) ;
[Link] ( 4 ) ;
[Link] ( 7 ) ;
[Link] ( 11 ) ;

[Link] ( ts ) ;
[Link] ( [Link] ( 4, 11 ) ) ;
[Link]( ) ;
[Link] ( ts ) ;
}
}

On execution the program produces the following output:

[1, 3, 4, 7, 9, 11]
[4, 7, 9, 11]
[]

From the output you can see that the subSet( ) function gives all those
nodes that lie between the nodes passed to it. Also, to delete all the
nodes in the tree at one shot, the clear( ) function can be used.

Maintaining a HashMap
The HashMap class lets us maintain a set of key - value pairs. For
example, we can maintain key - value pairs of cell numbers and names,
or key - value pairs of day names in English and Hindi. Against each key
multiple values may also be maintained. For example, against cell
number we can store the name, address and photograph. The key -
value pairs may not be stored in the same order as the order of
insertion. We can get the order in which they are being maintained by
printing out the hash map. This is shown in the following program.

package hashmapdemo ;
import [Link].* ;

public class HashMapDemo


{
public static void main ( String args[ ] )
{
HashMap < String, String> hm ;
hm = new HashMap < > ( ) ;
Chapter 19: Java Collections 383
[Link] ( "Sun", "Ravi" ) ;
[Link] ( "Mon", "Som" ) ;
[Link] ( "Tue", "Mangal" ) ;
[Link] ( "Wed", "Budh" ) ;
[Link] ( "Thu", "Guru" ) ;
[Link] ( "Fri", "Shukra" ) ;
[Link] ( "Sat", "Shani" ) ;

[Link] ( hm ) ;

String str ;
str = [Link] ( "Wed" ) ;
[Link] ( "Wed in hindi is " + str ) ;
}
}

The output of the program is shown below. Note that the get( ) function
can be used to obtain the value stored against the key passed to it.

{Thu=Guru, Tue=Mangal, Wed=Budh, Sat=Shani, Fri=Shukra, Sun=Ravi,


Mon=Som}
Wed in hindi is Budh

Using the Algorithms


There are many operations that we wish to perform on collections.
These include searching, sorting, finding minimum value, finding
maximum value, etc. In terminology of collections framework these are
called algorithms and are available for use in the form of static methods
of the Collections class. A smaller version of the same is also available in
the Arrays class. The program given below shows how to use these
algorithms from the Arrays class.

package arraysdemo ;
import [Link].* ;
public class ArraysDemo
{
public static void main ( String[ ] args )
{
int arr[ ] = new int[ 5 ] ;
Random r = new Random( ) ;

for ( int i = 0 ; i < [Link] ; i++ )


384 Let Us Java

{
arr[ i ] = [Link] ( 25 ) ;
[Link] ( arr[ i ] ) ;
}
[Link] ( arr ) ;
[Link] ( "After sorting: " ) ;
for ( int i = 0 ; i < [Link] ; i++ )
[Link] ( arr[ i ] ) ;

[Link] ( arr, 2, 4, -3 ) ;
[Link] ( "After filling: " ) ;
for ( int i = 0 ; i < [Link] ; i++ )
[Link] ( arr[ i ] ) ;

int pos ;
pos = [Link] ( arr, -3 ) ;
[Link] ( "pos = " + pos ) ;
}
}

Here is the output of the program.

15
13
13
2
18
After sorting:
2
13
13
15
18
After filling:
2
13
-3
-3
18
pos = 2
Chapter 19: Java Collections 385
The program generates random numbers using nextInt( ) function of
Random class and then populates the array arr with these randomly
generated integers. Next, it calls the sort( ) function to sort these
numbers.
The call to fill( ) function fills the array with -3 starting from 2 nd position
up to and excluding the 4th position. Then the program uses the
binarySearch( ) function to search the position of first occurrence of -3
in the array.
I hope now you have got a fair idea of how to use the Java collections
framework. You can explore the other collection classes, interfaces and
algorithms of the framework on your own.

[A] State True or False:

(a) Java collections framework provides common algorithms through


static functions of Collections class.

(b) The Java collection framework is based on Generics.

(c) Key - value pairs can be maintained using ArrayList class.

(d) In a hashmap order of insertion and order of access are same.

(e) ArrayList class can grow and shrink an array dynamically.

(f) Elements of a linked list are stored in adjacent memory locations.

(g) Stack is a FIFO list.

(h) All binary trees are maintained by TreeSet class as binary search
trees.

(i) It is possible to maintain elements of ArrayList in sorted order.

[B] Answer the following:


386 Let Us Java

(c) Write a program that maintains a hash map of 10 cell numbers as


keys and the name of the person and his email address as values.

[B] Pick up the correct alternative for each of the following questions:

(a) Which of the following is the CORRECT import statement for using
classes in Java collection framework?
(1) import [Link].*
(2) import [Link].*
(3) import java.*
(4) import [Link].*

(b) Java collections maintain data in the form of


(1) int
(2) float
(3) double
(4) Any reference type

(c) Consider the following code snippet:

ArrayList < int > num = new ArrayList < > ( ) ;


[Link] ( 10 ) ;
[Link] ( 20 ) ;

What change should be made to make the above code to work?


(1) Replace ArrayList with Vector
(2) Replace ArrayList with LinkedList
(3) Replace int with Integer
(4) The code will work perfectly

(d) Consider the following code snippet:

ArrayList < Integer > num = new ArrayList < Integer > ( ) ;
[Link] ( 10 ) ;
[Link] ( 20 ) ;
[Link] ( 30 ) ;
[Link] ( 40 ) ;
Integer arr [ ] = new Integer[ [Link]( ) ] ;
// add statement here
for ( int n: arr )
[Link] ( n ) ;
Chapter 19: Java Collections 387
Which statement will you add for the code to work?

(1) arr = [Link] ( arr ) ;


(2) arr = num ;
(3) arr = [Link] ( arr ) ;
(4) arr = convert ( arr ) ;

(e) Which of the following is NOT an interface in the Java Collection


framework?
(1) TreeSet
(2) Set
(3) SortedSet
(4) NavigableSet

To store, retrieve and manipulate multiple numbers / strings arrays


can be used

Arrays suffer from 2 limitations :


- They have no mechanism to maintain data in different ways like
Key -Value maps, Dictionary, etc.
- Arrays have no means to access data in FIFO, LIFO, Sorted order,
etc.
Instead of arrays we should use ready-made library called Java
Collection Framework

Advantages of using Java Collection f/w


- Very efficient, time tested, written by experts
- Readymade classes for most data structures, so we can
concentrate on program rather than building data structures
- It is possible to extend the collection classes to suit our needs
Collection framework contains :
- Collection classes - ArrayList, LinkedList, TreeSet,
PriorityQueue, HashMap, etc.
388 Let Us Java

- Interfaces - Collection, List, Set, SortedSet, NavigableSet,


Queue, DeQueue, etc
- Algorithms fill( ), max( ), min( ), reverse( ), shuffle( ),
binarySearch( ), sort( ), etc.
Algorithms are static methods of Arrays class

All collection classes are implemented as Generics, hence can work


only with reference types

Vector class and ArrayList class both can maintain arrays that grow
dynamically

Vector is synchronized class, so slow. ArrayList is not synchronized,


so fast

For a Vector class :


- capacity indicates how many elements can be stored in the vector
- size indicates number of elements present in it
- grow size indicates by how much would the capacity increase,
when we store an element once the capacity is full
Vector / ArrayList should be used if we are to store and process their
elements sequentially

LinkList should be used if frequent insertions / deletions of elements


is required

Rule for inserting elements in a Binary Search Tree (BST)- Greater


to Right, Smaller to Left of Root

The sequence of visiting nodes in BST in Inorder traversal Left,


Root, Right

When elements are accessed using Inorder Traversal, they get


accessed in ascending order

The order in which we insert entries into a HashMap and the order in
which they are stored may be different
Text is gone! Graphics is the way forward. Learn how to build
Graphical User Interfaces in Java...

389
390 Let Us Java

A Simple Swing Application


Event Handling
One More GUI Application
Adapter Classes
What Next?
Exercises
KanNotes
Chapter 20: User Interfaces 391

I -centric world it is expected that Java programs would let


a program interact with the user using GUI elements like text boxes,
list boxes, combo boxes, push button, radio buttons, check boxes, scroll
bars, etc. To facilitate this interaction Java provides three libraries
Active Window toolkit (AWT), Swing and JavaFX. Of these, AWT is the
older library. Moreover, the world has now moved over to either Swing
or JavaFX library. In fact Swing internally uses AWT. In that sense Swing
is built on top of AWT. In this chapter we would see how to build simple
GUI based applications using Swing library.

A Simple Swing Application


In this application the goal is to create and display a window shown in
Figure 20.1. As you can see, this window has two labels, two text fields
and a button. On entering the temperature in the text field for
Centigrade degrees and clicking the Convert button, the program should
do the conversion of temperature into Fahrenheit degrees and display
this temperature in the second text field.

Text Field

Label

Button Panel
Figure 20.1
Given below are the steps that we should carry out to create this
application using NetBeans.
Step I Create a Java Application, give Project Name as GUIApp. Choose a
suitable location on your disk for creating the files of this application.
Uncheck the check box.
392 Let Us Java

Step II To create the window for the application, add new JFrame form to
the application. For this right click on the GUIApp project in the project
On doing so, it
will ask you to supply the name of the class to represent the window. Type
ConvertTemp
Step III At the end of step II a window would appear in NetBeans. Now
we need to insert Container (Panel) and Controls (Labels, Text fields,
Button) in this window. Drag and drop them from the Swing Containers
and Controls window that appears besides the frame window.
Step IV roperty of the two label controls and

indow by typing the new values.


Step V Change names of the two text fields and the button to txtTempC,
txtTempF and btnConvert respectively. This can be done by right

Step VI Add Button handler - Select the Convert button, Go to Events


Window (another tab in the Properties ouble click the
event actionPerformed. Give the name of the handler as
btnConvertActionPerformed( ).
Step VII Add the following code in the handler created in Step VI
above.

private void btnConvertActionPerformed ( [Link]


evt )
{
String str ;
float f, c ;

str = [Link]( ) ;
c = [Link] ( str ) ;
f = c * 9 / 5 + 32 ;
str = [Link] ( f ) ;
[Link] ( str ) ;
}

Step VIII Compile and execute the program using F6. On execution the
window with the container and controls we had inserted would appear.
Chapter 20: User Interfaces 393
On providing the temperature in Centigrade and clicking the Convert
button the temperature in Fahrenheit would get displayed.
So much about creating our first GUI application using Swing library. Let
us now understand what we did in this application. Given below is the
source code that the wizard has created for us as we were creating the
application.

package converttemp ;
public class ConvertTemp extends [Link]
{
private [Link] jPanel1 ;
private [Link] jLabel1 ;
private [Link] jLabel2 ;
private [Link] txtTempC ;
private [Link] txtTempF ;
private [Link] btnConvert ;

public ConvertTemp( )
{
initComponents( ) ;
}

public static void main ( String args[ ] )


{
/* code to create and display the form */
}
}

When we added a JFrame form to our application and gave a name


ConvertTemp to it, a class of this name, inherited from the Swing class
JFrame, got inserted in our application. You can observe this inheritance
from the code given above and also note that main( ) is now present in
this class.
For every container and control that we can drag and drop in the
window there is a Swing class available. For example, for a panel there is
a class called JPanel, for a button JButton and for a text field JTextField.
These classes are defined in the package [Link]. So when we
dragged and dropped them into the window and gave names to them,
private variables by these names got created in the ConvertTemp class.
394 Let Us Java

But somewhere the objects of JPanel, JButton, JTextField, etc. also need
to be created. Well, that is what is done in the initComponents( )
function that has been called from the ConvertTemp
fact if you take a look at this function you would see apart from creation
of these objects, properties of these objects being setup. These include
position, size, color, etc. You can also observe statements to add all
these controls to the window. You are best advised not to edit the code
in initComponents( ) directly.
The wizard would add the code to create and display the window in
main( ). When the window is created, an object of ConvertTemp would
be created. This would result into call to its constructor and in turn to
initComponents( ).
One question that must be troubling you what is the difference
between a container and a control? A control is something that the user
interacts with, like a push button, a check box or a combo box. As the
name suggests, a container is something that would hold these visual
controls.
Now that we have understood the code to create the window, container
and controls, let us now turn our attention to a phenomenon called
event handling.

Event Handling
In simplest words an event is a thing that takes place. Programmatically
it means change in the state of an object. Events occur all the time when
we are interacting with a GUI application. For example, when we enter a
character from keyboard, or move the mouse, or click the left mouse
button, events occur. These events are generated as a consequence of
interaction with the graphical components in the GUI. Such events are
known as Foreground events.
Apart from these, events also occur without any user interaction. For
example, expiry of a timer, completion of some ongoing task,
occurrence of an interrupt, etc. Such events are known as Background
Events.
When an event occurs, the program is supposed to react to that event.
That reaction is known as event handling. Programmatically, a function
known as event handler gets executed when an event occurs. To ensure
that all events are handled in a standard manner, Java uses a
Chapter 20: User Interfaces 395
mechanism called Event Delegation Model to handle the events. This
model involves two key players:

(a) Source For


example objects of JButton, JTextField, JComboBox are all sources.
These sources provide information of the occurred event to their
respective handlers.
(b) Listener listens to (i.e. it waits for) an event to occur.
When an event occurs, the listener processes the event.
Programmatically, listener is an interface containing prototypes of
functions. For example, the MouseListener interface contains
prototypes of functions like mouseClicked(), mousePressed( ),
mouseReleased( ), etc.

The events themselves are represented using readymade classes like


MouseEvent, KeyEvent, ActionEvent, etc. When an event occurs, event
objects are created and passed to the listener functions (defined in a
class that implements the listener interface) to tackle the event.
Different applications would react to occurrence of same event
differently. For example, on clicking a mouse one application may print a
page on the printer, whereas, another application may draw a circle in
the window. Hence, in both applications, different functions would have
to be written for the same mouse event. These functions are nothing
but the implementations of the functions declared in the MouseListener
interface.
Let us understand this inter-play of multiple classes, objects and
interfaces with reference to our temperature converter application. We
did two specific things in this application. These are as follows:

(a) We dragged and dropped the button in our window and gave it a
name btnConvert.
(b) For the Convert button, for the actionPerformed event, we added
an event handler function. We called this function
btnConvertActionPerformed( ).

As a result of step (a) above, a private variable btnConvert of the type


JButton got declared in the ConvertTemp class. An object of JButton
class got created in initComponents( ) and its address got stored in
btnConvert.
396 Let Us Java

When we performed step (b) above, a call to the function


addActionListener( ) got added in initComponents( ). This call is made
using btnConvert. This call ties the ActionListener interface with the
Convert button. ActionListener interface has the following method
declaration in it:

void actionPerformed ( ActionEvent e ) ;

In initComponents( ) this method is implemented in a class (often called


anonymous class). Object of this class is passed to the
addActionListener( ) method.
When we click the Convert button, an actionPerformed event occurs.
Information about this event is packed in an ActionEvent object. This
object is then passed to the actionPerformed( ) method of the
anonymous class. From this method our event handler the function
btnConvertActionPerformed( ) gets called. In this method we do the
temperature conversion and display the result in the text field.
It is said that for event handling Java uses Event Delegation model. This
means that the responsibility of event handling is delegated (assigned)
to listeners. As a result, the logic that displays the controls and
generates the events remains completely separated from the logic that
reacts to these events.
In this model, the listener needs to be registered with the source object
(button in our example), so that the listener can receive the event
notification. This way the event notifications are sent only to those
listeners who wish to receive them.

One More GUI Application


Now that we are familiar with creation of a GUI application and its
working, let us now create one more application to help you fix your
ideas. The window and the controls for this application are shown in
Figure 20.2.
Chapter 20: User Interfaces 397

Figure 20.2
As you can see in Figure 20.2, there are several labels, 4 text fields (for
Name, Age, Salary and Address), 1 list box (for Grade of employee), 2
radio buttons (for Sex of employee), 3 check boxes (for Hobbies of
employee) and 1 button (Show button) in the window. The user would
interact with different controls and either type or select the data values
for an employee. Once the Show button is clicked the typed or selected
values should be displayed in a message box as shown in Figure 20.3.

Figure 20.3
398 Let Us Java

To create this application, you should follow exactly the same steps that
were discussed while creating the first GUI application in the previous
section.
Regarding GUI in this application, one additional thing that you need to
do is manage the mutual exclusivity of the radio buttons for Male /
Female. To do this, first insert two radio buttons and then insert a
Button Group control. Change ButtonGroup property of both radio
buttons to have a value same as name of the Button Group control.
Once this is done, you can choose only one out of the two radio buttons
at a time.
Also, for Combo Box by default model property would have some
default values. Edit this property to add values Grade I, Grade II, Grade
III and Grade IV to it.
Once again add an event handler for the button for actionPerformed
event. Once created, add the following code in the event handler to
display the typed / selected values in a message box.

private void btnShowActionPerformed ([Link] evt )


{
String str,str1,str2 ;
String strName ;
String strAge ;
String strGrade ;
String strSalary ;
String strAddress ;
String strSex = "" ;
String strReading = "" ;
String strTravelling = "" ;
String strSports = "" ;

strName = [Link] ( ) ;
strAge = [Link]( ) ;
strSalary = [Link]( ) ;
strAddress = [Link]( ) ;
strGrade = [Link]( ) ;

if ( [Link]( ) )
strSex = [Link]( ) ;

if ( [Link]( ) )
Chapter 20: User Interfaces 399
strSex = [Link]( ) ;

if ( [Link]( ) )
strSports = [Link]( ) ;

if ( [Link]( ) )
strReading = [Link]( ) ;

if ( [Link]( ) )
strTravelling = [Link]( ) ;

str1 = strName + "\n" + strAge + "\n" + strSalary + "\n" +


strAddress + "\n" + strGrade + "\n" ;
str2 = strSex + "\n" + strSports + "\n" + strReading + "\n"+
strTravelling + "\n" ;
str = str1+str2 ;
[Link] ( null, str,"Employee Info",
JOptionPane.INFORMATION_MESSAGE ) ;
}

In this event handler we have extracted the values from the text fields
using calls to the getText( ) function. Which of the radio buttons and
check boxes have been selected is checked using the isSelected( )
function. The actual selections are again obtained using the getText( )
function. The grade selected from Combobox is collected using the
function getName( ).
All the strings extracted from these functions are concatenated, with
\
str is displayed using the static method ShowMessage( ) of the
JOptionPane class. The information icon is displayed using the enum
value INFORMATION_MESSAGE.

Adapter Classes
Suppose we wish to interact with mouse in our GUI application. For this
we need to add the MouseListener interface. If we do this then all the
methods in the MouseListener interface need to be implemented in our
class. Problem is that MouseListener has five methods in it. These are as
follows:

public void mouseClicked ( MouseEvent e ) ;


400 Let Us Java

public void mousePressed ( MouseEvent e ) ;


public void mouseReleased ( MouseEvent e ) ;
public void mouseEntered ( MouseEvent e ) ;
public void mouseExited ( MouseEvent e ) ;

Suppose we wish to react only to the MouseClicked event; we still have


to implement all the methods of the interface. So only the
mouseClicked( ) function would have some meaningful code, whereas
the rest of them would have empty body. Two such functions are shown
below.

public void mousePressed ( MouseEvent e )


{
}

public void mouseReleased ( MouseEvent e )


{
}

Providing such empty-bodied function becomes tedious when the


interface has a large number of functions. To avoid this unnecessary
work Java provides Adapter Classes, one per interface. Thus, for
MouseListener interface there would be an equivalent adapter class
known as MouseAdapter. This class would contain five empty-bodied
functions. Now all that we need to do is, inherit our class from this
adapter class and override only the mouseClicked( ) function. Smart
work, you would agree!

What Next?
There are many controls and interfaces in Java swing API. The intention
of this chapter was to introduce you to some of them and discuss the
basic philosophy behind creating modern GUI and handling events. The
Swing library is very exhaustive and covering all classes in it would need
a separate book. Nevertheless, through this chapter you got introduced
to the Swing API and its working. Rest you are free to explore on your
own.
Chapter 20: User Interfaces 401

[A] State True or False:

(a) There is no difference between a container and a control.

(b) A control has to be in a container for it to become visible and


usable.

(c) For every control that can be inserted in a window there is a


readymade class available in Swing API.

(d) All Swing classes are defined in [Link] package.

(e) We can modify Adapter classes by adding new methods to them.

(f) For every event related interface available in Swing library there is
one equivalent adapter class.

(g) Methods in adapter classes are empty-bodied.

(h) We can avoid using Adapter classes by implementing all the


methods of an interface in our class.

(i) The Even Delegation model ensures that the code that creates
controls and events remains separate from the code that reacts to
events.

[B] Answer the following:

(a) Write a program that creates a window and displays a message

it.

(b) or a left click and

(c) Write a program that draws a line, rectangle and ellipse of suitable
402 Let Us Java

Three ways to provide input to a Java program :


- Console IO - Input from keyboard, Output to screen
- Command Line Arguments
- GUI elements like Text Fields, Buttons, Combo Boxes, Menu, etc.
GUI Libraries : AWT - Older way, Swing - Newer way

For every window and control there are Swing classes available

Event is a thing that takes place

Java uses Event Delegation model - Responsibility of event handling


is delegated (assigned) to Listeners

Programmatic elements involved in GUI - Sources, Events, Listeners,


Adapters

Sources are classes for controls. All classes are subclasses of


[Link]

To represent an event that a control may generate, many event


classes exist
- Ex. : Button, Menu - ActionEvent
- Ex. : Frame - WindowEvent
Event Listeners are Interfaces. Different listeners exist for different
controls
- Ex. : Button, TextField - ActionListener
- Ex. : Mouse - MouseListener, MouseMotionListener
Adapters Abstract classes. There is 1 abstract class per listener

Adapters contain empty body of all interface methods

Idea behind Adapters - Inherit and override only desired functions


World is full of data. You are in a commanding position if you
know how to deal with it in a professional manner...

403
404 Let Us Java

Data Organization
Common Database Operations
Database Operations through Java
JDBC Architecture
JDBC Driver Types
MySQL Database Installation
Common JDBC API Components
Putting it to Work
Exercises
KanNotes
Chapter 21: JDBC 405

D being generated and exchanged. All this data finally gets stored in a
database. As a Java programmer one must know how to handle this data
programmatically. To help us do this Java provides an API called JDBC. It
stands for Java Database Connectivity. This API lets us write Java
programs that can interact with a wide range of databases. How this can
be done is discussed in this chapter.

Data Organization
Modern way of organizing data is storing it in a Relational Database
Management System or RDBMS. Different vendors provide this RDBMS
software. These include Oracle, Microsoft, IBM, etc. There are several
open source implementations available as well, the most popular
amongst which is MySQL. All these RDBMSs are accessible through the
JDBC API.
Each of these RDBMS organizes the data in the form of different tables.
One database may contain multiple tables. Each table contains data
organized in the form of records (rows). Each record may contain
multiple fields (columns).
For example, a company may have a database containing Employees
table containing records about employees working in an organization.
Each record may contain fields like Name, Age, Salary, etc.
Likewise a University database may consist of tables for students,
professors, courses, examinations, payments, etc. It is also possible to
establish relationships between tables. For example, if a student pays
fees, then the record of fees paid can be linked to his record in the
student table. This would be a one-to-one relationship. If the same
student pays fees multiple times then it would become a one-to-many
relationship.

Common Database Operations


There is a set of typical operations that one needs to carry out on
database of any kind. These are as follows:

(a) Create Table - Create a table by specifying its name and the fields
that it would contain along with the type of each field.
(b) Modify Table - Modify the specifications of different fields, or add /
delete certain fields.
406 Let Us Java

(c) Drop Table - Delete the table from the database including all the
records present in it.

To carry out these operations a simple language has been created. It is


called SQL, standing for Structured Query Language. This language
provides simple English like statements to perform database operations.
SQL is supported by almost every RDBMS and it allows you to work with
a database independently of the underlying RDBMS.
Given below are some sample SQL statements for carrying out database
operations. The comments before each SQL statement would help you
understand the operation being performed by the SQL statement.

// Create a table called Persons containing two fields EmpID of the type
// int and Name of the type variable length string of 255 characters
CREATE TABLE Persons ( EmpID int, Name varchar ( 255 ) )

// Modify Persons table by adding a field DateOfBirth of the type date


ALTER TABLE Persons ADD DateOfBirth date

// Modify the Persons table by deleting the column DateOfBirth


ALTER TABLE Persons DROP COLUMN DateOfBirth

// Delete the Customers table


DROP TABLE Customers

SQL also provides statements that let you work with the records of each
table. Common operations on a table include Create new record(s),
Read existing record(s), Update existing record(s), Delete existing
record(s). In short these are known as CRUD operations. The SQL
statements that carry out these operations are often known as SQL
queries. Given below are some sample SQL statements for carrying out
CRUD operations.

// Insert a new record in Persons table, with values 101 and Sunil in the
// EmpID and Name respectively
INSERT INTO Persons ( EmpID, Name) VALUES ( 1001

// Read all records from Employees table


SELECT * FROM Employees

// Modify record whose Employee ID is 1001 by changing its Name field


// to hold a value Satish
Chapter 21: JDBC 407
EmpID = 1001

// Delete that record from the Persons table whose Employee ID is 1244
DELETE FROM Persons WHERE EmpID = 1244

Database Operations through Java


The operations mentioned in the previous section were performed using
SQL. Let us now see how these operations can be carried out through
Java. Creation, Modification and Deletion of a table are infrequent
operations. By this what I mean is Customers or Students table is not
going to get created, altered or deleted every other day. In fact once you
have set up all the fields in a table to your satisfaction, you would rarely
change it. More common operations would be the CRUD operations.
Hence usually the operation of creation of tables is done manually using
the tools that come with each RDBMS. For example, in this chapter we
propose to use MySQL RDBMS and perform these operations using the
MySQL WorkBench that comes with MySQL.
The CRUD operations can be performed using the JDBC objects called
Connection, Statement and ResultSet. The purpose of each of these
objects is mentioned below.
(a) Connection To establish connection with database
(b) Statement To execute SQL statements
(c) Resultset To process results of a SQL query
Before we can use these objects in our Java program we need to
understand the JDBC architecture and install a RDBMS. Our choice of
database would be MySQL, primarily because it is free of cost and quite
popular amongst open source community. The JDBC architecture and
MySQL installation are discussed in the following sections.

JDBC Architecture
To help programmers communicate with the database, vendors provide
vendor-specific JDBC driver software. For example, Oracle provides a
JDBC driver to help programmers communicate with databases
maintained by it. Likewise, Microsoft provides a JDBC driver to help
programmers communicate with databases maintained by MS SQL.
Java programmers must have a standard and uniform way to
communicate with any third-party JDBC driver. To facilitate this, an
408 Let Us Java

interface called Driver is declared in the [Link] package. The third-


party database vendors implement this interface in their driver.
To manage different JDBC drivers there is a component called Driver
Manager. For example, through a Java program when we attempt to
connect to a database, the Driver Manager would load the suitable JDBC
driver. Thus, JDBC Manager ensures correct driver usage to access each
database.
Once the driver is loaded we have to use the different classes present in
JDBC API to interact with the database.
The various layers of JDBC Architectures are shown in Figure 21.1.

Figure 21.1

JDBC Driver Types


Java implementations are available for a wide variety of Operating
Systems and hardware. These platforms themselves have evolved over
the years. There are different JDBC driver implementations for these
different platforms. All these drivers are classified into 4 categories
Chapter 21: JDBC 409
Type 1 driver, Type 2 driver, Type 3 driver and Type 4 driver. Most
legacy applications would use Type 1, 2, or 3 driver, whereas to connect
with modern databases Type 4 driver is used. For programs in this book
Type 4 driver would have to be installed.

MySQL Database Installation


We wish to install MySQL on a Windows machine. To do this we need to
first download the MySQL Installer. This is available for download at
[Link] Once downloaded,
execute this MySQL Installer. When presented with options to install
components, choose MySQL database and JDBC driver. At the time of
writing this book the JDBC driver was available in mysql-connector-java-
[Link].
Once the MySQL database and driver stand installed, download MySQL
Workbench for your version of Windows from URL given below and
install it.
[Link]
The Workbench provides an integrated tool for carrying out the
following operations:

(a) Database Design


(b) Trying SQL queries
(c) Database Administration
(d) Database Migration

In a later part of the chapter we would see how to use the MySQL
Workbench to create a database and its tables(s). We would also see
how to use the JDBC driver to work with the database programmatically.

Common JDBC API Components


The JDBC API provides different classes and interfaces. In a previous
section we had seen the purpose three classes Connection, Statement
and ResultSet. Apart from them, JDBC API also provides several other
classes and interfaces. The important amongst them are as follows:

(a) DriverManager: This class provides services for loading and


managing JDBC drivers.
(b) Driver: This is an interface. Each JDBC driver implements this
interface. It handles the communications with the database server.
410 Let Us Java

In a Java program we rarely interact with Driver directly. Instead,


we use DriverManager objects, which in turn manages the Driver
objects.
(c) SQLException: This class handles any errors that occur in a database
application.

Putting it to Work
We have now understood the data organization, SQL statements for
database operations, JDBC architecture and JDBC API components. We
have also seen how to install MySQL and MySQL Workbench. So it is
now time to write a Java program that accomplishes the following:

(a) Create a Schema study able Accounts


and add three fields to it ID, Name and Balance.
(b) Add 4 records to the table using MySQL Workbench containing
following data:
ID Name Balance
1011 Neha 4000.50
1023 Sunil 5000.00
1021 Rohit 6000.75
1044 Rahul 5600.55
(c) Create a record with field values 1001, Joe, 5000.00.
(d) Retrieve and print all existing records.
(e) Update record Change Sunil to Sanjay.
(f) Delete record whose ID is 1044.

Out of these, steps (a) and (b) are to be performed using MySQL
workbench, whereas the rest are to be performed through the Java
program.
So let us now create a schema, add table to it and then add 4 records to
it. Carry out the following steps to achieve this:

(a) Start MySQL workbench by double-clicking its icon. Create a new


schema (database) by selecting from the menu File | New Model.
By default a schema by the name mydb would get created. It would
Chapter 21: JDBC 411
(b) Double click on mydb schema. A dialog would popup. Through this
dialog change the Name
(c) ouble c

(d) Click on the Columns tab at the bottom of the page and create
three columns with following properties.

Column Name Datatype Primary Key


ID INT Yes
Name VARCHAR( 255 ) No
Balance FLOAT No

(e)
Name and Balance would be shown. Add 4 records with values
mentioned in the problem statement above.

Now finally we have reached a stage where we can write a Java program
to carry out steps (c), (d), (e) and (f) given in the problem statement.

package myjdbccrud ;
import [Link].* ;

public class MyJdbcCRUD


{
static final String jdbcDriver = "[Link]" ;
static final String dbURL = "jdbc:mysql://localhost/study" ;

public static void main ( String[ ] args ) throws Exception


{
Connection conn = null ;
Statement stmt = null ;
ResultSet rs = null ;

try
{
[Link] ( jdbcDriver ) ;
conn = [Link] ( dbURL,
"root", "admin" ) ;

stmt = [Link]( ) ;
412 Let Us Java

String sql ;
sql = "INSERT INTO Accounts VALUES ( 1001, 'Joe',
5000.0 )" ;
[Link] ( sql ) ;

sql = "UPDATE Accounts SET NAME = 'Sanjay'


WHERE ID = 1023" ;
[Link] ( sql ) ;

sql = "DELETE FROM Accounts WHERE ID = 1044" ;


[Link] ( sql ) ;

sql = "SELECT * FROM Accounts" ;


rs = [Link] ( sql ) ;

int id ;
String name ;
float balance ;

while ( [Link]( ) )
{
id = [Link] ( "ID" ) ;
name = [Link] ( "Name" ) ;
balance = [Link] ( "Balance" ) ;

[Link] ( id + " " + name + " " + balance ) ;


}

[Link]( ) ;
[Link]( ) ;
}
finally
{
if ( conn != null )
[Link]( ) ;
}
}
}

Let us now to try to understand the program. The project name given
was MyJdbcCrud, hence the classes in this program would belong to the
Chapter 21: JDBC 413
package myjdbccrud, as indicated in the package statement at the
beginning of the program.
The import statement ensures that the classes declared in [Link]
package for database access are available to the program.
Now we need to open a communication channel with the database. For
this we need to load and register the JDBC driver. This registration
needs to be done only once in the program. We have done this
registration through the call

[Link] ( jdbcDriver ) ;

where jdbcDriver is a string that has been initialized to


This call dynamically loads the driver's class file
into memory, which automatically registers it. Naturally if we use a
different RDBMS than MySQL then the driver name and hence the string
would change as given below.

ORACLE RDBMS - [Link]


DB2 RDBMS - [Link].DB2Driver

Now we need to open a connection with the database. This is done


using the statement

conn = [Link] ( dbURL, "root", "admin" ) ;

The getConnection( ) method needs three parameters the database


URL which indicates the name and location of the database, login name
and password to access the database. We have initialized the dbURL to
jdbc:mysql://localhost
Here localhost refers to the local machine and study refers to the
database name. If the database is present on a different machine, then
localhost should be replaced by IP address or name of the machine
where the database is hosted.
Once again for Oracle and DB2 the dbURL string would be different. For
these databases the following strings should be used:

Oracle RDBMS - jdbc:oracle:thin:@hostname:port


Number:databaseName
DB2 RDBMS - jdbc:db2:hostname:port Number/databaseName
414 Let Us Java

ame have been used in the call to


getConnection( ). This call creates a Connection object and returns it,
which we promptly collect in conn.
Once the connection with the database is established, we have
performed the CRUD operations. For this we have to create a Statement
object by calling createStatement( ) on the connection object. Next, we
have to create the query string and pass it to executeUpdate( ) method
of Statement object to execute the query. This sequence of operations
is shown below.

stmt = [Link]( ) ;
String sql ;
sql = "INSERT INTO Accounts VALUES ( 1001, 'Joe', 5000.0 )";
[Link] ( sql ) ;

Create, update and delete operations are similar in the sense that to
perform all of them the executeUpdate( ) method has to be called. The
Read operation is a bit different. For it we need to call the
executeQuery( ) method on the Statement object. When we do this, the
query is fired on the database and all the records that qualify the query
are returned in the form of a ResultSet object. For example, when we
ELECT Accounts
table would qualify this query and hence would be returned together in
a ResultSet object.
We can iterate through all the records in the ResultSet object through a
while loop. Each time through the loop we can extract the individual
field values in the record by calling the ResultSet methods as shown
below.

id = getInt ( "ID" ) ;
name = [Link] ( "Name" ) ;
balance = [Link] ( "Balance" ) ;

We have extracted the values and displayed them on the screen. Once
all the records have been iterated, [Link]( ) returns a false, whereupon
the loop is terminated.
That brings us to the final stage of the program where we need to do
the cleanup operations. We do this by calling the close( ) methods on
Statement, ResultSet and Connection objects.
Chapter 21: JDBC 415
One small thing needs to be done before you can execute the program.
We need to add the JDBC library. Carry out the following steps to do
this:

(a) ibrarie
project window.
(b)
(c) Navigate to the suitable directory where you have downloaded the
mysql-connector-java-5.1.40-bin
(d) Click Open followed by OK.

Once the library has been added we can now use F6 to build and
execute the program.

[A] State True or False:

(a) A database can contain multiple tables.

(b) MySQL is an open source RDBMS.

(c) Modern databases use T3 type of JDBC driver.

(d) Advantage of JDBC is that the same driver can be used to connect
multiple RDBMSs.

(e) A call to [Link]( ) loads and registers the JDBC driver.

(f) Records from a table can be deleted using call to executeQuery( )


method of Statement object.

(g) To read a set of records from a table we must use the


executeUpdate( ) method of the Statement object.

(h) Driver
416 Let Us Java

(j) A set of records is returned while reading a database table into a


RecordSet object.

[B] Answer the following:

(a) Write a program which lets you carry out the CRUD operations
through a GUI shown in Figure 21.2. Use the same database and
table discussed in t

Note that all the records added to the table should get displayed in
the list box. Before carrying out Delete or Update operations the
record should be searched using the ID. A new record should be
added or the existing record should be modified on clicking the
Commit button.

Figure 21.2

[C] Pick up the correct alternative for each of the following questions:

(a) What do CRUD operations stand for?


(1) CREATE, READ, UPDATE, DELETE
(2) CREATE, REMOVE, UPDATE, DROP
(3) CLEANUP, REMOVE, UPGRADE, DROP
(4) CLEANUP, RECTIFY, UPGRADE, DELETE
Chapter 21: JDBC 417
(b) Consider the following code snippet:
Connection conn ;
conn = [Link] ( dbURL, "root", "admin" ) ;
Which of the following is the CORRECT way to create a Statement
object?
(1) Statement stmt = [Link]( ) ;
(2) Statement stmt = createStatementObject( ) ;
(3) Statement stmt = new StatementObject( ) ;
(4) Statement stmt = [Link]( ) ;

(c) Which statement should be added to following code snippet to


insert a new record in Accounts table:
Statement stmt ;
Stmt = [Link]( ) ;
String sql = "INSERT INTO Accounts VALUES ( 1001, "Joe", 5000.0 )" ;
// add statement here
(1) [Link] ( sql ) ;
(2) [Link] ( sql ) ;
(3) [Link] ( sql ) ;
(4) [Link] ( sql ) ;

(d) Which of the following is the CORRECT way to make available


Statement, Connection and ResultSet objects?
(1) import Statement, Connection, ResultSet
(2) import Statement, Connection, ResultSet from SQL
(3) import [Link].*
(4) Import sql.*

Terminology :
- Field - Individual item of information
- Record - Collection of fields
- Table - Collection of records
- Database - Collection of tables
Different vendors provide RDBMS. Ex. : Oracle, MS SQL, MySQL
418 Let Us Java

All DB use SQL to carry out operations on a database or tables

SQL statements are often called Queries and are English like
statements

All RDBMS are accessible through Java API - JDBC. To these API
functions SQL queries have to be passed

Common database operations - Create / Modify / Drop Table

Examples of database operations :


- CREATE TABLE Persons ( ID int, Name varchar ( 255 ) )
- ALTER TABLE Persons ADD DateOfBirth date
- ALTER TABLE Persons DROP COLUMN DateOfBirth
- DROP TABLE Customers
These database operations are usually done using Tools that come
with each DB. Ex. : MySQL WorkBench that comes with MySQL

Common operations on Table CRUD (Create, Read, Update, Delete)

Examples of operations on a table :


- INSERT INTO
- SELECT * FROM Employees
-
- DELETE FROM Persons WHERE EmpID = 1244
These operations are done programmatically using JDBC objects

Common JDBC objects used are :


- Connection object establishes connection with database
- Statement object executes SQL statements
- Resultset object processes results of a query
Add library "mysql-connector-java-5.1.40-bin" before using JDBC
objects

Software Installations required - MySQL Installer and Workbench


Ability to do multiple things simultaneously is a great asset in
life. So also in programming...

419
420 Let Us Java

Networking Concepts
Networking Model
Protocols
Packets
IP Addresses
Sockets
Port Numbers

Communicating with Whois Server


Give Me the Home Page
Two-Way Communication
Multiuser Chat Application
File Transfer Using UDP
Exercises
KanNotes
Chapter 22: Network & Internet Programming 421

A ll successful people are usually well connected. It has become an


important ingredient for the

that
is where Network Programming is heading for. Hence learning network
programming has become more relevant today than ever before.
Often we need our application to write some data into a file stored on a
remote machine connected through the network, or exchange messages
across the machines connected to the network. Using the Java
networking API it has become as simple to carry out such jobs.

Networking Concepts
It is important to understand several concepts and terms before we can
actually start writing networking programs. Let us begin with a typical
computer network. Figure 22.1 shows a typical computer network.
We can make the following observations from Figure 22.1.
(a) PCs, Laptops, Mobile phones are client machines (also known as
nodes/hosts). They are connected to Hub/Switch through network
cables or wirelessly.
(b) Database Server, File Server, Print Server, Web Server, Application
Server are also connected to Hub/Switch.
(c) Clients and Servers form the Local Area Network (LAN). All clients
can get services from the servers.
(d) Gateway machine is connected to Hub/Switch and also to Router.
The router would be connected to other routers of other LANs or to
Internet. The routers route the data from one machine to another
along the least congested path.
(e) Gateway machine is so called because clients and servers in the LAN
can communicate with devices in other LANs or Internet through it.
(f) A Hub sends the incoming data packet to every node connected to
it. As against this, a Switch sends the incoming data packet only to
specified node.
(g) Access Point lets wireless devices to connect to LAN.
(h) Since all devices in Figure 22.1 are connected to a centralized
Hub/Switch the arrangement is known as Star topology. There are
422 Let Us Java

other topologies like Bus, Ring, Tree, Mesh each with its set of pros
and cons.

Figure 22.1

(i) All devices are connected to the network using a network adapter.
Most desktops and older laptops contain a Network Interface Card
(NIC) that acts as wired network adapter.
(j) Modern laptops, tablets and cell phones contain wireless network
adapters.
(k) Wireless networking capability can be added to a PC or old laptop by
attaching a wireless network adapter in its USB port.
(l) Some network adapters are actually just software packages that
Chapter 22: Network & Internet Programming 423
(m) Network adapters serve the purpose of transmitting and receiving
data on both, a wired and a wireless network.

Networking Model
In early days of networking PCs from same manufacturer could
communicate with one another. As networking became popular, a need
was felt to help vendors create interoperable network devices and
software. Typical issues involved in networking include how to create
packets, how to detect and correct errors, how to route packets from
one host to another, how to support multiple OS, how to deal with
heterogeneous network cabling, etc.
Towards this end in late 70's IOS defined a standard called Open
Systems Interconnection (OSI) reference model. OSI uses a 7-layered
network model, with each layer responsible for different aspects
(mentioned above) of network communication.
For Internet, the computing industry has combined some of the layers of
OSI model into a single layer. As a result, a 4-layer model called TCP/IP
model has emerged. This model is shown in Figure 22.2.

Figure 22.2
The purpose of each layer in brief is as follows:
(a) Application Layer - This layer provides services for user applications
for sending/receiving emails, web browsing, file transfer, audio
and/or video streaming, etc.
(b) Transport Layer (TCP layer) - This layer ensures that there is a
reliable channel for the application layer. This means that it ensures
424 Let Us Java

that whatever is sent from one end of the connection arrives at the
other end, without errors or omissions, and in the same order as
sent.
The transport layer may have to split the data into packets to give to
the IP layer. The TCP layer has to include sequence information in
the packets to allow it to re-assemble them in the correct order at
the far end, and to detect if a packet has gone missing. It also needs
to be able to resend a packet when this happens.
(c) Internet Layer (IP layer) - This
of data provided by the transport layer from source address to
destination address on the Internet.
(d) Network Interface Layer - This layer carries out actual transmission
of bits with implementations for a wide range of networks -
Ethernet, WiFi, optic fiber, etc.

Each layer receives services from layer below it and provides services to
the layer above it.
layer below it works. It merely uses the service provided to it. This
allows any layer to be swapped out for an alternative, and the layers
t care as long as the service provided by each
underlying layer is the same.
For example, one implementation of network interface layer may send
data over Ethernet, and another implementation handles sending the
data over a phone line. The Internet layer t need to know
anything about the network interface layer. The standard service
interface provided by the network interface layer, regardless of whether
Ethernet or a phone line is carrying the data, allows the Internet layer to
work in exactly the same way regardless. Thus, the layered model makes
the complexity of network communication more manageable.
Note that each layer feels that it is directly communicating with same
layer in another machine. As the data passes down a layer, a header and
trailer specific to that layer gets added to it. Similarly, when the data
reaches the other end and travels up the layers the headers and trailers
are stripped.

Protocols
Protocols are a set of rules that the network, computers and
applications agree upon to carry out communication between devices.
Chapter 22: Network & Internet Programming 425
The commonly used protocols in each layer of TCP/IP model are shown
in Figure 22.3.

Figure 22.3
There are many more protocols available in each layer than the ones
shown in Figure 22.3. All these protocols are implemented as a protocol
stack by the OS (Operating System) and its components.
The Ethernet protocol indicates how bits will be transmitted through
different physical media (network cables like CAT5, Fiber Optic, etc.) at
different speeds.
The IP protocol provides for transmitting blocks of data from source
machine to destination machine. Hosts are identified by a unique
address known as an IP address.
IP is a best effort protocol. It doesn't guarantee the correctness of the
delivered data. The packets may be lost, may get duplicated or may be
delivered out-of-order. These aspects of packet delivery are addressed
by transport layer protocols like TCP and UDP.
The protocols used in the Application layer are chosen based on what
the application intends to do. For example, for browsing Internet, the
HTTP protocol is used, for email SMTP and POP3 protocols are used.
Most of our programs in this chapter will use the protocols in
Application layer.

Packets
Traditional telecommunications links transmit data as a series of bytes,
characters, or bits alone. Unlike this, in a computer network data is
transmitted in the form of Packets. That's the reason why Internet is
often referred to as packet switched network. Once the data is
426 Let Us Java

formatted into a packet, the network can transmit longer messages


more efficiently and reliably.
A packet consists of three elements header, payload and trailer. As the
names suggest, header and trailer are used to mark the beginning of the
packet and end of the packet, whereas payload contains the actual data

IP Addresses
To be able to identify the devices in a network and carry out
communication between them using Internet Protocol (IP), each of them
has to be assigned a unique address. This address is called IP address.
There are two IP addressing schemes IPv4 and IPv6. An IPv4 address is 4
byte long, whereas an IPv6 address is 16 bytes long. The IPv4 addresses
are commonly written using 4 numbers (one number per byte) in a
dotted-decimal notation. In this notation, each byte in IP address is
separated using dot. One example of this notation is IP address
[Link].
To avoid miscommunication between machines in a network, their IP
addresses must be unique. This uniqueness can be achieved in case of
small networks, especially when these networks are not connected to
the outside world. However, to guarantee uniqueness of IP addresses in
big networks spanning cities and continents, the IP addresses are
created and managed by a central authority called Internet Assigned
Numbers Authority (IANA). IANA allocates super-blocks of addresses to
Regional Internet Registrars. These in turn allocate smaller blocks to
Internet Service Providers and enterprises, who in turn further allocate
the addresses to individual organizations who in turn assign them to
individual devices.

Sockets
Another term that is commonly used in network communication is
Socket. Socket is a software construct that identifies an end-point in a
communication channel. A socket is used by applications as an interface
to the underlying network and protocols. Applications that
communicate with one another in a network carry out the
communication using sockets. Java networking API provides classes for
creating sockets and sending / receiving packets through them.
Chapter 22: Network & Internet Programming 427

Port Numbers
It is common to send emails through your email application at the same
time as you download a file from a web site. Here, the email application
is communicating with an email server program residing on another
machine, whereas the web browser is communicating with a web server
program running on yet another machine. The IP address of the machine
on which the email application and the web browser is running is same.
In such a case, the data sent by the web server should not go to the
email application; similarly the data sent by the email server should not
go to the web browser. To avoid such situations the email application
and the web browser use sockets with different port numbers on the
same machine (IP address) for carrying out communication. These ports
are logical ports and not physical ports. They should not be confused
with HDMI or USB ports.
Email program and Web Browser are standard applications. Hence they
use standard port numbers. After all, you should not be required to
make a phone call to the place where the Web Server is present and ask
which port number it is using so that you can send a request to it for
downloading a file. IANA is responsible for assigning standard port
numbers. Port numbers used by applications that use some common
protocols are as follows:
HTTP - 80
SMTP - 25
POP3 - 110
FTP - 20, 21
Time - 37
Telnet - 23
Whois - 43
There is another important reason why the idea of port numbers was
created. The network link speed is usually so high that one application
would not be able to use the entire capacity of the connection by itself.
For example, when you visit a website and a page is downloaded in your
browser, unless you click a link and make a request for another page,
the network link is idle. Hence, to meaningfully utilize the capacity of the
network link, it becomes important to be able to share the same link for
multiple applications. This means multiple applications running on the
machine will use the same IP address of the machine, but different port
numbers.
428 Let Us Java

Figure 22.4 captures the essence of what we have discussed in the


above paragraphs.

Figure 22.4

Having had a reasonable introduction to network communication, let us


now write a program that obtains IP address and name of different

package addresses ;
import [Link] ;

public class Addresses


{
public static void main ( String[ ] args )
{
try
{
InetAddress ia = [Link]( ) ;
[Link] ( "Name and address: " + ia ) ;
[Link] ( "Address: " + [Link]( ) ) ;
[Link] ( "Name: " + [Link] ( ) ) ;
Chapter 22: Network & Internet Programming 429
ia = [Link] ( "[Link]" ) ;
[Link] ( "Name: " + [Link] ( ) ) ;
[Link] ( "Address: " + [Link] ( ) ) ;
[Link] ( "Reachable: " + [Link](3000));

ia = [Link] ( "[Link]" ) ;
[Link] ( "Name: " + [Link] ( ) ) ;
[Link] ( "Address: " + [Link] ( ) ) ;
[Link] ( "Reachable: " + [Link](3000));

InetAddress[ ] ias = [Link] (


"[Link]" ) ;
for ( int i = 0 ; i < [Link] ; i++ )
[Link] ( ias[ i ] ) ;

}
catch ( UnknownHostException ex )
{
[Link] ( ) ;
}
}
}

My name and address is KanetkarDell/[Link]


My address is [Link]
My name is KanetkarDell
Name: [Link]
Address: [Link]
Reachable: false
Name: [Link]
Address: [Link]
Reachable: false
[Link]/[Link]

Let us now try to understand the program.


The InetAddress class is used to encapsulate both the numerical IP
address and the domain name for that address. It can handle both IPv4
and IPv6 addresses.
430 Let Us Java

The InetAddress class does not have public constructors. So to create an


InetAddress object we have to use one of the factory methods. Factory
method is a static method in a class that creates an object and returns
its address. This is often a better alternative than providing overloaded
constructors, as having unique factory method names makes the usage
easier. Three commonly used InetAddress factory methods are
getLocalHost( ), getByName( ) and getAllByName( ).
The getLocalHost( ) method returns the InetAddress object that
represents the local host. The getByName( ) method returns an
InetAddress for a host name passed to it. On the Internet to achieve
scalability, often a single name is used to represent several machines.
The getAllByName( ) factory method returns an array of InetAddresses
that represent all of the addresses that a particular name resolves to.
As the name suggests, the isReachable( ) method tests whether the
address is reachable. At times the firewall and server configuration may
block the request resulting in an unreachable status. 3000 represents
the timeout value, in milliseconds. It indicates the maximum amount of
time the try should take. If the operation times out before getting an
answer, the host is deemed unreachable.

?
There are several time servers on Internet that maintain an accurate
measure of current time. We can write a client program to connect to
one of these servers and obtain the current date and time.

package javatimeclient ;
import [Link].* ;
import [Link].* ;
import [Link].* ;

public class JavaTimeClient


{
public static void main ( String[ ] args ) throws Exception
{
Socket s ;
String hostname = "[Link]" ;
int port = 37 ;
long secSince1970, msSince1970, secSince1900 ;
long diffBetEpochs = 2208988800L ;
Date time ;
Chapter 22: Network & Internet Programming 431

InputStream is = null ;
s = new Socket ( hostname, port ) ;
is = [Link]( ) ;

int i, ch ;
secSince1900 = 0 ;
for ( i = 0 ; i < 4 ; i++ )
{
ch = [Link]( ) ;
secSince1900 = ( secSince1900 << 8 ) | ch ;
}
secSince1970 = secSince1900 - diffBetEpochs ;
msSince1970 = secSince1970 * 1000 ;
time = new Date ( msSince1970 ) ;
[Link] ( "It is " + time + " at " + hostname ) ;
[Link]( ) ;
}
}

Given below is the output of the program.


It is Thu Nov 15 11:44:14 IST 2018 at [Link]
[Link] package provdies two classes for creating TCP sockets-
ServerSocket and Socket. The ServerSocket class is for servers, whereas
the Socket class is for clients. The ServerSocket class is designed to be a
'listener,' which waits for clients to connect before doing anything. The
Socket class is designed to connect to server sockets and initiate
protocol exchanges.
In this program we have used the time server "[Link]" which is
listening for an incoming client request at port number 37. When we
create the Socket object by calling its constructor, it establishes a
connection between our client program and the time server.
Next we gained an access to the input stream associated with the client
socket by calling the getInputStream( ) method. The time reported by
time server (as seconds since 1/1/1900) is then read a byte at a time and
a long int is constructed out of it.
The time protocol sets the epoch at 1/1/1900, whereas Java Date class
does it at 1/1/1970. Hence we have subtracted Subtract 70 years' worth
of seconds, i.e. 2208988800, from seconds since 1900. Then using the
432 Let Us Java

Date class we converted the milliseconds since 1970 into date time
format and printed it.

Communicating with Whois Server


Whois is a TCP-based request/response protocol using which we can
obtain information about the owner of a domain name, its IP address
and contact information for a particular site. Given below is a program
that obtains this information for the site kicit .

package javawhoisclient ;
import [Link].* ;
import [Link] ;

public class JavaWhoIsClient


{
public static void main ( String[] args ) throws Exception
{
Socket s = new Socket ( "[Link]", 43 ) ;
InputStream is = [Link]( ) ;
OutputStream os = [Link]( ) ;

String str = "[Link]" + "\n" ;


byte buf[ ] = [Link]( ) ;
[Link] ( buf ) ;

int c ;
while ( ( c = [Link]( ) ) != -1 )
[Link]( ( char ) c ) ;

[Link]( ) ;
}
}

On execution of this program it displays the following information:


Domain Name: [Link]
Registry Domain ID: 120408941_DOMAIN_COM-VRSN
Registrar WHOIS Server: [Link]
Registrar URL: [Link]
Updated Date: 2018-04-18T02:22:47Z
Creation Date: 2004-05-18T07:23:07Z
Registry Expiry Date: 2019-05-18T07:23:07Z
Chapter 22: Network & Internet Programming 433
Registrar: BigRock Solutions Limited
Registrar IANA ID: 1495
Registrar Abuse Contact Email: abuse-
contact@[Link]
Registrar Abuse Contact Phone: +1.2013775952
Domain Status: clientTransferProhibited
[Link]
Name Server: [Link]
Name Server: [Link]

In this program we have first constructed a Socket object using the


hostname "[Link]" and the port number 43, since InterNIC
server is listening for client requests at this port. Next, both input and
output streams associated with the socket are obtained. Then, a string is
constructed that contains the name of the web site ([Link]) we wish
to obtain information about. This string is converted into a byte array
which is then sent to the InterNIC server through the socket. The
response sent by the InterNIC server is then read byte by byte and
displayed on the screen. Finally, the socket is closed, which also closes
the I/O streams.

Give Me the Home Page


Whenever we type a request in the browser to visit a site our request
goes to the web server where the site is hosted. On receiving the
request the web server software responds to that request by sending
the home page of that site in the form of HTML. This request is a GET
request made using a protocol called HTTP (Hyper Text Transfer
Protocol). If we want, we too can make a HTTP GET request from our
program. Instead of displaying the HTML response in a web browser we
would simply display it on the screen. The following program shows how
this can be achieved.

package javhttpclient ;
import [Link].* ;
import [Link].* ;
import [Link].* ;

public class JavHTTPClient


{
public static void main ( String[ ] args ) throws Exception
434 Let Us Java

{
URL url = new URL ( "[Link] ) ;
URLConnection urlConnection = [Link]( ) ;
InputStream is = [Link]( ) ;

int c ;
while ( ( c = [Link]( ) ) != -1 )
[Link] ( ( char ) c ) ;
[Link]( ) ;
}
}

Given below is the truncated output of the program.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"


"[Link]
<html xmlns="[Link] xml:lang="en"
lang="en" dir="ltr">

<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"
/>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"
/>

Rather than using the raw Socket class to create socket and then send a
GET request, we have used the more specialized class
HttpURLConnection. Using this class we can conveniently connect to a
site on the HTTP web server, make a request, and access the response
headers and the response message.

Two-Way Communication
So far we have written only client programs which communicated with
already existing server programs. The sockets that we created in all
these client programs were stream sockets. Through these sockets the
client could establish a connection with the server and then carry out
communication. While the connection is in place, data flows between
the processes in continuous streams. Hence such sockets are known as
stream sockets. These sockets are said to provide a connection-oriented
service. The protocol used for transmission is Transmission Control
Protocol (TCP).
Chapter 22: Network & Internet Programming 435
There is one more type of socket. It is known as datagram socket. It is
used to transmit individual packets of information. The protocol used is
User Datagram Protocol (UDP). Datagram sockets offer a connectionless
service. Hence the packets sent using these sockets may arrive in any
sequence or may even be lost or duplicated.
UDP is appropriate for network applications that do not require the
error checking and reliability in packet transmission. Stream sockets and
the TCP protocol is more commonly used for majority of Java
networking applications.
Let us now try to create a single user chat application. This application
would have two programs a server and a client. Once created, they
would be able to carry out two-way communication between them.
Let us begin with the server first. Here is the program for it.

// Single User Chat Server Program


package javasingleuserchatserver ;
import [Link].* ;
import [Link].* ;
import [Link].* ;

public class JavaSingleUserChatServer


{
public static void main ( String[ ] args ) throws Exception
{
ServerSocket serSock = new ServerSocket ( 6001 ) ;
[Link] ( "Waiting for connection " ) ;
Socket comSock = [Link]( ) ;
[Link] ( "Connected to client" ) ;

DataInputStream dis ;
dis = new DataInputStream ( [Link]( ) ) ;
DataOutputStream dos ;
dos = new DataOutputStream ( [Link]( ) ) ;

String msgRecd, msgToSend ;

Scanner scanner = new Scanner ( [Link] ) ;


while ( true )
{
msgRecd = [Link]( ) ;
436 Let Us Java

[Link] ( "Recd. from client: " + msgRecd ) ;


if ( [Link] ( "quit" ) )
{
[Link]( ) ;
[Link]( ) ;
[Link]( ) ;
[Link]( ) ;
break ;
}

[Link] ( "Enter text: " ) ;


msgToSend = [Link]( ) ;
[Link] ( msgToSend ) ;
}
}
}

In all the client programs in this chapter we used to create one socket
and then use it to connect to a specific server at a specific port. Once
connected, through the same socket we used to communicate with the
server. In the server program there is a major change. In this program
we have to create two sockets a listening socket and a communication
socket. Using the listening socket the server would wait for a connection
request from the client. Once this request is received, the
communication is carried out with the client using the communication
socket.
The listening socket is created using ServerSocket class. The constructor
of this class uses server's IP address and the port number passed to it to
create a socket. We have chosen the port number as 6001. There is
nothing special about this number. You are free to choose any other
suitable number.
Using the listening socket accept( ) function is called. This function is a
blocking function. This means that the control would not return from
this function unless a connection request comes from the client. As
soon as the client connection request arrives, the accept( ) function
accepts the connection request, creates a new socket object for
communication and returns it into comSock. Once this communication
socket is created, communication is carried out with the client using the
input and output streams associated with the socket.
Chapter 22: Network & Internet Programming 437
The idea behind using a different socket for communication is to let the
server wait for other clients' connection request in a multithreaded
server. This concept is demonstrated in the next section.
References to communication socket's input/output streams are
obtained by calling methods getOutputStream( ) and getInputStream( ).
Using these references DataOutputStream and DataInputStream
objects are created. These objects are then used to send or receive
individual messages by calling writeUTF( ) and readUTF( ) methods.
When server receives a message "quit" message the socket and the
associated streams are closed.
Now that the server program is ready, let us take a look at the client
program. This is shown below.

// Single User Chat Client Program


package javasingleuserchatclient ;
import [Link].* ;
import [Link].* ;
import [Link].* ;

public class JavaSingleuserChatClient


{
public static void main ( String[ ] args ) throws Exception
{
[Link] ( "Connecting to server..." ) ;
InetAddress localAddress = [Link]( ) ;
Socket cliSocket = new Socket ( localAddress, 6001 ) ;

DataInputStream dis ;
dis = new DataInputStream ( [Link]( ) ) ;
DataOutputStream dos ;
dos = new DataOutputStream ( [Link]( ) ) ;

[Link] ( "Connected to server" ) ;


Scanner scanner = new Scanner ( [Link] ) ;
String msgToSend, msgRecd ;

while ( true )
{
[Link] ( "Enter text: " ) ;
msgToSend = [Link]( ) ;
438 Let Us Java

[Link] ( msgToSend ) ;
if ( [Link] ( "quit" ) )
{
[Link]( ) ;
[Link]( ) ;
[Link]( ) ;
break ;
}
msgRecd = [Link]( ) ;
[Link] ( "Server response: " + msgRecd ) ;
}
}
}

For sake of convenience we plan to run server and client on the same
machine. Hence while creating the client socket we are using the local
machine's IP address as the IP address of the server. The client program
makes a connection request to server at port number 6001.
Once the connection is established, it just sends a message to the
server. When the server responds to this message, the client collects it
and displays it on the screen.

Multiuser Chat Application


In this application many users can connect to a server. Once connected,
any client should be able to communicate with any other connected
client. To ensure that communication between one pair of clients does
not get mixed up with communication of another pair three things are
done. These are

(a) Server maintains a list of its active clients in a vector. When a new
client connects to the server, this vector would be updated.
(b) Communication between any pair of clients happens in a separate
thread.
(c) All messages sent by a client are prepended with the client id for
whom it is meant. So if client 2 wishes to communicate with client 7
then he should send messages in the following format:
client 7 # Hello, how are you doing?
client 7 # Can we meet sometime next week?
Chapter 22: Network & Internet Programming 439

package javamultiuserchatserver ;
import [Link].* ;
import [Link].* ;
import [Link].* ;

public class JavaMultiUserChatServer


{
static Vector<ClientThread> v = new Vector< >( ) ;
static int i = 0 ;

public static void main ( String[ ] args ) throws Exception


{
ServerSocket serSock = new ServerSocket ( 1234 ) ;
Socket comSock ;

while ( true )
{
comSock = [Link]( ) ;
[Link] ( "New client req recd: " + comSock ) ;
DataInputStream dis ;
dis = new DataInputStream ( [Link]( ) ) ;
DataOutputStream dos ;
dos = new DataOutputStream (
[Link]( ) ) ;
[Link] ( "Starting new clien thread..." ) ;
ClientThread t ;
t = new ClientThread ( comSock, "Client" + i, dis, dos ) ;
[Link] ( t ) ;
[Link]( ) ;
i++ ;
}
}
}

class ClientThread extends Thread


{
Scanner scn = new Scanner ( [Link] ) ;
private String name ;
final DataInputStream dis ;
440 Let Us Java

final DataOutputStream dos ;


Socket s ;
boolean isloggedin ;

public ClientThread ( Socket s, String name, DataInputStream dis,


DataOutputStream dos )
{
[Link] = dis ;
[Link] = dos ;
[Link] = name ;
this.s = s ;
[Link]=true ;
}

public void run( )


{
String msgRecd ;
while ( true )
{
try
{
msgRecd = [Link]( ) ;
[Link] ( msgRecd ) ;
if ( [Link] ( "quit" ) )
{
isloggedin=false ;
[Link]( ) ;
[Link]( ) ;
[Link]( ) ;
break ;
}

// find out intended recipient


StringTokenizer tok ;
tok = new StringTokenizer ( msgRecd, "#" ) ;
String msgToSend = [Link]( ) ;
String recipient = [Link]( ) ;

for ( ClientThread ch : JavaMultiUserChatServer.v )


{
if ( [Link] ( recipient ) &&
Chapter 22: Network & Internet Programming 441
[Link] == true )
{
[Link]( name + " : " + msgToSend);
break ;
}
}
}
catch ( IOException e )
{
[Link]( ) ;
}
}
try
{
[Link]( ) ;
[Link]( ) ;
}
catch ( IOException e )
{
[Link]( ) ;
}
}
}

Note that when a new client request comes a new thread is launched for
by calling the start( ) method of Thread class. The actual communication
between two clients happens in the run( ) method. Since we don't call
the run( ) method explicitly, all variables that it needs are passed and
preserved in private variables through the constructor of ClientThread
class.
Let us now turn our attention to the client program. I would first present
the code.
package javamultiuserchatclient ;
import [Link].* ;
import [Link].* ;
import [Link] ;

public class JavaMultiUserChatClient


{
public static void main ( String[ ] args ) throws Exception
{
442 Let Us Java

InetAddress ip = [Link]( ) ;
Socket s = new Socket ( ip, 1234 ) ;
DataInputStream dis ;
dis = new DataInputStream ( [Link]( ) ) ;
DataOutputStream dos ;
dos = new DataOutputStream ( [Link]( ) ) ;

Thread sendth = new SendThread ( dos ) ;


Thread recvth = new RecvThread ( dis ) ;
[Link]( ) ;
[Link]( ) ;
}
}

class SendThread extends Thread


{
private DataOutputStream dos ;

SendThread ( DataOutputStream d )
{
dos = d ;
}
public void run( )
{
Scanner scn = new Scanner ( [Link] ) ;

while ( true )
{
String msgToSend = [Link]( ) ;
try
{
[Link] ( msgToSend ) ;
}
catch ( IOException e )
{
[Link]( ) ;
}
}
}
}
Chapter 22: Network & Internet Programming 443
class RecvThread extends Thread
{
private DataInputStream dis ;
RecvThread ( DataInputStream d )
{
dis = d ;
}
public void run( )
{
Scanner scn = new Scanner ( [Link] ) ;

while ( true )
{
try
{
String msgRecd = [Link]( ) ;
[Link] ( msgRecd ) ;
}
catch ( IOException e )
{
[Link]( ) ;
}
}
}
}

When the client program is executed it creates a socket to connect to


port 1234 of server. Please remember to replace ip with actual server
address if you are running server on a different machine. When client
(say client 8) connects to server it has to send a message in the format
client 4# Remember me?
This means that client 8 is sending a message to client 4.
To ensure that sending and receiving of messages happens independent
of one another, each activity is carried out in a separate thread.

File Transfer Using UDP


We have seen how to communicate between client and server using
stream-based sockets. Let us now try to send a file from client to server
using datagram sockets.
444 Let Us Java

The server program creates a datagram socket and calls the receive( )
function to receive a filename from the client. Once the filename is
received in a datagram packet the file by this name is created on the
server. Next the chunks received from client are written to this file. The
process ends when the string "END" is received from the client. Here is
the server progr

// UDP Server Program


package javaudpserver ;
import [Link].* ;
import [Link].* ;

public class JavaUDPServer


{
public static void main ( String[ ] args ) throws Exception
{
DatagramSocket serSocket = new DatagramSocket ( 5000 ) ;
byte[ ] data = new byte[ 1024 ] ;
DatagramPacket pkt ;
pkt = new DatagramPacket ( data, [Link] ) ;
[Link] ( pkt ) ;
String str = new String ( [Link]( ), 0, [Link]( ) ) ;
[Link] ( "Filename received: " + str ) ;

File f = new File ( str ) ;


FileWriter fw = new FileWriter ( f ) ;
BufferedWriter bufferedWriter = new BufferedWriter ( fw ) ;
while ( true )
{
pkt = new DatagramPacket ( data, [Link] ) ;
[Link] ( pkt ) ;
str = new String ( [Link]( ) , 0, [Link]( ) ) ) ;
if ( [Link]( ).equals ( "END" ) )
break ;
[Link] ( str ) ;
[Link]( ) ;
}

[Link] ( "File " + str + "created on server" ) ;


[Link]( ) ;
[Link]( ) ;
}
Chapter 22: Network & Internet Programming 445
}

Let us now look at the client program.

// UDP Client Program


package javasingleuserudpclient ;
import [Link].* ;
import [Link].* ;
import [Link].* ;

public class JavaSingleUserUDPClient


{
public static void main ( String[ ] args ) throws Exception
{
InetAddress ip ;
ip = [Link]( ) ;
DatagramSocket socket ;
socket = new DatagramSocket( ) ;

[Link] ( "Enter filename" ) ;


Scanner sc = new Scanner ( [Link] ) ;
String fname = [Link]( ) ;

byte[ ] data = [Link]( ) ;


DatagramPacket pkt ;
pkt = new DatagramPacket ( data, [Link], ip, 5000 ) ;
[Link] ( pkt ) ;

File f ;
f = new File ( fname ) ;
FileInputStream fis = new FileInputStream ( f ) ;

byte[ ] chunk = new byte[1024] ;


int chunkLen ;
while ( ( chunkLen = [Link] ( chunk ) ) != -1 )
{
if ( chunkLen != 0 )
pkt = new DatagramPacket ( chunk, [Link],
ip, 5000 ) ;
else
{
chunk = "END".getBytes( ) ;
446 Let Us Java

pkt = new DatagramPacket ( chunk, [Link],


ip, 5000 ) ;
}
[Link] ( pkt ) ;
}
[Link]( ) ;
[Link]( ) ;
}
}

The client program first receives the filename as input and sends it to
the server. It then sends chunks of this file to the server until its end is
reached. On reaching the end of file, it sends a string "END" to server as
a signal to stop the communication.

[A] State whether the following statements are True or False:


(a) Internet uses the 7 layer OSI model for network programming.

(b) To avoid conflict it is necessary that multiple applications running


on same machine must carry out communication at different port
numbers.
(c) accept( ) is a non-blocking function.

(d) HTTP protocol is used for accessing web pages from a site.

(e) Time servers always return the local standard time.

(f) Every working site on the Internet has a corresponding entry in the
whois database.
(g) IP protocol is responsible for reliable delivery of packets, detecting
errors in transmission and flow control.

[B] Attempt the following:


(a) Modify the single user chat program discussed in this chapter such
Chapter 22: Network & Internet Programming 447

[C] Match the following:

Connection oriented Access point


Connectionless Logical network adapter
Dotted decimal notation Star
Email Protocol TCP
Network layer protocol UDP
Topology SMTP
Wireless devices Port 80
Loopback IP
UDP Stream sockets
HTTP Port 37
Time Datagram sockets
TCP IPv4 addresses
Communication end point IP address + Port number

[D] Attempt the following:


(c) Modify the single user chat program discussed in this chapter such
that the server simply echoes back the message that it receives
from the client.
(d) Modify the multi user chat program to carry out chat in a swing
based GUI application for server as well as client.

Usually nodes in LAN are connected to a centralized Hub/Switch in a


star topology

All devices are connected to the network using a network adapter

Gateway machine is connected to Hub/Switch and also to Router

A Hub sends the incoming data packet to every node connected to it

A Switch sends the incoming data packet only to specified node

Access Point lets wireless devices to connect to LAN

Wireless devices are connected to an Access Point


448 Let Us Java

Network adapters transmit and receive data on wired and a wireless


network

Network communication is done using a 4-layered TCP/IP model

4 layers - Application, Transport, Internet, Network Interface

Different protocols are used in different layers

IP4 addresses are written in a dotted decimal notation

Socket forms a communication end point

Different application communicate using different port numbers to


avoid conflict during communication

Java provides several classes for network programming in [Link]


package

TCP - Connection-oriented service, UDP - Connectionless service

Stream sockets are used for TCP-based communication

Datagram sockets are used for UDP-based communication


4
450 Let Us Java

CLASSPATH Variable
Strictfp Modifier
Packages
Creating and Using a Package
Split Packages
Different Packages, Same Type
Nested Packages
Package FAQs
Packages and Access Mechanism
Bitwise Operators
KanNotes
Chapter 23: Miscellany 451

T he topics discussed in this chapter were either too large or far too
removed from the mainstream Java programming for inclusion in the
earlier chapters. These topics provide certain useful programming
features, and could prove to be of immense help in certain programming
strategies. These include CLASSPATH variable, strictfp modifier,
packages and bitwise operators. Let us understand them one by one.

CLASSPATH Variable
Our Java program may use types stored in other .class files. CLASSPATH
is a mechanism that helps Java runtime environment locate the other
.class files. It is an environment variable and it contains a list of
directories that contain third-party and user-defined types.
CLASSPATH variable is different than the PATH environment variable.
PATH is used by Operating System to locate executable files, whereas
CLASSPATH is used to locate the .class files. The default value of
CLASSPATH is . . This means by default the search for .class files is
carried out only in current directory or its sub-directories.
In Windows the CLASSPATH variable can be set permanently through
Control Panel or at command prompt. Given below is an example of
setting it at command prompt.
set CLASSPATH=%CLASSPATH%;.;C:\ProgramFiles\Java\mylib
Here %CLASSPATH% gives the existing value of CLASSPATH variable. We
have two directories in the list, . and C:\ProgramFiles\Java\mylib
separated by a semicolon (;). The .class files would be first searched in
current directory. If not, found they would be searched in mylib
directory.
If we wish to set the CLASSPATH value temporarily, we can do so as
shown in the following example:

java -classpath .;c:\ProgramFiles\Java\mylib [Link]

If executed under Linux remember to replace \ and ; with / and :


respectively.

strictfp Modifier
Floating-point calculations are platform-dependent. So, the same
floating-point operation may give different results when the same class
file is executed on different platforms. This happens because floating
452 Let Us Java

point precision may vary from one platform to another. It can be


mitigated using the strictfp keyword.
As the names suggests, the strictfp modifier stands for strict floating-
point operations. It ensures that we get the same result on every
platform while performing float operations. strictfp can be applied to a
class, a method or an interface, but not to abstract method, variable or
on constructor.

Packages
A reasonably big Java software would contain many classes,
interfaces, enumerations and annotations. Java helps you organize
them properly by storing related classes, interfaces, enumerations
and annotations in a logical container called Package. This
organization is helpful in three ways:

(a) Packages makes it easy to locate and use types (i.e., classes,
interfaces, enumerations and annotations).

(b) Two different packages may contain types with same names. So, if a
library package contains a type called class Student and we also
define a type called class Student, so long as they belong to two
different packages, we can use both. Thus, packages help avoid
naming conflict.

(c) Through packages we can control which type within it can be


accessed from outside the package.

To enforce a good design practice Java follows certain rules about


packages and directory structure. These are as follows:

(a) A new folder is created for every new package. Moreover, package
name and folder name are always same.

(b) A .java file can contain only one public type. Its name is same as the
name of the .java file.

Creating and Using a Package


Let us now see how to create our own package and use it. Here are
the specifications of the package.
Package name: sample
Filename: [Link]
Chapter 23: Miscellany 453
Class name: Sample containing a method show( )
And now the actual program

// Package Declaration [Link]


package sample ;
public class Sample
{
public void show( )
{
[Link] ( "Bye" ) ;
}
}

We wish to call show( ) from main( ) present in a class Client present


in file [Link]. Here is the program to do this

// Package Usage [Link]


package client ;
import [Link] ;
public class Client
{
public static void main ( String args[ ] )
{
Sample a = new Sample( ) ;
[Link]( ) ;
}
}

Given below are the steps to be followed to create these packages in


NetBeans.

(a) Create a new project by name Client. This will create a file called
[Link] containing a package client, which contains a public
class, Client.

(b) Add a new package called sample. For this right-click Source
Packages. A menu will pop up. From this menu select New | Java
Package sample. This action will create a package sample.

(c) Once the sample package is created, right-click sample package. A


menu would pop up. From this menu select New | Java class
454 Let Us Java

Sample. This action will create a public class Sample in a file


[Link] in the package sample.

(d) Define show( ) method in the Sample class.

Let us now examine the directory structure. The source code would
get created in the following files:

~\Client\src\client\[Link]
~\Client\src\sample\[Link]

On compilation the bytecode gets stored in following files:

~\Client\build\classes\client\[Link]
~\Client\build\classes\sample\[Link]

As you can appreciate the directory structure reflects the package


structure. As a result, it becomes easy to locate a type.
Note that if we do not import the Sample class from sample package
using an import statement, we can still use the Sample class. This can
be done by using a fully qualified name as shown below:

[Link] a = new [Link]( ) ;

Split Packages
It is possible to split a package across multiple files. This means a
package can contain multiple public types stored in different files.
This suits software development teams as different developers can
develop different types and store them in different files. All these
types can belong to the same package. Following program
demonstrates split packages.

// File: [Link]
package sample ;
public class Sample1
{
public void show( )
{
[Link] ( "Bye" ) ;
}
}
Chapter 23: Miscellany 455
// File: [Link]
package sample ;
public class Sample2
{
public void display( )
{
[Link] ( "Hi" ) ;
}
}

Let us now look at code that uses these split packages.

// File: [Link]
package client ;
import sample.Sample1 ;
import sample.Sample2 ;
class Client
{
public static void main ( String args[ ] )
{
Sample1 s1 = new Sample1( ) ;
[Link]( ) ;
Sample2 s2 = new Sample2( ) ;
[Link]( ) ;
}
}

Given below are the steps to be followed to create these packages in


NetBeans.

(a) Create a new project by name Client. This will create a file called
[Link] containing a package client, which contains a public
class, Client.

(b) Add a new package called sample. For this right-click Source
Packages. A menu will pop up. From this menu select New | Java
Package sample. This action will create a package sample.

(e) Once the sample package is created, right-click sample package. A


menu would pop up. From this menu select New | Java class
Sample1. This action will create a public class Sample1 in a file
[Link] in the package sample.
456 Let Us Java

(c) Define show( ) method in the Sample1 class.

(d) Again right-click sample package. A menu would pop up. From this
menu select New | Java class Sample2. This action will create a
public class Sample2 in a file [Link] in the package sample.

(e) Define display( ) method in the Sample2 class.

The source code would get created in the following files:

~\Client\src\client\[Link]
~\Client\src\sample\[Link]
~\Client\src\sample\[Link]

On compilation the bytecode gets stored in following files:

~\Client\build\classes\client\[Link]
~\Client\build\classes\sample\[Link]
~\Client\build\classes\sample\[Link]

Different Packages, Same Type


It is possible that different packages contain types that have same
names. For example, two packages sample1 and sample2 may contain
two different classes by the same name Sample. This is shown in the
following code.

// File: [Link], Package: sample1


package sample1 ;
public class Sample
{
public void show( )
{
[Link] ( "Bye" ) ;
}
}

// File: [Link], Package: sample2


package sample2 ;
public class Sample
{
public void display( )
Chapter 23: Miscellany 457
{
[Link] ( "Bye" ) ;
}
}

Let us now look at client code that uses these Sample class from two
different packages.

// File: [Link], Package: client


package client ;
import [Link] ;
import [Link] ;
class Client
{
public static void main ( String args[ ] )
{
[Link] s1 = new [Link]( ) ;
[Link]( ) ;
[Link] s2 = new [Link]( ) ;
[Link]( ) ;
}
}

The source code would get created in the following files:

~\Client\src\client\[Link]
~\Client\src\sample1\[Link]
~\Client\src\sample2\[Link]

On compilation the bytecode gets stored in following files:

~\Client\build\classes\client\[Link]
~\Client\build\classes\sample1\[Link]
~\Client\build\classes\sample1\[Link]

Note that while creating objects of Sample class from two different
packages, we should use the fully qualified name to help understand
which Sample class are we planning to use for object creation, as
shown below:

[Link] s1 = new [Link]( ) ;


[Link] s2 = new [Link]( ) ;
458 Let Us Java

Nested Packages
It is also possible to create nested packages. This is especially helpful
while creating big libraries containing numerous types. For example, the
classes in Java library are organized in many nested packages like
[Link], [Link], [Link], etc. Note that all packages in Java API
begin with java or javax. Let us now create nested packages for user-
defined classes.

// File: [Link], Package: sample


package sample ;
public class Sample
{
public void show( )
{
[Link] ( "Bye" ) ;
}
}

// File: [Link], Package: [Link]


package [Link] ;
public class Trial
{
public void display( )
{
[Link] ( "Hi" ) ;
}
}

Let us now look at client code that uses the Sample class present in
sample package and the Trial class present in the nested package
[Link].

package client ;
import [Link] ;
import [Link] ;
class Client
{
public static void main ( String args[ ] )
{
Sample s = new Sample( ) ;
[Link]( ) ;
Chapter 23: Miscellany 459
Trial e = new Trial( ) ;
[Link]( ) ;
}
}

The source code would get created in the following files:

~\Client\src\client\[Link]
~\Client\src\sample\[Link]
~\Client\src\sample\trial\[Link]

On compilation the bytecode gets stored in following files:

~\Client\build\classes\client\[Link]
~\Client\build\classes\sample\[Link]
~\Client\build\classes\sample\trial\[Link]

Package FAQs
Often there are questions in programmer s mind about packages and
import statements. I have compiled below these FAQs.

(a) What if package name is absent in a .java file?

All types in the file belong to a package called default package. This
practice should however be discouraged.

(b) Should package name be in small case?

It is a good idea and is used by many Java development


environments including NetBeans. This helps avoids name conflict
with class/interface names.

(c) How do I ensure uniqueness in package names?

Use reversed Internet domain names like [Link],


[Link], etc. Since domain names are unique, their
reversed forms are also unique.

(d) Which packages are imported by default?

default package, [Link]

(e) Which packages would get imported through the statement:


import graphics.A* ;
460 Let Us Java

None. It does not import all packages that begin with letter A. It
would result into compilation error.

(f) Can the following set of statements be replaced by import


[Link].*?
import [Link].*
import [Link].*

No. * can be used to signify all types in a package, and not all
packages nested in a package.

(g) What do the following import statements mean?


import example.ex1.* ;
import example.ex2.ex3.* ;

First statement means import all public types from directory


C:\~\example\ex1. Second statement means import all public types
from directory C:\.....\example\ex2\ex3.

Packages and Access Mechanism


We are already familiar with access specifiers private, protected and
public. If we do not use any of them then the data member or
member function is treated to have a default access specifier. For
example, num and fun( ) in the following code are considered to have
default access specifier.

package p1 ;
class Myclass
{
int num = 40 ;
void fun( )
{
}
}

There are following possibilities when we attempt to access num and


fun( ):
(a) They are accessed from same class
(b) They are accessed from same package s class
(c) They are accessed from different package's class
Chapter 23: Miscellany 461
(d) They are accessed from same package's sub-class
(e) They are accessed from different package's sub-class

Keep the following guidelines in mind while deciding whether they


would accessible or not.
(a) private members are accessible within the class.
(b) default members are accessible within the package.
(c) protected members are accessible within package and in sub-
classes.
(d) public members are accessible anywhere.
(e) Within a package behavior of default, protected and public are
same.
(f) Default members are not accessible across package boundary.
(g) Protected members can be accessed outside the package only
through child class object.
These guidelines have been captured in Figure 23.1.

Figure 23.1

Bitwise Operators
Bitwise operators permit us to work with individual bits of a byte. There
are many bitwise operators available in Java. These include:
~ - complement operator
<< - left shift
>> - right shift
>>> - unsigned right shift
& - and
462 Let Us Java

| - or
^ - xor

The usage of these bitwise operators is shown in the following code


snippet:

int ch, dh, eh, fh, a, b, c ;


ch = 32 ;
dh = ~ch // toggles 0s to1s and 1s to 0s
eh = ch << 3 // << shifts bits in ch 3 positions to left
fh = ch >> 2 // >> shifts bits in ch 2 positions to right
a = 45 & 32 // and bits of 45 and 32
b = 45 | 32 // or bits of 45 and 32
c = 45 ^ 32 // xor bits of 45 and 32

Note that except ~ all other bitwise operators are binary operators.
Remember the following tips while using bitwise operators:
(a) Any bit value ANDed with 0 is 0.
(b) Any bit value ORed with 1 is 1.
(c) 1 XORed with 1 is 0.
(d) << - As bits are shifted from left, zeros are pushed from right.
(e) >> - As bits are shifted from right, left-most bit is copied from left.
(f) >>> - As bits are shifted from right, zeros are pushed from left.

Purpose of each bitwise operator is given below:


~ - Convert 0 to 1 and 1 to 0
<< - Shift out desired number of bits from left
>>, >>> - Shift out desired number of bits from right
& - Check whether a bit is on / off. Put off a particular bit
| - Put on a particular bit
^ - Toggle a bit

There are a few more bitwise operators known as bitwise compound


assignment operators. These include operators like <<=, >>=, &=, |= and
^=. They offer a shortcut as shown in the following statements:
a <<= 5 // is same as a = a << 5
b &= 2 // is same as b = b & 2
Chapter 23: Miscellany 463

CLASSPATH is an environment variable that contains a list of


directories separated by ; (: in Linux)

JRE searches directories in CLASSPATH to locate .class files that


contain third-party and user-defined types.

When the same class file containing floating-point operations is


executed on different platforms it may give different results.

When strictfp is applied to a class, a method or an interface it


ensures that we get same result of floating-point operations on
different platforms

Packages are logical containers that may contain related classes,


interfaces, enumerations and annotations

A package may be split across files

Two different packages may contain types with same names

Through packages we can control which type within it can be


accessed from within and outside the package

A new folder is created for every new package with the same name as
name of the package

A .java file can contain only one public type. Its name is same as the
name of the .java file

Bitwise Operations :
Set a bit to a value 0/1 Write operation
Check whether bit is 1 (on) or 0 (off) Read operation
Bitwise operators available in Java are ~, <<, >>, >>>, &, |, ^, <<=,
>>=, &=, |=, ^=.
You should never take a test when you are not prepared. You
should never give up an opportunity to get tested when you are
fully prepared and confident. This chapter would help you check
your strengths and weaknesses, once you are prepared and
confident...

465
466 Let Us Java

Periodic Test I
(Based on Chapters 1 to 6)

Time: 90 Minutes Maximum Marks: 40

[A] Fill in the blanks: [5 Marks, 1 Mark each]


(1) Java interpreter convers Java source code into ______.
(2) _____ type of values cannot be checked using switch-case.
(3) In the expression condition1 & condition2, condition2 would get
executed only if condition1 is ______.
(4) The size of an int data type is ______ bytes.
(5) Exponentiation operation can be performed using _____ function.

[B] State True or False: [5 Marks, 1 Mark each]


(1) $salary is a correct variable name in Java.
(2) A java program compiled for one JVM has to be recompiled to make
it work on a different JVM.
(3) If we are to run a Java program on a machine, it is enough if JRE is
installed on it.

(4) Once a variable is declared as final its value cannot be changed.

(5) Consecutive cases with no statements between them enable the


cases to execute a common set of statements.

[C] What would be the output of the following code snippets:


[5 Marks, 1/2 Mark each]
(1) What would be the output of the following code snippet?
int a = 25543 ;
[Link] ( "%10d\n", a ) ;
[Link] ( "%+10d\n", a ) ;
[Link] ( "%,10d\n", a ) ;
[Link] ( "%,+10d\n", a ) ;

(2) Why is a function in a class marked public? Why is a class in a


package marked public?
Periodic Tests 467
(3) What is JVM? What is a package?

(4) Write Java statements to sum odd integers between 1 and 99, using
a for statement.

(5) What would be the output of the following code snippet?


int i = 1, j = 2, k = 3 ;
[Link] ( j == 5 ) ;
[Link] ( i <= k ) ;
[Link] ( ! ( i <= j ) ) ;
[Link] ( !i ) ;
(6) How would you ensure that a float result (2.5) gets stored in
variable a in the following code snippet?
float a ;
int b = 5, c = 2 ;
a=b/c;
(7) What would be the output of the following code snippet if value of
choice is 1?

switch ( choice )
{
case 1 :
case 2 :
[Link] ( "Right choice" ) ;
}
(8) Would the following program run? If yes, what would be the output
and if no, what would be the error? Assume that the value of choice
is 3?
switch ( choice )
{
case 1 - 5 :
[Link] ( "Right choice" ) ;
default :
[Link] ( "Wrong choice" ) ;
}
(9) Point out the error, if any, in the following code snippet:
int i = 5, j = 10 ;
boolean flag ;
468 Let Us Java

flag = ( i == 20 && j != 10 ) ? true : false ;


[Link] ( flag ) ;
(10) Point out the error, if any, in the following code snippet:
boolean ret = 1, flag = 0 ;
[Link] ( ret ) ;
[Link] ( flag ) ;

[D] Match the following: [5 Marks, 1/2 Mark each]

(a) size of byte (1) literal


(b) continue (2) abandon loop
(c) break (3) short-circuiting expression
(d) cond1 | cond2 (4) 1 bit
(e) size of short (5) identifier
(f) constant (6) 1 byte
(g) cond1 || cond2 (7) next iteration
(h) size of boolean (8) 4 bytes
(i) size of int (9) no short-circuiting expression
(j) variable (10) 2 bytes

[E] Attempt the following: [20 Marks, 10 Marks each]

(1) According to a survey a popular social networking site has hit one
billion users in Jan 2019. If its user base grows at a rate of 8% per
month, write a program to show how many months will it take for
the site to grow its user base to 1.5 billion users? Print user base
figures at the beginning and end of each month.
(2) Write a program that receives a 4-digit number as input and prints
an equivalent encrypted number. The encryption should be done as
follows:
Replace each digit with ( digit + 7 ) mod 10
Interchange first digit with third digit
Interchange second digit with fourth digit
Also write the decryption logic to obtain the original number from
the encrypted number.
Periodic Tests 469
Periodic Test II
(Based on Chapters 7 to 8)

Time: 90 Minutes Maximum Marks: 40

[A] Fill in the blanks: [5 Marks, 1 Mark each]

(1) _______ package should be imported to be able to use


trigonometric functions.
(2) While defining a function that receives variable number of
arguments _____ symbol is used to collect the values passed to the
function in an array.
(3) During a function call the actual and formal arguments must match
in _____, _____, and _____.
(4) A function should be marked with _____ keyword to indicate that it
is not going to return any value.
(5) A function that calls itself is known as a _______ function.

[B] State True or False: [5 Marks, 1 Mark each]

(1) A fresh set of local variables gets created every time a function is
called normally or recursively.
(2) A function can return only one value at a time.
(3) A function cannot be defined inside another function.
(4) Any function can be made a recursive function.
(5) It is possible to define a function that receives different number of
arguments in different function calls.

[C] Answer the following: [10 Marks, 2 Marks each]

(1) Is this a correct statement? If not, why not?


return ( a, b, c ) ;
(2) What would happen on execution of the following statement?
What value would it return to the calling function?
return ( a, b, c ) ;
470 Let Us Java

(3) Write a code snippet that demonstrates that actual arguments


passed to a function can be a constant, variable or expression,
whereas the formal arguments must always be variables.
(4) Write a code snippet that calls a function cal( ) and passes to it an
angle in degrees. The function cal( ) should return sum of sin and
cos of the angle passed to it.
(5) A recursive call should always be subjected to an if. Why? Explain
with an example.

[D] Attempt the following: [20 Marks, 10 Marks each]

(1) Define a function that receives 4, 5 or 6 integers and returns sum of


the integers that it receives.
(2) Write a recursive function which prints the prime factors of the
number that it receives when called from main( ).
Periodic Tests 471
Periodic Test III
(Based on Chapters 9 to 12)

Time: 90 Minutes Maximum Marks: 40

[A] Fill in the blanks: [5 Marks, 1 Mark each]

(1) In Java an array is implemented as an ______.


(2) An array is created in _____ memory and a reference to it is created
in ______ memory.
(3) _______ method of a class gets called when garbage collector is
about to collect an object.
(4) _____ is used by methods of a class to identify an object it is
working on.
(5) Static functions in a class can access only ______ data.

[B] State True or False: [5 Marks, 1 Mark each]

(1) A string object cannot be mutated.


(2) Two strings represented by objects s1 and s2 can be compared
using the statement if ( s1 == s2 ).
(3) In a 2D array all rows must have same number of elements.
(4) Objects are passed to a function by reference.
(5) A class permits us to build user-defined data types.

[C] Answer the following: [10 Marks, 2 Marks each]

(1) Write a code snippet to print the name and ordinal value for each
element of the following enum.
enum maritalstatus { single, married, divorced } ;
(2) Illustrate with a code snippet the difference between a String and
StringBuilder class.
(3) What is the purpose of static block? When does it get invoked?
(4) Which of the following statements are true about an object?
472 Let Us Java

- Each object's variables can have different values.


- An object can contain many methods using which we can access
or manipulate its state.
- Objects can be created either on heap or on stack.
- An object behaves like a blueprint or template.

(5) What is the limitation of an array of pointers to strings? How can it


be overcome?

[D] Attempt the following: [20 Marks, 10 Marks each]

(1) Create an array of strings containing names of 10 cities. Write a


program that sorts the cities in reverse alphabetical order and
prints this reversed list.
(2) Declare a class Circle containing private variables radius, area and
circumference. Provide a constructor to set up a value in radius.
Create an array of 10 Circle objects, each with different radii. Define
a method calc( ) in the Circle class that calculates and prints area
and circumference for a given Circle object. Call this method for
each object in the array.
Periodic Tests 473
Periodic Test IV
(Based on Chapters 13 to 15)

Time: 90 Minutes Maximum Marks: 40

[A] Fill in the blanks: [5 Marks, 1 Mark each]

(1) The class at the top of exception class hierarchy is _______.


(2) In Java all function calls are resolved using the __________
mechanism.
(3) In an Inheritance chain Base class is also known _______ as and
Derived class is also known as _______.
(4) In overloaded functions their arguments must differ in _______,
_______, or _______ .
(5) _______ keyword should be used to prevent derivation of a new
class from an existing class.

[B] State True or False: [5 Marks, 1 Mark each]

(1) Protected members are inaccessible in the inheritance chain.


(2) Protected members are accessible to classes in the same package.
(3) Inheritance makes use of "Has A" relationship.
(4) Inheritance, Containership and Generics are all code reuse
mechanisms.
(5) Function overloading is an example of Polymorphism.

[C] Answer the following: [10 Marks, 2 Marks each]

(1) Which exception is likely to occur in the following code snippet?


int a, b, c ;
// receive b and c from keyboard
a=b/c;
(2) What is the difference between checked and unchecked
exceptions?
(3) What do you mean by exception propagation?
474 Let Us Java

(4) If no exceptions are thrown in a try block, where does control


proceed to when the try block completes execution?
(5) What happens if several catch blocks match the type of the thrown
object?

[D] Attempt the following: [20 Marks, 10 Marks each]

(1) Create a Document class. From it inherit a Magazine class and a


Book class. Objects of each class should contain a print( ) method.
Create 5 objects each of Magazine and Book class. Store these
objects in an array of references of Document class. Call print( )
method using the array elements ensuring that appropriate class's
print( ) function gets called.

(2) Create the following class hierarchy:


Vehicle - base class
Car, Truck - derived classes derived form Vehicle
Declare an interface Storable containing methods serialize( ) and
deserialize( ). Implement this interface in the derived classes. Call
these functions from main( ).
Periodic Tests 475
Periodic Test V
(Based on Chapters 16 to 21)

Time: 90 Minutes Maximum Marks: 40

[A] Fill in the blanks: [5 Marks, 1 Mark each]

(1) The Java collection class that can be used for maintaining key-value
pairs is _______.
(2) Common algorithms like searching, sorting, etc. can be applied on
collection using functions present in ________ class.
(3) A thread can be created in a Java program by extending the
_______ class or implementing the _______ interface.
(4) If two methods running in two different threads wish to access the
same resource, then to ensure at a time only one thread accesses
the resource the methods should be marked as _______.
(5) All Swing classes are defined in _______ package.

[B] State True or False: [5 Marks, 1 Mark each]

(1) Generic functions cannot work for primitives like int, float, char, etc.
(2) A generic function can receive multiple argument types.
(3) Bounded generics can work only with the objects of specified class.
(4) Protected members are inaccessible in the inheritance chain.
(5) In Swing API there is one adapter class for each listener.

[C] Answer the following: [10 Marks, 2 Marks each]

(1) What are Sources, Events, Listeners, Adapters in context of GUI


applications?
(2) Suppose you have connected to a database containing a table called
Employees. Each record in this table contains EmployeeID, Name,
Age and Salary. Write a code snippet that would read and print all
records present in this table.
(3) What does each function call in the following code snippet achieve?
static final String jdbcDriver = "[Link]" ;
476 Let Us Java

static final String dbURL = "jdbc:mysql://localhost/study" ;


Connection conn = null ;
Statement stmt = null ;
String sql = sql = "INSERT INTO Accounts VALUES ( 1001, 'Joe' )" ;

[Link] ( jdbcDriver ) ;
conn = [Link] ( dbURL, "root", "admin" ) ;
stmt = [Link]( ) ;
[Link] ( sql ) ;
(4) What are CRUD operations?
(5) What are bounded generics? When are they used?

[D] Attempt the following: [20 Marks, 10 Marks each]

(1) Write a program that maintains a hash map of 10 Employee Ids as


keys and name of the person, his email address and his date of birth
as values.
(2) Producer - Consumer algorithm is a popularly used algorithm in
Computer Science. It is a technique for generating requests (by
producer) and processing the generated requests (by consumer).
Write a program to implement this algorithm to meet following
specifications:
The Producer produces factorial value of numbers in sequence 0,

Consumer consumes the produced factorial values by printing


them
Both Producer and Consumer work as independent threads
Consumer must wait while Producer is producing
Once Producer has produced it would send a signal to Consumer
Producer must wait while Consumer is consuming
Once Consumer has consumed it should send a signal to
Producer
Search it, the easy way...

477
478 Let Us Java

type conversion, 45, 48


array, 187, 188
! array
2-D arrays, 198, 200
!, 69 accessing elements, 188
!=, 61 bounds checking, 190
%=, 85 declaration, 188
&&, 64 initialization, 189
&, 68 jagged array, 200, 201
*=, 85 multi-dimensional, 197
--, 85 of objects, 195, 196
++, 85 of strings, 217
+=, 85 passing 2-D array, 198
-=, 85 passing array reference, 192
/=, 85 passing to function, 191, 192
<, 61 reading data from, 189
<=, 61 resizing of arrays, 202
==,61 returning an array, 193, 198
>, 61 two dimensional, 198, 200
>=, 61 associativity of operators, 49
? :, 71
|, 68
||, 64 B
2-D array, 198, 200
2-D jagged arrays, 200 Binary Search Tree, 381
Binary Tree, 380
BufferredInputStream, 308, 326
A BufferredOutputStream, 308
BufferredReader, 309
ActionListener interface, 396 BufferredWriter, 309
Algorithms, 373, 374, 383 binarySearch( ), 384, 385
ArrayList class, 375, 376 bitwise operators, 461
Arrays class, 383, 384 boolean data type, 37
AWT library, 391 bounds checking, 190
abs( ), 45 break, 90
abstract classes, 252 byte, 35
abstract functions, 252, 256 bytecode, 7, 8, 10
actionPerformed event, 392, 395
actual arguments, 119, 121
append( ), 217 C
args, 24, 26
command-line, 40 C++, 9
arithmetic instruction, 43 CLASSPATH, 451
Index 479
CRUD operations, 406, 407 constants, 21
Collection Classes, 373, 374 constructors, 163, 165
Complex class, 168 constructors,
Containership, 151 in inheritance, 237
Control Instructions, 53 continue, 92
called function, 114 control instructions, 53
calling function, 114, 118 decision, 61
canRead( ), 308, 312 case, 103
canWrite( ), 308 loops, 81
case, 103, 104 copyOf( ),
catch block, 277, 278, 282 copyValueOf( ), 213, 215
char data type, 37 cos( ), 45
character constant, 21 createStatement( ), 411, 414
chat application, 434, 438
class, 163, 164
ArrayList, 375, 376 D
Collections, 383
Complex, 168 DELETE, 412
constructors, 163, 165 DataInputSrteam, 326
HashMap, 382 DataOutputSrteam, 311
LinkedList, 378, 379 Data organization, 405
MouseAdapter, 400 Date class, 302, 303
Stack, 377 Driver interface, 408
StringBuilder, 217 DriverManager class, 409, 410
SQLException, 410 data type, 19, 35
TreeSet, 381 boolean, 37
terminology, 167 byte, 35
close( ), 310, 311, 312 char, 37
command line arguments, 40 enum, 221, 222
comment, 25 integer, 35
compareTo( ), 213, 215, 218 long, 35
compareToIgnoreCase( ), 215 user-defined, 32
compilation, 28 real, 36
compiler, 4, 8, 10, 11, 28 short, 35
compound assignment operators, 85 decision control instructions, 61
concat( ), 213, 215 default, 103
contains( ), 216 delete( ), 217
conditional operators, 71 directory operations, 301
console, 313 do, 90
console I/O, 50 double, 36
console I/O functions, 50, 51 do-while, 90
readLine( ) function, 50 drive operations, 301
constant variables, 49
480 Let Us Java

for, 86
E loop, 86, 87, 88
multiple initializations, 89
Event, 394 nesting, 88
ActionEvent, 396, 396 partial, 88
MouseEvent, 395, 399, 400 formal arguments, 119, 121
actionPerformed, 392, 395, 396 format( ), 51
Event handling, 394 format specifiers, 52
else, 61 function overloading, 131
else if clause, 66 functions, 113
enum, 221 functions
enumerations, 221 called function, 114
use of, 222 calling function, 114, 118
exceptions passing values between, 118
user-defined, 287 function overloading, 131
exception handling, 276 readLine( ) function, 50
execution, 28 println( ) function, 51
executeUpdate( ), 412
executeQuery( ), 412, 414
exists( ), 312, 316
explicit conversion, 47
G
exponential form, 37
garbage collector, 166, 167
generic classes, 361
generic functions, 353
F generics, 353
bounded, 366
Float, 39 getAbsolutePath( ), 302
File, 301, 303, 305 getCanonicalPath( ), 216, 217
FileInputStream, 308, 314 getConnection( ) , 413, 414
File Operations, 301 getFloat( ), 412, 414
FileOutputStream, 311, 313, 315 getInt( ), 412, 414
FilterOutputStream, 326 getName( ), 302, 304, 314
FileReader, 309, 312 getParent( ), 302
FileWriter, 309, 310, 311 getString( ), 412, 414
false, 37 getText( ), 392, 398, 399
file decryption, 318, 321
file encryption, 318, 321
file transfer, 446
fill( ), 195
H
final, 50, 240
finalize method, 166, 167 HTTP, 433
finally block, 285, 286, 312 HashMap, 382
float, 36 HashMap class, 382
hierarchy, 48
Index 481
isEmpty( ), 216
I isSelected( ), 398, 399

I/O System
Expectations, 301
IDE, 11
J
INSERT, 412
Input/Output, 301 J2SE, 14
InputStreamReader, 302. 309 JButton, 393, 394
Integer, 35, 39 JDBC, 405, 407
Integrated Development Architecture, 407
Environment, 11 adding library, 413
Interfaces, driver, 408
ActionListener, 396 driver manager, 408
MouseListener, 400 driver type, 408
practical uses of, 260 JLabel, 393
Interfaces - different JPanel, 393, 394
implementations, 264 JTextField, 393, 394
Interfaces - focused view, 261 James Gosling, 5
Interfaces - unrelated inheritance, Java, 5, 6
266 bytcode, 7, 8, 10
identifier, 21 data types, 19, 35
if-else statement, 61 instructions, 41
nested if-elses, 65 keywords, 23
incremental development, 241 library, 14
indexOf( ), 214, 215 streams, 306
inheritance, 231 JavaFX library, 391
constructors, 237 JDK, 10, 11
uses, 234 JIT compiler, 10
insert( ), 217 JRE, 10, 11
instruction types, 41 JVM, 7, 8, 9
instructions, 41 jagged array, 200, 201
instructions [Link] package, 408
arithmetic instruction, 41, 43 joining and splitting strings, 216
control instruction, 41, 53
exception handling, 41
type declaration instruction, 41 K
int, 35
integer, 35 keywords, 23
integer constant, 35
interface,
practical uses, 260 L
inter-thread communication, 346
isDirectory( ), 304
482 Let Us Java

Linked List, 378 networking concepts, 421


LinkedList class, 378, 379 networking model, 423
Linux, 7, 8 new, 159, 160, 162
Listener interfaces, 399
lastIndexOf( ), 214, 215
literal, 21, 37 O
log( ), 45
log10( ), 45 OOP, 143
logical operators, 64, 68 objects, 163
long, 35 object, 163, 165
loops, 81 Connection, 407, 409, 411
loops ResultSet, 407, 409, 411
do-while loop, 90 Statement, 409, 410, 411
for, 86 object destruction, 166
tips, 83 object-oriented programming, 146
while, 81 classes, 149
containership, 151
inheritance, 149
M objects, 148
polymorphism, 151
Math, 45 reusability, 151
MouseAdapter, 400 operators,
MouseListener interface, 400 associativity, 49
Multitasking, 329 bitwise, 461
Multithreading, 329 compound assignment operators,
MySQL, 405 85, 100
Workbench, 407 conditional operators, 71
installation, 409 hierarchy, 70
main( ), 24, 25, 26 logical operators, 64
mouseClicked( ), 400 relational operators, 62
mouseEntered( ), 400 OutputStreamWriter, 309, 310
mouseExited( ), 400 overloading functions, 131
mousePressed( ), 400
mouseReleased( ), 400
multiple exceptions, 283 P
multiuser chat application, 438
PrintWriter, 309
package, 24, 25, 449
N [Link], 408
packets, 426
NetBeans, 11, 28 parseInt( ), 39, 40, 51
nested if-elses, 64, 65 parseFloat( ), 39, 40
nesting of loops, 88 passing
Index 483
2-D array, 198 strictfp, 451
array elements, 191 StringBuilder class, 217
array reference, 192 Swing library, 391, 393
parameters, 118 schema, 410, 411
values, 118 security, 8
port numbers, 427 short, 35
protocols, 426 sin( ), 45
polymorphism, 249 sockets, 426
pow( ), 45 sort( ), 385
primitives, 19 split( ), 217
println( ), 24, 27, 51 splitting strings, 216
protected, 232, 233 sqrt( ), 45
public, 234, standard exception, 287
private, 234 static data, 174
static functions, 174
streams, 306
R stream classes, 308
user-defined streams, 315
RDBMS, 405, 406 string Functions
Reader, 309 charAt( ), 213, 214, 215
Record I/O, 313 compareTo( ), 213, 215
readLine( ) function, 50 concat( ), 213, 214
real, 36 contains( ), 216
Recursion, 134 copyValueOf( ), 213, 214
reference type, 19 format( ), 216
relational operators, 61 indexOf( ), 214, 215
replace( ), 217 isEmpty( ), 216
resizing of arrays, 202 lastIndexOf( ), 214, 215
return, 118 length( ), 215
returning 1-D array, 193, 198 replace( ), 215
reusability, 151 substring( ), 214, 215
rules, toUpperCase( ), 215, 216
for constructing constants, 21 strings,
for constructing variables, 22 array of, 217
reading, 312
sorting, 220
splitting, 216
S structured programming, 143, 144
super, 236, 237, 238
SELECT, 412, 414 switch, 103, 105, 107
SQLException class, 410
Solaris, 4
Stack, 373, 374
Stack class, 377, 379
T
484 Let Us Java

TCP, 434 void, 24, 26, 27


Tree, 379
Binary, 380
TreeSet class, 381 W
table,
Alter, 406 Windows, 6, 7, 8, 11
Create, 406 Writer, 309, 310, 311
Drop, 406 while, 81, 83
tan( ), 45 whois server, 432
this reference, 172 write( ), 310, 311, 315
thread writeInt( ), 310, 311
launching, 332
launching multiple threads, 335
priorities, 347
synchronization, 343
three dimensional array, 197
throw, 287, 292
time server, 430
try, 292
toString( ), 310
toUpperCase( ), 213
traditional programming model, 6
true, 37
two dimensional array, 198
typecasting, 47, 48
type conversion, 47
type declaration instruction, 42

U
UDP, 444
UPDATE, 406, 407, 410, 412
user-defined exceptions, 287
user-defined streams, 315

V
value type, 19
variable names,
rules for constructing, 22
variables, 20, 22, 23

You might also like