Let's Java
Let's Java
}
catch ( StackException ex )
{
[Link] ( "Problem in stack" ) ;
[Link]( ) ;
}
try
{
while ( [Link]( ) > 0 )
[Link] ( [Link]( ) ) ;
}
catch ( StackException ex )
{
[Link] ( "Problem in stack" ) ;
[Link]( ) ;
}
}
}
Problem in stack
Stack full
25
Sanjay
Vinod
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.
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..
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
(d) For one try block there can be multiple catch blocks.
(e)
called.
(m) finally clause is used to perform cleanup operations like closing the
network/database connections.
(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.
(t) All types of exceptions can be caught using the Exception class.
(u) For every try block there must be a corresponding finally block.
(a) If we do not catch the exception thrown at runtime then who will
catch 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
import [Link].* ;
import [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 ) ;
{
String str ;
[Link] ( indent + [Link]( ) + "/" ) ;
for ( File fi : [Link]( ) )
{
str = indent + " " + [Link]( ) ;
[Link] ( str ) ;
}
./
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]
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
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.
package byteandcharacterstreams ;
import [Link].* ;
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( ) ) ;
}
}
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,
package displayfilecontents ;
import [Link].* ;
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
choice = [Link]( ) ;
}
[Link]( ) ;
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
// Converts all chars read from a file into uppercase using a filter stream
package filterstreamproject ;
import [Link].* ;
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 ;
String line ;
while ( ( line = [Link]( ) ) != null )
[Link] ( line ) ;
[Link]( ) ;
[Link]( ) ;
}
}
}
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
interface ITransform
{
public char transform ( char ch ) ;
}
class Encrypt implements ITransform
{
String str = "xyfagchbimpourvnqsdewtkjzl" ;
return ch ;
}
}
class Decrypt implements ITransform
{
String str = "xyfagchbimpourvnqsdewtkjzl" ;
return ch ;
}
}
class TransformWriter extends FilterWriter
{
private ITransform trans ;
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 ;
FileWriter tstream ;
TransformWriter tw ;
BufferedWriter sw ;
Chapter 16: Effective Input/Output 321
String line ;
while ( ( line = [Link]( ) ) != null )
[Link] ( line + "\r\n" ) ;
[Link]( ) ;
[Link]( ) ;
}
}
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.
(l) The streams implementation in Java is such that the stream doesn't
have to know source or destination of the data.
(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?
[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.*
Byte stream perform i/o one byte at a time. They are used to i/o
binary data
character stream
- 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
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 ) ;
}
}
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.
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
t = [Link]( ) ;
String s = [Link]( ) ;
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.
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
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]( ) ;
{
Thread x ;
Ex ( String n )
{
x = new Thread ( this, n ) ;
}
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:
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
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.
[India[Nagpur[KICIT]
]
]
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 ;
[KICIT]
[NAGPUR]
[INDIA]
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
(d) If we create a class that inherits from the Thread class, we can still
inherit our class from some other class.
(i) To launch a thread we must explicitly call the run( ) method defined
in a class that extends the Thread class.
[B] Pick up the correct alternative for each of the following questions:
(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
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
.
Generic Functions
Suppose you wish to print contents of an integer array. To achieve this
we can write a function as shown below:
// 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 ) ;
}
}
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( )
[Link]( ) ;
}
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 ) ;
-6.28
A
1.1
}
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;
t = n[ i ] ;
n[ i ] = n[ j ] ;
n[ j ] = t ;
}
}
}
}
}
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.
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.
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 ) ;
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]( ) ;
}
}
}
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 ;
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.
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 ) ;
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
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 ;
Statistics ( T[ ] obj )
{
arr = obj ;
}
public double getAverage( )
{
double sum = 0.0 ;
(d) Generic functions cannot work for primitives like int, float, char,
etc.
(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:
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
{
..
}
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 ) ;
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
(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.
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
package arraylistdemo ;
import [Link].* ;
public class ArrayListDemo
{
public static void main ( String[ ] args )
{
ArrayList <String> alnames ;
if ( [Link] ( "Aditya" ) )
[Link] ( "Aditya is present in the array list" ) ;
int sum = 0 ;
for ( int i = 0 ; i < [Link]( ) ; i++ )
sum = sum + [Link] ( i ) ;
376 Let Us Java
sum = 0 ;
for ( int n : arr )
sum += n ;
Here is th
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 ) ;
}
}
}
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 ) ;
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 ) ;
}
}
[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].* ;
[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.
package arraysdemo ;
import [Link].* ;
public class ArraysDemo
{
public static void main ( String[ ] args )
{
int arr[ ] = new int[ 5 ] ;
Random r = new Random( ) ;
{
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 ) ;
}
}
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.
(h) All binary trees are maintained by TreeSet class as binary search
trees.
[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].*
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?
Vector class and ArrayList class both can maintain arrays that grow
dynamically
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
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
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( ) ;
}
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) 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( ).
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.
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]( ) ;
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:
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
(f) For every event related interface available in Swing library there is
one equivalent adapter class.
(i) The Even Delegation model ensures that the code that creates
controls and events remains separate from the code that reacts to
events.
it.
(c) Write a program that draws a line, rectangle and ellipse of suitable
402 Let Us Java
For every window and control there are Swing classes available
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.
(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.
// 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 ) )
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
// Delete that record from the Persons table whose Employee ID is 1244
DELETE FROM Persons WHERE EmpID = 1244
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
Figure 21.1
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.
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:
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:
(d) Click on the Columns tab at the bottom of the page and create
three columns with following properties.
(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].* ;
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 ) ;
int id ;
String name ;
float balance ;
while ( [Link]( ) )
{
id = [Link] ( "ID" ) ;
name = [Link] ( "Name" ) ;
balance = [Link] ( "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 ) ;
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.
(d) Advantage of JDBC is that the same driver can be used to connect
multiple RDBMSs.
(h) Driver
416 Let Us Java
(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:
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
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
419
420 Let Us Java
Networking Concepts
Networking Model
Protocols
Packets
IP Addresses
Sockets
Port Numbers
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
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
package addresses ;
import [Link] ;
ia = [Link] ( "[Link]" ) ;
[Link] ( "Name: " + [Link] ( ) ) ;
[Link] ( "Address: " + [Link] ( ) ) ;
[Link] ( "Reachable: " + [Link](3000));
}
catch ( UnknownHostException ex )
{
[Link] ( ) ;
}
}
}
?
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].* ;
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]( ) ;
}
}
Date class we converted the milliseconds since 1970 into date time
format and printed it.
package javawhoisclient ;
import [Link].* ;
import [Link] ;
int c ;
while ( ( c = [Link]( ) ) != -1 )
[Link]( ( char ) c ) ;
[Link]( ) ;
}
}
package javhttpclient ;
import [Link].* ;
import [Link].* ;
import [Link].* ;
{
URL url = new URL ( "[Link] ) ;
URLConnection urlConnection = [Link]( ) ;
InputStream is = [Link]( ) ;
int c ;
while ( ( c = [Link]( ) ) != -1 )
[Link] ( ( char ) c ) ;
[Link]( ) ;
}
}
<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.
DataInputStream dis ;
dis = new DataInputStream ( [Link]( ) ) ;
DataOutputStream dos ;
dos = new DataOutputStream ( [Link]( ) ) ;
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.
DataInputStream dis ;
dis = new DataInputStream ( [Link]( ) ) ;
DataOutputStream dos ;
dos = new DataOutputStream ( [Link]( ) ) ;
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.
(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].* ;
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++ ;
}
}
}
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] ;
InetAddress ip = [Link]( ) ;
Socket s = new Socket ( ip, 1234 ) ;
DataInputStream dis ;
dis = new DataInputStream ( [Link]( ) ) ;
DataOutputStream dos ;
dos = new DataOutputStream ( [Link]( ) ) ;
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]( ) ;
}
}
}
}
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
File f ;
f = new File ( fname ) ;
FileInputStream fis = new FileInputStream ( f ) ;
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.
(d) HTTP protocol is used for accessing web pages from a site.
(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.
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:
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
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.
(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.
(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.
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]
~\Client\build\classes\client\[Link]
~\Client\build\classes\sample\[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" ) ;
}
}
// 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]( ) ;
}
}
(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.
(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.
~\Client\src\client\[Link]
~\Client\src\sample\[Link]
~\Client\src\sample\[Link]
~\Client\build\classes\client\[Link]
~\Client\build\classes\sample\[Link]
~\Client\build\classes\sample\[Link]
Let us now look at client code that uses these Sample class from two
different packages.
~\Client\src\client\[Link]
~\Client\src\sample1\[Link]
~\Client\src\sample2\[Link]
~\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:
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.
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]( ) ;
}
}
~\Client\src\client\[Link]
~\Client\src\sample\[Link]
~\Client\src\sample\trial\[Link]
~\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.
All types in the file belong to a package called default package. This
practice should however be discouraged.
None. It does not import all packages that begin with letter A. It
would result into compilation error.
No. * can be used to signify all types in a package, and not all
packages nested in a package.
package p1 ;
class Myclass
{
int num = 40 ;
void fun( )
{
}
}
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
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.
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)
(4) Write Java statements to sum odd integers between 1 and 99, using
a for statement.
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
(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)
(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.
(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
(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.
(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.
[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?
477
478 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
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