JAVA Programming 2013
JAVA Programming 2013
K. Rajkumar
Department of Computer Science
Bishop Heber College
Tiruchirappalli, India
No part of this eBook may be used or reproduced in any manner whatsoever without the publisher’s
prior written consent.
This eBook may or may not include all assets that were part of the print version. The publisher
reserves the right to remove any material in this eBook at any time.
ISBN 9788131799093
eISBN 9789332517868
Head Office: A-8(A), Sector 62, Knowledge Boulevard, 7th Floor, NOIDA 201 309, India
Registered Office: 11 Local Shopping Centre, Panchsheel Park, New Delhi 110 017, India
Preface xxiii
3. Arrays in Java 61
4. Methods in Java 89
Appendix A 667
Appendix B 668
Appendix C 669
Index 671
Preface xxiii
Key Terms—45
Review Questions—45
Exercises—59
3. Arrays in Java 61
3.1 Introduction—61
3.2 Declaring and Initializing Arrays—62
3.3 Accessing Array Elements—62
3.4 Problem: Sequential Search for a Key—64
3.5 Problem: Binary Search for a Key—65
3.6 The for-each Statement—68
3.7 Problem: Finding Euclidean Distance Between Two Vectors—69
3.8 Problem: Reverse an Array Without Copying—71
3.9 Multidimensional Arrays—72
3.10 Problem: Transpose of a Matrix—76
3.11 Summary—79
Key Terms—79
Review Questions—79
Exercises—88
4. Methods in Java 89
4.1 Introduction—89
4.2 Defining a Method—90
4.3 Calling a Method—90
4.4 Problem: Nested Method Calls—93
4.5 Problem: Calculate Area of Geometric Objects—94
4.6 Problem: Generate Prime Numbers—95
4.7 Recursion: Power and Pitfalls—96
4.8 Method Overloading—101
9.12 Summary—308
Key Terms—308
Review Questions—308
Exercises—316
13.13 Summary—438
Key Terms—438
Review Questions—439
Exercises—446
16.13.1 CheckBoxes—574
16.13.2 Radio buttons—577
16.13.3 Combo boxes—579
16.13.4 Lists—583
16.14 Dialog Windows—585
16.15 Choosing File Names—586
16.16 Choosing Colors—590
16.17 Displaying Messages—593
16.17.1 Message dialogs—593
16.17.2 Confirm dialogs—594
16.17.3 Option dialogs—594
16.17.4 Input dialogs—594
16.18 Problem: Designing Course Registration Form—595
16.19 Creating Editor Pane and Text Pane—601
16.20 Creating Slider—606
16.21 Designing Tabbed Pane—608
16.22 Handling Menu—610
16.23 Table Handling—614
16.24 Creating Custom Swing Components—618
16.25 Summary—620
Key Terms—621
Review Questions—621
Exercises—629
Appendix A 667
Appendix B 668
Appendix C 669
Index 671
Objectives
■■ To introduce Java and World Wide Web
■■ To introduce Java Editing Environments
Objectives
■■ To explore Java comments, errors and debugging Objectives
■■■
■ To explore
To introduce
Javaimplementations of Set
constants, variables, interface
literals, data types (both primitive and wrapper) and operators
To initialize
check whether Setswith
allow duplicates
■■■
■ To data types binary values List the learning requirements for
■■ To write
introduce
numericthe add andwith
values remove operations on Sets
underscore
■■ To
To understand
introduce the the ways
unionofand
type casting such
difference as upcasting,
operations downcasting, auto-boxing and unboxing
on Sets
the chapter, which could be topics,
■■■ To
■ To explain
developJava console
counting input andapplication
duplicates output statements concepts and solved programs.
■■■ To
■ To implement Command line arguments
introduce LinkedHashSet's insertion using
orderingSumIt application
■■ To briefly explain exception handling with try-catch statements
■■ To introduce TreeSet's red black tree implementation
■■ To explain Scanner class with PrintSum application
■■ To implement BufferedReader class with CircleArea application
Map Containers 293
10.1 intrOductiOn
■■ To develop EllipseArea application with DataInputStream class
Tothedevelop
third ConsoleTest
login.get(alex):12ff
■■ are
Sets type of Javaapplication
containers with
we areConsole
goingclass
to deal with in this book. Having seen Lists
login.contains(123ff):
and Map types, we might have observed true that lists and maps allow duplicate values. However there are
intrOductiOn
login.containsKey(rex): true
many situations where we need to hold only unique elements. This is where sets score better. In this
All keys Introduction
90
chapter,
You
theJAVA
are about
john
readers will be introduced to Set interface and its three implementations. Analogous to
Programming
to start a joyful journey to the world of Java by learning the powerful features of Java and de-
Map types, sets also have HashSet, LinkedHashSet and TreeSet types.
veloping
alex exciting Java applications now. In this book, Part 1 containing the first four chapters presents Java
rex
language
Modularas a structured
programming programming language. That is, you
applies divide-and-conquer will learn
strategy how totosolve
in order problems
divide basedprogram
the larger on intoGives an overview of the chapter and
a All
set ofvalues
algorithmic
10.2 set stepspieces
small and modular
interfaceso thatprogramming,
each piece of very similar to can
a program C language. In this chapter,
be implemented as a we Therefore, eachsets the context for the discussion of
will introduce
method.
235ff
you to the development of a Java application, besides highlighting the evolution of Java since 1991.
method can be implemented separately by different developers and integrated later to form a single appli-
12ff
Set interface
cation. Also, has exactly
methods the same
support set reusability
code of features like other
– that collection
is the same codeinterfaces
can besuch as List
applied to and Map. sets ofconcepts.
multiple
123ff
One notable feature of set is that it will not allow duplicate objects. Sets model the mathematical set
values. Method is also called function by earlier structured languages like C. In this chapter, we lead the
concept. Set interface inherits only methods from Collection interface.
readers
Recall,toHashtable
the understanding of methods
can store any key-valueandpairshow to achieve
as objects, whichmodular
includes programming using methods.
any container. Suppose
we want to map a set of linked lists as values for given keys. This can be easily done with Hashtables
4.2
as showndefining
in Example 9.1. a MethOd
Example
method9.1.
can LinkedLists as Hashtable Values in Figure 4.1.
A be defined with syntax as shown
Examples
figure 4.1. Method
LinkedList Definition
javaUsers in Java
= new LinkedList();
LinkedList linuxUsers = new LinkedList();
LinkedList pythonUsers = new LinkedList();
access-type return-type method-name(arguments) { Give adequate illustrations that im
// body;users = new Hashtable();
Hashtable prove the understandability of con
}
users.put(“java”, javaUsers);
users.put(“linux”, linuxUsers);
cepts and Java language features.
users.put(“python”, pythonUsers);
As shown in Figure 4.1, each method will have an access-type (right now assume public static for
simplicity), value to be returned by the method, name of the method and a set of arguments. Note that
The values()are
arguments returns all values
optional and aasmethod
a Collection, so you
need not canany
return create Iterator
value. If a to your Hashtable
method does not too as any value,
return
shown in Example 9.2.
it is indicated by void data type. Now, we shall develop a method max() that will read two integers and
calculate
Example 9.2.the biggest andfor
Iterators return the result to the calling place. Listing 4.1 depicts the method max().
Values
Transpose Matrix
1 4 7
2 5 8
3 6 9
Exercises
≥ 2
Fn = Fn-1 + Fn-2 for Fnn = Fn-1 + Fn-2 for n ≥ 2
exercises
A novice developer will A
implement
novice developer
this recursive
will implement
function to this
generate
recursive
Fibonacci
function
sequence
to generate
as Fibonacci sequence as
depicted in Figure 4.5. depicted in Figure 4.5.
13.1. Count the number of characters in a given file.
13.2.4.5.
figure Count the number
Fibonacci of4.5.
Function
figure words
Using in a file.
Fibonacci
Recursion Function Using Recursion
Expect readers to develop programs
13.3. Print the frequency (i.e. number of times it occurs) of each character from a given file.
fibo(int n) fibo(int n) based on the concepts and skills they
{13.4. Print the frequency of words in a given file.
if([File
13.5. n == 0)
{
Encryption] if( n cipher
Caesar == 0) (with k=2) replaces A by C, B by D, .., Y by A and Z by B. have learned throughout the chapter.
return 0;
Now read characters ofreturn 0;
a file, encrypt and store it in a new file. Just ignore when you encoun-
if( n == 1) if( n == 1)
ter lowercase
return 1; letters orreturn
other characters.
1; Display both source and destination files.
13.6. [File Decryption]
return fibo(n-1) +Read
returnan already
fibo(n-2); encrypted
fibo(n-1) file, perform the reverse replacement of charac-
+ fibo(n-2);
} ters and recover} the original file.
Java, since its advent about two decades ago, has been an extremely popular programming language around
the world. It is the Numero Uno programming language in terms of academic acceptance and the actual
number of developers. Further, Java continues to maintain its No.1 rank on the TIOBE Programming Com-
munity Index. This book aims to introduce Java by unraveling its powerful constructs to develop exciting
applications.
Audience
This book provides concise and simplified introduction to Java programming and is a suitable one-semester text
book for B.Sc., BCA, B.E. and B.Tech. students. It also covers major topics of Java syllabus for M.Sc., MCA and
other related postgraduate programmes that include a course on Java.
Prerequisites
This book does not assume any prior programming knowledge. However, some basic understanding of condi-
tions, iterations, functions and files concepts will help readers to understand the concepts easily. Therefore, a
little knowledge of either C or Python language would be advantageous to learn Java.
Reading Outcomes
This book is not a reference repository to all Java packages and Application Programming Interfaces (API). As
Java is vast, we will touch upon only those classes and methods that are necessary for the presentation of the con-
cepts discussed in this book. So, you are encouraged to refer to online API documentation available from Sun’s
Web site for further information about Java packages.
In contrast to the idea of a reference text book, this book will teach you the art of programming using Java
language. That is, you will learn how to solve problems by leveraging Java features through its wealthy collection
of classes and methods. The book also focuses on a few interesting problems from data structures, algorithms and
web engineering, besides object-oriented programming.
As Java certification is an added advantage, this book is designed to equip readers to take up Oracle Certified
Associate, Java SE7 Programmer – I (the erstwhile Sun Certified Java Programmer) certification examination,
with its unique multiple-choice question collections.
Course Outline
Although the whole book can be conveniently covered in one semester, instructors can customize the syllabus
according to their requirements. The following flow diagram suggests three sample tracks for the Java pro-
gramming course. The first track outlines the syllabus for the beginners who do not have any prior program-
ming knowledge. The second track is meant for the intermediate level who have a little programming knowl-
edge. The third track specifies the syllabus for the seniors who have complete knowledge of one programming
language.
Chapters 1–7
15.1–15.14 15.1–15.17
17.1–17.8 17.1–17.10
Online Resources
Source code of all examples and exercises, instructor’s lecture slides as well as errata can be accessed online from
www.pearsoned.co.in/krajkumar
Online Practice
The book comes with a customized FREE version of Coderipe with selected programming exercises and ex-
amples from the book (highlighted in the textbook using the Coderipe logo ( )). Coderipe is a Web-based
virtual programming lab on C, C++, Java and others.
Acknowledgements
I would like to thank Dr D. Paul Dhayabaran, Principal, Bishop Heber College, and all other staff members of
this college for providing me the opportunity to teach Java in this college for over a decade. This experience has
served well to make this book a reality. I am grateful to all teachers and students for their comments and sugges-
tions to improve this text.
This book has received a lot of insightful comments, suggestions and reviews from eminent instruc-
tors. My heartfelt thanks to Maria Bielikova (Slovak University of Technology, Slovakia), George Ghinea
(Brunel University, UK), Frederic Andres (National Institute of Informatics, Japan), Asanee Kawtrakul
(Kasetsart University, Thailand), Fernando Ferri (CNR, Italy), Patrizia Grifoni (CNR, Italy), Joemon Jose
(University of Glasgow, UK), Krzysztof Michalak (Wroclaw University, Poland), Kalaiarasi Anbananthen
(Multimedia University, Malaysia), and Christian Guetl (Graz University of Technology, Austria). Also, I am
indebted to all the anonymous reviewers for their constructive comments.
It has been a great pleasure and honor to work with Pearson. I would like to thank Mathivathani RP,
M. Balakrishnan, and all others who were involved in organizing, producing and promoting this book to ensure
that it was published on time.
As always, I thank my wife, Sheela, for her sustained support and my little daughters Hazel and Beryl who
made my long hours of writing cheerful and refreshing.
Comments and feedback about the topics discussed in this book are welcome. I may be contacted at
[email protected]
K. Rajkumar
Objectives
■■ To introduce Java and World Wide Web
■■ To introduce Java Editing Environments
■■ To explore Java comments, errors and debugging
■■ To explore Java constants, variables, literals, data types (both primitive and wrapper) and operators
■■ To initialize data types with binary values
■■ To write numeric values with underscore
■■ To understand the ways of type casting such as upcasting, downcasting, auto-boxing and unboxing
■■ To explain Java console input and output statements
■■ To implement Command line arguments using SumIt application
■■ To briefly explain exception handling with try-catch statements
■■ To explain Scanner class with PrintSum application
■■ To implement BufferedReader class with CircleArea application
■■ To develop EllipseArea application with DataInputStream class
■■ To develop ConsoleTest application with Console class
1.1 Introduction
You are about to start a joyful journey to the world of Java by learning the powerful features of Java and de-
veloping exciting Java applications now. In this book, Part 1 containing the first four chapters presents Java
language as a structured programming language. That is, you will learn how to solve problems based on
algorithmic steps and modular programming, very similar to C language. In this chapter, we will introduce
you to the development of a Java application, besides highlighting the evolution of Java since 1991.
HelloJava.clas s
HelloJava.java javac java Output
classes, abstract classes and interfaces that can be imported and invoked inside the Java program. Some
examples of primitive packages we are interested in this book are lang, util, io, awt, applet and swing.
Essentially, developing a Java application is simply designing the algorithm as a collection of
sequential steps and translating it into a Java source code. To be precise, the process of Java program-
ming has three steps (see Figure 1.1):
■■ Creating the program using any text editor (such as NetBeans (www.netbeans.org), Eclipse
(www.eclipse.org), JEdit (www.jedit.org), IntelliJCommunity Edition (http://www.jetbrains.
com) and many others and saving it to a file with .java extension, say HelloJava.java.
■■ Compiling the file, using javac compiler, as by typing javac HelloJava.java in the command
prompt, this produces a platform-independent byte code, with extension .class, say HelloJava.class.
■■ Interpreting or running the class file, with Java Virtual Machine (JVM ), as by typing java
HelloJava in the command prompt, which produces the desired output, as shown in Listing 1.1.
//HelloJava.java
import java.lang.*;
E:\Rajkumar\javacourse\basics>javac HelloJava.java
E:\Rajkumar\javacourse\basics>java HelloJava
Hello Java World
E:\Rajkumar\javacourse\basics>
Java starts executing a program from the first line of the main() method of a public class. This Java
program displays the string HelloJava onto the monitor of your computer using println() method. Here,
System.out refers to the standard output device, which is a monitor. Note that the source file should be
saved by its class name, and each file should have a public class in which main() method should have been
defined.
This application includes all classes in the package named lang, which is included automatically by
default to any application. Generally, we do not have to import it. Remember, Java is case sensitive.
For simplicity, let us skip the meaning of various words of this program such as public, class, static
and void. You will be able to understand them little later.
Java supports three types of comments.
■■ Single-line comments: the entire line followed by // will be ignored by javac compiler
■■ Multiline comments: javac ignores a block of statements that appear between /* and */
■■ Java documentation comments: statements that appear between /** and */. Java uses these com-
ments to generate html pages for classes.
Often, novice Java developers face many errors during their Java application development. How-
ever, most of the errors can be easily debugged by carefully examining the program as we create it.
Errors can be classified into two types:
■■ Syntax errors: These errors are reported to users during compilation phase and indicate the
mistakes in Java syntax.
■■ Semantic errors: These errors are reported to users during run-time phase and indicate errors in
the program logic or the program tries to perform illegal Java operation.
In Java SE 7, byte, short, int, and long variables can also be expressed using the binary number sys-
tem. To specify a binary value, add the prefix 0b or 0B to the number. Example 1.2 shows variables
with binary values
In Java SE 7 and later, any number of underscore characters (_) can appear anywhere between digits
in numerical values, which can improve the readability of your code. Example 1.3 shows other ways
in which the underscore can be used
Table 1.1 depicts wrapper classes of primitive data types along with the size and value ranges for
primitives. These wrapper classes are available in the package named java.lang, and each class pro-
vides a collection of methods to manipulate the wrapped data.
Operator Example
Assignment(=) int a = 100;
Addition & assignment (+=) a + = 100;
Subtraction & assignment (–=) a – = 100;
Multiplication & assignment (*=) a * = 100;
Division & assignment ( /=) a / = 100;
Reminder & assignment (%=) a % = 100;
Operator Example
Addition (+) a = a + b;
Subtraction (–) a = a – b;
Multiplication (*) a = a * b;
Division (/) a = a / b;
Reminder (%) a = a % b;
Operator Example
Unary + +a;
Unary – – a;
++ ++a & a++; increments a by 1
–– – – a & a – –; decrements a by 1
! !y; negates y
== a == b
Operator Example
Greater than (>) a >b
Greater than or equal to (>=) a >= b
Less than (<) a <b
Less than or equal to (<=) a <= b
Not equal to (!=) a != b
Logical AND (&&) (a > b) && (a > c)
Logical OR (||) (a > b) || (a > c)
Logical NOT (!) complement
Ternary (?:) Typical C style if-then-else operator
Operator Example
Bitwise AND (&) a&b
Bitwise OR (|) a|b
Bitwise NOT (~) One’s complement
Bitwise XOR (^) a^b
Left shift (<<) One bit left
Right shift (>>) One bit right
Unsigned right shift (>>>) Shifts a 0 into left-most position
Operator Example
instanceof, compares object to a specified type a instanceof Integer
Java follows the same operator precedence as C language to evaluate a given Java expression. Fur-
ther, we will introduce brackets to expressions as and when required in order to avoid the ambiguity
during the evaluation of expressions. Example 1.5 illustrates the evaluation of an arithmetic expres-
sion. Normally, we would follow type2 with lots of brackets than type1.
int x = 100;
long y = x; // upcasting
int z = (int)y; // downcasting
100 + “hello” becomes “100hello” // concatenation
Java 1.5 and later versions of it supports automatic conversion of primitive data types to their wrapper
classes in assignment statements and method as well as constructor invocations. This conversion is
known as auto-boxing or simply boxing. Java also supports automatic unboxing, where wrapper types
are automatically converted into their primitive equivalents as shown in Example 1.7.
Integer i = 5; // auto-boxing
int j = 0;
j = new Integer(5); // unboxing
// WelcomeMe.java
E:\Rajkumar\javacourse\basics>javac WelcomeMe.java
E:\Rajkumar\javacourse\basics>java WelcomeMe Rajkumar
Hello Rajkumar
E:\Rajkumar\javacourse\basics>
The println() method displays the output by concatenating the string Hello with the command line argu-
ment value Rajkumar. Understand, args is a string array; thereby users can transmit any number of values
from the command prompt. The meaning of System.out will be explained to you in Chapter 14.
Similar to reading strings from command line, other primitive data types can also be read using
wrapper class methods. For example, other wrapper classes provide parseXXX() methods to parse
primitive types such as int, long, float and double. Here, XXX denotes a primitive data type, either int,
float, long or double. Obviously, parseInt() method from Integer wrapper class converts the given string
equivalent of integer into int. Listing 1.3 illustrates the use of parseInt() to find the sum of two numbers.
// SumIt.java
import java.io.*;
E:\Rajkumar\javacourse\basics>javac SumIt.java
E:\Rajkumar\javacourse\basics>java SumIt 10 20
Sum: 30
E:\Rajkumar\javacourse\basics>
Here, parseInt() method will throw an exception named NumberFormatException which is of type
IOException. That is, parseInt() expects integer, say, “100.” Anything else will throw an exception.
For instance, giving “12.00” will throw this exception. Exception can be handled using try-catch
statements as shown in Listing 1.4.
// SumIt2.java
import java.io.*;
E:\Rajkumar\javacourse\basics>javac SumIt2.java
E:\Rajkumar\javacourse\basics>java SumIt2 15 20
Sum: 35
E:\Rajkumar\javacourse\basics>
In this application, users are reported with a message, Enter 2 integers, when they fail to supply
two integers through command prompt. Try block contains all Java statements that are likely throw
exceptions and catch block will define an exception that is likely to happen. Note that a try block can
follow one or more catch() blocks handling several exceptions. Exception handling is discussed in
detail in Chapter 7.
1.8.2 Scanner
The Scanner class from java.util package allows the user to read numerical values from either key-
board (i.e. System.in that is a standard input device) or file without having to convert them from
strings and determine whether there are more values to be read. Some of the important methods in
Scanner class are shown summarized Table 1.8.
Method Returns
int nextInt() Returns the next token as an int
long nextLong() Returns the next token as a long
float nextFloat() Returns the next token as a float
double nextDouble() Returns the next token as a long
Finds and returns the next complete token from this scan-
String next() ner and returns it as a string; a token is usually ended by
whitespace such as a blank or \n
Returns the rest of the current line, excluding any line sepa-
String nextLine()
rator at the end
void close() Closes the scanner
Note that if the next token read is not of a specific type, Java will throw an exception, InputMis-
matchException. One final word about tokens, a token is a group of characters in the input, which
ends with any of the four whitespace characters, blankspace, \r, \t and end of file by default. Tokens
can also be parsed based on any user-defined character, by using useDelimiter() method (Listing 1.5).
// PrintName.java
import java.io.*;
import java.util.*;
E:\Rajkumar\javacourse\basics>javac PrintName.java
E:\Rajkumar\javacourse\basics>java PrintName
Enter your first name: Rajkumar
Enter your last name: Kannan
Your name is Kannan Rajkumar
E:\Rajkumar\javacourse\basics>
The above application begins with importing all classes available in java.util package, as Scan-
ner is defined in util package. Scanner object is instantiated to read from keyboard using System.in
stream. The method nextLine() reads a string with new line character from keyboard. Further, this
application uses print() method instead of println() to display a string. Here, the cursor will wait on
the same line for the user to give input values.
One final note about Scanner, other nextXXX() methods reading primitive data will not read new-
line character that is appended to input string while typing values in the keyboard. This will return
newline character also as a token, which has to be discarded while reading primitive data from key-
board, by simply calling a dummy nextLine() method. Another obvious solution will be to set up a
new scanner for primitive data types. The following application calculates the sum of two integers
using nextInt() method (Listing 1.6).
// PrintSum.java
import java.util.*;
int a = sc.nextInt();
// Step3: get second number
System.out.print(“Enter integer2: ” );
int b = sc.nextInt();
// Step4: discard \n
sc.nextLine();
// Step5: get name
System.out.print(“Enter your name: ” );
String name = sc.nextLine();
// Step6: show
System.out.println(“Hello ” + name + “ Sum is ” + (a+b));
}
}
E:\Rajkumar\javacourse\basics>javac PrintSum.java
E:\Rajkumar\javacourse\basics>java PrintSum
Enter integer1: 30
Enter integer2: 20
Enter your name: Rex Peter
Hello Rex Peter Sum is 50
E:\Rajkumar\javacourse\basics>
1.8.3 BufferedReader
Before Scanner class was introduced, in earlier Java versions, most of the Java developers were using
BufferedReader class from io package to read data from keyboard. It provides one important method
named nextLine() that reads a string from keyboard, so that the string can be parsed into specific
primitive types, using parseXXX() methods of the wrapper classes, as before.
Now, let us develop a simple application that will calculate the area of a circle. First, we need to
identify the set of steps (called algorithm) to be carried out to accomplish this task. The steps are writ-
ten as comments in the following code snippet (Listing 1.7).
import java.io.*;
public class CircleArea
{
public static void main ( String args[] ) throws IOException
{
// Step1: get radius of circle
// Step2: calculate area of circle
// Step3: print the calculated area
}
}
Now, we must convert each step into the corresponding Java statement, which will result in the
r equired application, as shown in Listing 1.8. Here, InputStreamReader reads characters from com-
mand prompt, buffers them and supplies those characters to BufferedReader class. Note that parse-
Double() reads radius as a double value.
// CircleArea.java
import java.io.*;
public class CircleArea
{
public static void main ( String args[] ) throws IOException
{
BufferedReader in = new BufferedReader (
new InputStreamReader ( System.in ) );
// Step1: get radius of circle
System.out.print ( “Enter radius: ” );
double radius = Double.parseDouble (in.readLine());
// Step2: calculate area of circle
double area = 3.14159 * radius * radius;
// Step3: print the calculated area
System.out.println ( “Area of circle is: ” + area );
}
}
E:\Rajkumar\javacourse\basics>javac CircleArea.java
E:\Rajkumar\javacourse\basics>java CircleArea
Enter radius: 5.0
Area of circle is: 78.53975
E:\Rajkumar\javacourse\basics>
1.8.4 DataInputStream
DataInputStream is yet another class that provides methods to read primitive data types from key-
board. Like BufferedReader, this class supports readLine() method to read a string from keyboard.
Then, the string can be parsed into specific primitive types using parseXXX() methods of wrapper
classes as before. In Listing 1.9, let us calculate the area of ellipse using DataInputStream class.
// EllipseArea.java
import java.io.*;
public class EllipseArea
{
public static void main ( String args[] ) throws
IOException
{
// Step1: create stream
DataInputStream in = new DataInputStream
( System.in );
// Step2: get point 1
System.out.print ( “Enter point 1: ” );
int f = Double.parseInt (in.readLine());
// Step3: get point 2
System.out.print ( “Enter point 2: ” );
int g = Double.parseInt (in.readLine());
// Step4: calculate area
int area = 3.14159 * f * g;
// Step5: show result
System.out.println ( “Area of ellipse is: ” +
area );
}
}
E:\Rajkumar\javacourse\basics>javac EllipseArea.java
E:\Rajkumar\javacourse\basics>java EllipseArea
Enter point 1: 4
Enter point 2: 6
Area of ellipse is: 75.39815999999999
E:\Rajkumar\javacourse\basics>
Buffering can also be added by using BufferedInputStream between System.in and DataInput-
Stream as shown in Example 1.8.
Example 1.8.
1.8.5 Console
Finally, Java supports one more advanced alternative to read strings from command prompt. Two
important methods Console supports are readLine() to read a string and readPassword() that reads a
string that is invisible while typing. In this application, valueOf() converts character array into a string
(Listing 1.10).
// ConsoleTest.java
import java.io.*;
public class ConsoleTest
{
public static void main(String[] args) throws IOException
{
// get Console object
Console c = System.console();
// get name
System.out.print(“Enter user name: ” );
String s = c.readLine();
// get password
System.out.print(“Enter password: ” );
char[] pwd = c.readPassword();
System.out.println(“You typed: ” + s + “,” + String.
valueOf(pwd));
}
}
E:\Rajkumar\javacourse\basics>javac ConsoleTest.java
E:\Rajkumar\javacourse\basics>java ConsoleTest
Enter user name: admin
Enter password:********
You typed: admin,helloraj
E:\Rajkumar\javacourse\basics>
1.9 Summary
1. Java application can be edited using any editor such as JEdit and even Notepad
2. Java application is compiled with javac compiler and interpreted with Java interpreter
3. Javac generates byte code from source Java file which is a platform-independent code
4. Errors can be syntactic errors or semantic errors
5. Java supports primitive data types and their equivalent wrapper classes
6. Constants can be created using public static final access type
7. Java has a wealth of operators
8. Java supports many type casting features such as upcasting, downcasting, auto-boxing and
unboxing
9. Java application can receive input values using command line, Scanner class, BufferedReader
class, DataInputStream as well as Console class
Key terms
Review questions
Multiple-choice Questions
1. Consider the following program:
import java.lang.*;
public class ClassA
{
// code for the class
}
What should be the name of the java file containing this program?
a. lang.java b. ClassA.java
c. ClassA d. ClassA.class
e. Any file name with the java suffix will do
4. What will be the output for the code segment shown below?
a. 100 b. 200
c. 100100 d. Compilation error
5. Choose the correct output for the following code:
It will throw
a. NumberFormatException b. IOException
c. InputMismatchException d. None of the above
a. 3 b. 7
c. 1342 d. 10
a. –2 b. 2
c. –6 d. 6
String b = Integer.toBinaryString(x);
System.out.println(b);
}
}
a. 10100000 b. 00001010
c. 1010 d. 0101
a. 10100000 b. 00001010
c. 1010 d. 0101
a. 10 8 b. 12 12
c. 8 12 d. 8 8
a. A A b. h h
c. a a d. F F
14. What will be the output for the source code below?
int a = 10, b = 5;
int c = 20 - (++b) - a--;
System.out.println(a + b + c)
}
}
a. 19 b. 20
c. 21 d. 22
a. 20 b. ob1010ob1010
c. oB10101010 d. 40
a. ob101010 b. OB101010
c. 10101000 d. 00101010
a. 200 b. 200.0
c. Compilation error d. Runtime exception
a. True b. False
c. 0 d. Compilation error: b not initialized
Answers
1. b 2. c 3. b 4. c 5. d 6. a 7. b 8. a 9. c 10. c
11. b 12. c 13. c 14. d 15. a 16. b 17. a 18. d 19. c 20. a
21. d
Short-answer Questions
1. What is internet and WWW?
2. What is JDK and J2SE?
3. Explain JRE.
4. Explain java compiler and interpreter.
5. Explain primitive data types, variables and literals.
6. What is the range of values for each primitive data types?
7. How to define Java constants?
8. Explain upcasting, downcasting, boxing and unboxing.
9. Explain command line arguments with an example.
10. Explain the methods of Scanner class.
11. Explain Console class and its methods.
Exercises
1.1 Write a program that will read an integer and display its ASCII equivalent.
1.2. Write a program that will read a character and display its numeric value.
1.3. Write a program to display the size, minimum value and maximum value of all Java data types
(Hint: use constants such as Integer.SIZE, Integer.MIN_VAUE and Integer.MAX_VALUE).
1.4. Develop a Java application to display a string Hello Java five times.
1.5. Read five integers from command line and calculate the mean, median and mode of the
numbers.
1.6. Write a program to display the result of the following expressions (assume int i = 1, double
d = 1.0);
■■ a = a + 5 + 35/8;
■■ d = 2.5 + (++a) + 4 * a + d;
1.7. Write a program to convert Indian rupees into pounds (GBP) and US dollars (USD).
1.8. Write a program for temperature conversion.
1.9. Calculate body mass index (BMI) of a person given height (in cm) and weight (in kg). BMI is
weight (in kg) divided by height squared (in meters).
1.10. Write a program to generate a character A and display it.
1.11. Write a program to solve a quadratic equation (Hint: Math.sqrt() gives square root).
1.12. Write a program that reads account balance and interest rate from a customer and calculate the
interest earned by him in one year.
1.13. Write a program that reads a number and checks whether it is a two-digit number or not.
1.14. Write a program that converts the given hex number into its octal equivalent.
1.15. Write a program to calculate the electrical resistance of a wire (Hint: The electrical resistance
R of a cylindrical wire with length l (in meter) and diameter d (in meter) can be computed from
the area A of its diameter (m2) and the resistivity P of the material (rho, meter times Ohm).
Objectives
■■ To introduce different conditional statements such as if, if-else, if-else-if and nested if statements
■■ To implement the revised CircleArea and Biggest2 application with if statement
■■ To apply if-else statement to Divisible application
■■ To implement CalcGrade application with if-else-if statement
■■ To explain the importance of conditions and how control flows to different parts of a program
■■ To explain the relation between if statement and logical operators
■■ To check the given year is leap or not
■■ To implement switch statement for ArithCalculator application
■■ To introduce switch statement with string case
■■ To explain looping structures such as while, do-while and for statements
■■ To implement nested loops for MultiplicationTable application
■■ To explain break, continue and assert statements
2.1 Introduction
Thus far, all of our programs follow sequential execution. That is, program execution starts at the
first statement inside main() method and continues till it reaches the end of main(), in the order they
appear. As a next step, Java supports a variety of control flow statements such that the sequence of
execution of statements of a Java application can be altered. The flow of control can be changed based
on some decisions or conditions. We can also make a certain block of statements to be executed sev-
eral times depending on some conditions. This chapter aims to introduce the readers to those features
with which a rich collection of Java applications can be developed.
2.2.1 if Statement
The if statement checks a condition first. If the condition is evaluated to true, it executes a block
of statements inserted in between curly braces. Then, the execution continues in the next line of the
program. The condition can be a simple boolean condition or a complex condition designed based
on relational and/or logical expressions. The syntax shown in Figure 2.1 explains the if statement.
if (condition)
{
// block of statements
}
In Listing 1.8, CircleArea.java application, we have calculated the area of circle by reading the
value of radius. Suppose, a user enters a zero or some negative value for radius, the program will show
undesired results. So, it is always advisable to check for them first before calculating the area by using
the if statement, as shown in Listing 2.1.
// CircleArea.java
import java.io.*;
{
System.out.println(“Enter a positive number for
radius”);
return; // control goes back to command
prompt
}
// Step4: calculate area
double area = 3.14159 * radius * radius;
// Step5: print result
System.out.println ( “Area of circle is: ” + area );
}
}
Enter radius: 0
Enter positive number for radius
In this application, if a user enters 0 or a negative number, the application gives a message asking
to enter some positive number for radius and terminates execution.
// Biggest3.java
import java.io.*;
Observe in this program that the second if statement will be executed irrespective of whether the
first if statement is evaluated to true or not.
if (condition)
{
// true-block of statements
}
else
{
// else-block of statements
}
Listing 2.3 shows an example that checks whether a given integer is divisible by another integer
or not, using reminder operator (%) available in Java. A number is divisible by another number if the
result of integer division gives reminder zero. The input values have to be entered in the command
prompt and are collected from args.
// Divisible.java
import java.io.*;
if (condition1)
{
// true-block of statements for condition1
}
else if (condition2)
{
// true-block of statements for condition2
// similarly we can have any number of else-if statements
}
else
{
// else-block of statements.
// This block will be executed if neither condition1 nor
condition2 is true
}
In order to illustrate if-else-if statement, we will develop a Java application that will calculate grade
(such as S, A, B, C and F) of a student depending on his/her marks as shown in Listing 2.4.
// CalcGrade.java
import java.util.*;
import java.io.*;
Enter mark: 86
Grade = A
Here any one of the if statements will be executed, depending on the marks of a student. If the given
mark does not satisfy any of the if statements, then the else part will be executed assigning F to grade.
if (condition1)
{
if (condition2)
{
// true block, here condition1 and condition2 are true
}
else
{
// else block for condition2, here condition1 is true, but
condition2 is false
}
}
else
{
// else block for condition1. Here condition1 is false and we
don’t care for condition2
}
Consider the program snippet depicted in Example 2.1. Here a two-level nested if statement is used
to check whether num is between 80 and 90.
if ( num > 80 )
if ( num < 90 )
System.out.println( num + “ is between 80 and 90”);
Similarly, a three-level nesting can be done using three if statements as shown in Example 2.2.
If ( num > 80 )
if ( num < 90 )
if ( num % 2 == 0 )
System.out.println( num + “ is between 80 and 90 and
even” );
Multilevel nested if statement is generally not recommended because of its complex structure. Some
of the nested if statements can be avoided by using logical operators as discussed above. Also software
development practices emphasize us to introduce curly braces as and when required with control
structures, to avoid unexpected results during the evaluation of expressions. Let us now rewrite the
above example with proper curly braces to enhance readability, as depicted in Example 2.3.
if ( num > 80 )
{
if ( num < 90 )
{
if( num % 2 == 0 )
{
System.out.println( num + “ is between 80 and 90 and
even” );
}
}
}
// LeapYear.java
import java.util.*;
switch ( expr )
{
case literal-1:
case literal-1 body; break;
case literal-2:
case literal-2 body; break;
case literal-3:
case literal-3 body; break;
default:
default body
}
Unlike if statements that contain a condition in the parentheses, switch contains an expression.
Here, expression is evaluated first. Then, starting from top to bottom, if the value of the expression
matches with a case, then its body of statements will be executed. Since break statement is present,
control is brought out of switch statement. If no case matches, then the body of the default case will
be executed.
A switch statement works with the byte, short, char and int primitive data types. It also works with
enumerated types, the string class (Java 1.7 onwards) and few wrapper classes such as Character,
Byte, Short and Integer.
Now, let us design an arithmetic calculator that uses switch statement to check the operation type
and calculate accordingly. Listing 2.6 depicts arithmetic calculator application.
// ArithCalculator.java
import java.io.*;
Enter operand1: 10
Enter operand2: 20
Enter operator: +
Result: 30
Enter operand1: 10
Enter operand2: 20
Enter operator: &
Illegal Operator
In this example, an arithmetic operator has to be read as a character, for that we use charAt()
method from string class that returns a specific character given a location. Switch statement branches
to any of the cases depending on opr and performs the necessary operation and comes out of switch,
where the result is printed. A word of caution, failure to use break statement will result the control to
continue executing subsequent case statements.
// StringSwitch.java
import java.util.*;
int passMark;
switch(name.toLowerCase())
{
case “ba” :
case “bcom” :
case “bsc” : passMark = 40; break;
case “ma” :
case “mcom” :
case “msc” : passMark = 50; break;
default : System.out.println(“Unavailable
programme”);
}
System.out.println(“Minimum pass mark for ” +
name + “ is ” + passMark);
}
}
Here, toLowerCase() method of string class converts the user input into lowercase string and
switch branches accordingly. This application calculates the minimum pass marks to be secured by
bachelors or masters students. It assigns a passMark to either 40 or 50 depending on whether cases are
ba, bcom and bsc or ma, mcom or msc. Then it displays the pass marks.
while(condition)
{
// block of statements
}
Initially, condition is evaluated in the while loop. If it is true, then the block of statements will be
executed. This will continue as long as the expression result is true. If the condition is false, the loop
body will be skipped and the first statement after the while loop will be executed.
do
{
// block of statements
}
while (condition);
Notice that the condition appears at the end of the loop, so the statements in the loop are executed
once before condition is tested. If the condition is true, the control jumps back up to do statement, and
the statements in the loop are executed again. This process repeats until the condition is false.
Once index variables are initialized and the condition is evaluated to true, then the body of the loop
will be executed. The index variables are either incremented or decremented, so that condition can be
checked again, and accordingly the body of the loop will be again and again executed.
Listing 2.8 illustrates the working of the three looping statements by simply printing values 1 to 10.
// Loops.java
// print 1 to 10 using while, do-while and for loops
public class Loops
{
public static void main(String[] args)
{
// using for loop
for (int i = 1; i <= 10; i++) // initialize, check &
increment
{
System.out.print(i); // print
}
// using while loop
int i = 10; // initialize
while (i >= 0) // check
{
System.out.print(i); // print
i--; // decrement i
}
// using do-while loop
i = 1; // initialize
do
{
System.out.print(i); // print
i++; // increment i
} while (i <= 10); // check
/* indefinite loops
while(true) // you can use while with true as condition
{
System.out.println(“Hello”); // displayed until you
press CNTL-C
}
123457891010987654321012345678910
// MultiplicationTable.java
// multiplication table of 4x4
public class MultiplicationTable
{
public static void main(String[] args)
{
// using for loop
for (int i = 1; i <= 4; i++) // for each row
{
for (int j = 1; j <= 4; j++) // for each column
{
System.out.print(i * j + “\t”); // multiply row
and col value
}
System.out.println(“\n”); // continue in next line
}
}
}
1 2 3 4
2 4 6 8
3 6 9 12
4 8 12 16
Type1 just ensures whether the boolean expression is true, otherwise it will throw an error. The
second type checks whether the boolean expression is true. If true, it will execute the expression that
is mentioned in the second part of the assert statement. The expression should not return void. An
example of assert statement is given in Listing 2.10.
// AssertEx.java
public class AssertEx
{
public static void main(String[] args)
{
int x = Integer.parseInt(args[0]);
assert( x > 0);
System.out.println(“You typed a +ve number”);
}
}
javac AssertEx.java
java -ea AssertEx 10
You typed a +ve number
Here, assert ensures the command line parameter value is greater than 0. If it is zero, control con-
tinues with next statement. If it is not greater than 0, AssertionError will be thrown. Remember you
need to run the program with –ea option.
2.4 Summary
1. There are four types of conditional statements – if, if-else, if-else-if, nested if statements
2. Conditions for if statements can be boolean, relational and logical conditions
3. Java loops allow us to execute a set of statements iteratively several times
4. Every looping statement (such as while, do-while and for) will define four parts in any order –
initialize index variables, check condition, execute body of loop and increment or decrement
index variables
5. Nested loops are used to achieve iteration at multiple levels
6. Curly braces should be introduced as and when required with conditional and looping s tatements
to avoid ambiguity
7. Control flow can be manually altered with break and continue statements
8. Break and continue statements should be used only inside a loop and not inside any block of
statements.
9. Assert statement checks whether an assumption is true. Otherwise, Java generates Assertion
Error. Assert statement can also have an expression that will be executed when the assertion is ture.
Key terms
Review questions
Multiple-choice Questions
1. What will be the output for the program shown below?
a. Prints all even numbers from 0 to 100 b. Prints all odd numbers from 0 to 100
c. Compilation error d. Runtime error
System.out.println(i + “: ” + (char)i);
}
}
a. Prints all ASCII characters from 0 to 255 b. Prints binary equivalents from 0 to 255
c. Prints bytes equivalents from 0 to 255 d. Prints binary equivalents from 1 to 255
a. Test A b. Test B
c. Test C d. None of the above
13. What will be the value of val that will print “Test B”?
a. 9 b. 10
c. Any number greater than 9 d. Test B can never be printed
14. Find out the output:
a. 0, 1, 2 b. 0, 1
c. 1, 2 d. 1, 2, 3
a. 50 b. 52
c. 54 d. None of the above
a. One b. Two
c. Three d. Not a number
a. Ball
b. Ball cat
c. Ball cat not a character
d. Not a character
25. Find out the output:
a. ball cat
b. ball
c. ball cat not a character
d. Compilation error as default appears in the beginning
}
}
}
a. apple
b. ball
c. ball cat
d. ball cat not a string
e. not a string
f. Error: String for cases not allowed
a. 1, 2, 3 b. 1, 2
c. Prints i indefinitely d. Runtime exception
}
System.out.println(i);
}
}
a. 9 b. 10
c. 11 d. Exception as scope of i is limited to inside
for loop
a. Line 1
b. Line 1 Line 2 Line 3
c. Line 1 Line 2 Line 3 Default line
d. Compilation error: continue statement inside switch not allowed
System.out.println(“Line 2”);
}
}
Answers
1. b 2. c 3. a 4. a 5. b 6. a 7. b 8. b 9. a 10. b
11. c 12. a 13. d 14. c 15. a 16. d 17. d 18. d 19. a 20. b
21. c 22. a 23. a 24. c 25. a 26. b 27. b 28. b 29. b 30. c
Short-answer Questions
1. Explain if statement with an example.
2. Explain if-else statement with an example.
3. Explain nested if statement with an example.
4. Discuss switch statement with an example.
5. Explain while loop with an example.
6. Explain do-while loop with an example.
7. Explain for loop with an example.
8. Discuss assert statement with an example.
Exercises
Objectives
■■ To explain how to declare one-dimensional, two-dimensional and multidimensional arrays
■■ To explain different array types
■■ To make developers learn how to choose arrays
■■ To illustrate accessing one-dimensional array elements with StudentMarks application
■■ To develop application for sequential search
■■ To develop application for binary search
■■ To implement BiggestN application with for-each statement
■■ To develop application for Euclidean distance
■■ To develop application for reversing an array
■■ To explain two-dimensional arrays by implementing TopStudent application
■■ To understand three-dimensional arrays by storing semester-wise marks
■■ To find the transpose of a two-dimensional matrix
3.1 Introduction
In the CalcGrade application Listing 2.4 of Chapter 2, we have illustrated a method to calculate a
grade from the mark of a student in a given course. Suppose a student has obtained marks in four
courses in a particular semester. So, a single variable cannot hold all these four marks. To solve this
problem, we have a handy static data structure that will store a collection of values under a single
name, namely arrays. In this chapter, we will learn how to create and use arrays to store a collec-
tion of values. Apart from studying the basic notion of arrays, the readers will also be introduced to
some interesting applications such as sequential search, binary search, finding Euclidean distance,
reversing arrays without copying and finding the transpose of a given matrix.
Before the values are stored in array locations, the array has to be declared by specifying its type and
required size as shown in Example 3.1. Each array is identified with its name, also called reference. Once
declared, the array can be initialized with values of the specified type. Array values can also be initialized
during declaration time using curly braces. Example 3.1 shows different instances of declaring arrays.
The StudentMarks application (shown in Listing 3.1) receives MAX marks from command line
and calculates the percentage of those marks.
// StudentMarks.java
import java.io.*;
// find sum
int sum = 0;
for(int i = 0; i < MAX; i++)
sum += marks[i];
// show average
System.out.println(“Average: ” + ((double)sum/MAX));
}
}
C:\jdk>java StudentMarks 55
Enter four marks
Note that, the array is not just declared with the size 4, instead we have defined a constant MAX,
which will be used for declaration. Also, before calculating the sum of marks, the if statement is used
to verify whether the command line argument contains four values, otherwise the control will return
to the command prompt.
// SequentialSearch.java
public class SequentialSearch
{
public static void main(String[] args)
{
// Step1: check command line arguments
if(args.length < 2)
{
System.out.println(“Enter list of numbers and key to
search”);
return;
}
E:\Rajkumar\javacourse\basics>javac SequentialSearch.java
E:\Rajkumar\javacourse\basics>java SequentialSearch 1 2 3 4 5 6 7
8 9 8
8 exists first at location 7
E:\Rajkumar\javacourse\basics>java SequentialSearch 1 2 3 4 5 6 7
8 9 10
10 does not exist in given list
Once a set of numbers followed by the key to be searched in the command prompt are entered, the
key is compared with every array element to check whether they are same. At the end, the location of
the key is returned as output if it exists.
// BinarySearch.java
public class BinarySearch
{
public static void main(String[] args)
{
if(args.length < 2)
{
System.out.println(“Enter list of numbers and key to
search”);
return;
}
lb = mid + 1;
else
{
// key matches with mid element
// so remember mid element’s location
loc = mid;
break;
}
E:\Rajkumar\javacourse\basics>java BinarySearch 1 2 3 4 5 6 7 8 9
4
4 exists at location 3
E:\Rajkumar\javacourse\basics>java BinarySearch 1 2 3 4 5 6 7 8 9
50
50 does not exist in given list
E:\Rajkumar\javacourse\basics>java BinarySearch 1 2 3 4 5 6 7 8 9
–5
–5 does not exist in the given list
Binary search assumes the given input array is pre-sorted. The midpoint is calculated between the
first element and the last element of the array. If key is less than the midpoint element, it indicates that
key might be present in the left half of the array and search is continued only in the left half. This way
binary search effectively eliminates searching the right half. Therefore, efficiency in binary search
is improved by 50%. On the other hand, if key is greater than the midpoint element, search will be
continued only with the right half of the array. This processing is repeated until the midpoint element
is the key or the lower bound crosses the upper bound of the reduced array.
Here, index-variable iterates through the array, specified by array-name, and body of statements
will be executed until array has more elements.
For instance, the following program snippet shown in Example 3.2 prints the marks of a student
stored in the array marks using for-each statement.
In this application, let us extend our previous version of Biggest3 application in order to find the big-
gest number among the given n numbers. In Listing 3.4, we have introduced for-each statement to
move through the numbers during the calculation.
// BiggestN.java
import java.io.*;
public class BiggestN
{
public static void main(String[] args) throws IOException
{
// Step1: Create buffered reader
BufferedReader in = new BufferedReader(new
InputStreamReader(System.in));
3.7 P
roblem: Finding Euclidean Distance
between Two Vectors
Euclidean distance compares the distance between two one-dimensional arrays (one-dimensional
arrays are also called vectors). It is calculated as the square root of the sums of the squares of the
differences between corresponding entries in the arrays. It is used to find the similarity between two
vectors. If Euclidean distance is zero, then the given two vectors are the same. Listing 3.5 explains the
functioning of Euclidean distance.
// Euclidean.java
import java.util.*;
// instantiate arrays
int[] arr1 = new int[size];
int[] arr2 = new int[size];
Here, Math.pow() method finds the power while Math.sqrt() calculates the square root of the argu-
ments. Rest of the code is self-explanatory.
// ReverseArray.java
import java.util.*;
E:\Rajkumar\javacourse\basics>java ReverseArray
Enter array size
5
Enter array elements
1 2 3 4 5
Reversed array elements
5 4 3 2 1
Here, with a temporary variable the first element and last element is interchanged. Then second
element and the previous element to the last are interchanged. This swapping is continued half of the
size of the input array.
// TopStudent.java
import java.io.*;
public class TopStudent
{
sum += marks[i][j];
}
73
Enter marks of student 2
Enter mark 0 :
93
Enter mark 1 :
83
Students average marks: 68.0 58.0 88.0
Top student: 2
His average is : 88.0
The above algorithmic steps can be converted into a code snippet as shown in Example 3.4.
// declare variables
int nSemesters = 4; // assume number of semesters is 4
int nStudents = 50; // number of students = 50
int nCourses = 5; // number of courses = 5
// initialize values
for (int i = 0; i < nSemesters; i++)
for (int j = 0; j < nStudents; j++)
for (int k = 0; k < nCourses; k++)
marks[i][j][k] = sc.nextInt();
// TransposeCopy.java
import java.util.*;
// Step5: transpose
for(int i = 0; i < rows; i++)
for(int j = 0; j < cols; j++)
arr2[j][i] = arr[i][j];
// Step6: show result
System.out.println(“Transpose Matrix”);
for(int i = 0; i < cols; i++)
{
for(int j = 0; j < rows; j++)
System.out.print(arr2[i][j] + “ ” );
System.out.println();
}
}
}
E:\Rajkumar\javacourse\basics>java TransposeCopy
Enter rows
2
Enter cols
3
Enter array elements
1
2
3
4
5
6
Transpose Matrix
1 4
2 5
3 6
Suppose you have a larger matrix say order 1 million by 1 million. Then you feel you are wasting
memory by allocating space for the destination array. So you just want to eliminate destination array
and do not want to reserve space for the target array indeed. Listing 3.9 shows a modified application
that will find transpose without copying elements to another array.
// Transpose.java
import java.util.*;
E:\Rajkumar\javacourse\basics>java Transpose
Enter array size
3
Enter array elements
1
2
3
4
5
6
7
8
9
Transpose Matrix
1 4 7
2 5 8
3 6 9
Here by keeping the inner loop j to begin with (i+1), we are ignoring diagonal elements as they
need not be swapped.
3.11 Summary
1. Arrays store values of the same type
2. Arrays can have unlimited dimensions from one dimension, two dimensions, three-dimensions
to n-dimensions
3. Array index identifies its elements
4. Java needs arrays to be declared and initialized first before accessing array elements
5. For-each statement can be used with arrays
Key terms
Review questions
Multiple-choice Questions
1. Which of these statements are correct methods to create arrays?
a. abc b. a
c. Compilation error d. Runtime error
a. 10 20 30
b. 10
c. Some random value representing the address of the handle array
d. Runtime error
a. 15 b. 2222
c. 1111 d. 3333
a. a b. b
c. c d. d
a. 8, 8 b. 4, 4
c. 8, 16 d. 16, 16
a. 4, 16 b. 8, 32
c. 8, 8 d. 16, 16
13. What is the output?
a. 0 b. ‘0’
c. null d. 1
14. You want to initialize all of the elements of a int array arr to the same value equal to 10. What
could you write? Assume the array has been correctly instantiated.
(a) for(int i=1; i<a.length; i++) a[i] = 10;
(b) for(int i=0; i<=a.length; i++) a[i] = 10;
(c) for(int i=0; i<a.length; i++) a[i] = 10;
(d) for(int i=0; i<a.length+1; i++) a[i] = 10;
a. a b. b
c. c d. a, c
15. What is the output of the program below?
{
int[] x = {5,6,7,8,9, 10};
int[] y = x;
y[2] = 20;
System.out.println(x[2]);
}
}
a. 20 b. 6
c. 7 d. None of the above
16. What is the output?
a. 0246
b. Compilation error: int array accessed by long index variable
c. Runtime error
d. 0 2 4 6, but possible loss of precision
17. What is the output for the program below?
a. 1, 3, 5, 7 b. 0, 2, 4, 6
c. Compilation error: trying to d. Runtime error
update index variable
a. 0, 2 b. 2, 5, 6
c. 0, 2, 4, 6 d. 5, 6, 7, 8
a. 0, 2 b. 2, 5, 6
c. 0, 2, 4, 6 d. 5, 6, 7, 8
a. 0 b. 4
c. 5 d. 1
e. 3
21. What will be the values of arr after this for loop?
a. 10112 b. 10011
c. 10022 d. 21011
22. Java arrays are static. That means its size cannot be increased during runtime
a. True b. False
a. (a) b. (b)
c. (c) d. (d)
28. Find out the output:
a. 12345 b. 32345
c. 13345 d. 12445
29. Find out the output:
a. 4 b. 9
c. 6 d. Error
Answers
1. c 2. d 3. a 4. c 5. c 6. c 7. c 8. c 9. a 10. c
11. b 12. a 13. a 14. c 15. a 16. a 17. a 18. c 19. c 20. d
21. a 22. a 23. e 24. a 25. a 26. c 27. d 28. b 29. c
Short-answer Questions
1. What is an array? How do you access array elements?
2. What is 2D array? How do you access array elements?
Exercises
3.1. Read a set of values from command line and print them one at a time back to the user.
3.2. Collect integers from command line and store them in an array.
3.3. Read a line of text followed by a word to search from command line. Search for the word and
print proper message.
3.4. Find the product of two vectors.
3.5. Reverse the order of 1D array without a temporary array.
3.6. Given an array of n elements, list all duplicate elements. Do not use a temporary array.
3.7. Find the longest consecutive sequence of integers with no primes.
3.8. Develop an application for Sudoku game.
3.9. Given an array A, find its 1D and 2D Haar Wavelet Transform.
3.10. Generate 100 random integers from 0 to 9. If the sum is 300 keep these integers in an array.
In this way, generate integer array 100 times. Print a histogram saying how many times each
digit occurs.
3.11. Given a 2D, check whether the sums of each row or each column is 1.
3.12. Given a 1D array, find mean, median and mode.
3.13. Find the most frequent element in a given 1D array.
3.14. Find Pascal’s triangle.
3.15. Create 125 random numbers and store them in a 3D [5x5x5] array. Search for an element in
this array.
Objectives
■■ To introduce Java method definition and method invocation
■■ To implement Big2 application to understand methods
■■ To explain passing primitive data types to methods with AreaFunction application
■■ To generate prime numbers
■■ To introduce the power of recursion with factorial function
■■ To explain the pitfalls of recursion with Fibonacci function
■■ To design overloaded methods
■■ To explain method overloading with AdditionCalculator application
■■ To illustrate passing one-dimensional arrays to methods using SortNumbers applications
■■ To define sort() method with String array as an argument
■■ To explain passing two-dimensional arrays to methods with Recipes application
4.1 Introduction
A method is a set of Java statements, which is referred to by a name and can be called at any point in
an application simply by its name. When method name is encountered in an application, execution
of the program branches to the body of the method. After the method is executed, the control returns
to the area of the main program code from which it was called, and the program continues at the
next statement. Java uses stack to remember the address of Java statement from where the control is
transferred to the method, so that it can return to the calling place.
Modular programming applies divide-and-conquer strategy in order to divide the larger program into
a set of small pieces so that each piece of a program can be implemented as a method. Therefore, each
method can be implemented separately by different developers and integrated later to form a single appli-
cation. Also, methods support code reusability – that is the same code can be applied to multiple sets of
values. Method is also called function by earlier structured languages like C. In this chapter, we lead the
readers to the understanding of methods and how to achieve modular programming using methods.
As shown in Figure 4.1, each method will have an access-type (right now assume public static for
simplicity), value to be returned by the method, name of the method and a set of arguments. Note that
arguments are optional and a method need not return any value. If a method does not return any value,
it is indicated by void data type. Now, we shall develop a method max() that will read two integers and
calculate the biggest and return the result to the calling place. Listing 4.1 depicts the method max().
Here, the access-type is public static, return type is int, name of the method is max, there are two
arguments a & b and the method returns an int value.
variable = method-name(arguments);
Listing 4.2 illustrates the complete application for finding the biggest of the given two integers.
The method max2() will find out the biggest.
// Big2.java
import java.util.*;
Note that even though the names of variables (a and b) are same in main() and max2(), they are
totally different local copies. In other words, the scope of those variables is limited within either
main() or max2() where they are defined.
As another illustration for methods, let us develop a method cube() that will return the cube of a
number. The complete application shown in Listing 4.3 generates cubes of first 1000 integers.
//Cubes.java
public class Cubes
{
public static int cube(int i)
{
return (i * i * i);
}
Suppose we want to print the reverse of a number. Then you can use reminder operator to extract
digits and iteratively create new digits by multiplying the powers of 10 as shown in Listing 4.4.
// ReverseNumber.java
remainder = n%10;
reverse = reverse*10 + remainder;
n = n/10;
}
while(n > 0);
return reverse;
}
//DupGenerator.java
public class DupGenerator
{
public static String duplicate(String s)
{
return s + s;
}
JavaJava
HelloHelloHelloHelloHelloHelloHelloHello
// AreaFunction.java
import java.io.*;
{
int area = areaSquare(5);
System.out.println(area);
// alternatively println() method can also call a method
directly
System.out.println(areaSquare(5));
System.out.println(areaRectangle(5,3));
System.out.println(areaTriangle(5,3));
System.out.println(areaCircle(3));
System.out.println(areaCylinder(3,4));
}
}
25
25
15
7.5
18.849
131.94299
// PrimeNumber.java
prime = false;
break;
}
}
return prime;
}
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83
89 97 101 103 107 109 113 127 131 137 139 149 151 157 163 167 173
179 181 191 193 197 199 211 223 227 229 233 239 241 251 257 263
269 271 277 281 283 293 307 311 313 317 331 337 347 349 353 359
367 373 379 383 389 397 401 409 419 421 431 433 439 443 449 457
461 463 467 479 487 491 499
You can even generate millions of prime numbers. Just change the data type from int to bigger
types such as BigInteger and enjoy playing with the code.
// Factorial.java
import java.util.*;
Enter a number: 5
Factorial of 5: 120
Enter number: 2
Factorial of 2: 2
Enter number: 0
Factorial of 0: 1
Calculating factorial is even easier with recursion. The recursive function that calculates factorial
is shown in Figure 4.3.
int factorial(int n)
{
if (n == 0)
return 1;
return n * factorial(n-1);
}
A recursive function must always have a stop condition with which the execution of the function
terminates. For example in the factorial function, the factorial calculation terminates with 0!, which is
assumed to be 1. Until this, factorial function will be recursively called (Listing 4.9).
// RecursiveFactorial.java
import java.util.*;
Enter a number: 5
120
Enter a number: 10
3628800
Enter a number: –2
Exception: –2 is a negative number
Though recursion is a powerful programming technique, it demands a lot of memory space as the
state of every recursive call has to be stored in a runtime stack. Not only excessive space require-
ments, there is also a lot of re-computation involved. This is evident when you write a recursive func-
tion that generates Fibonacci sequence. The sequence of numbers 0 1 1 2 3 5 8 13 21 34 55 89 144
233 … represents a Fibonacci sequence. A Fibonacci sequence can be generated with the following
equation as shown in Figure 4.4.
F0 = 0
F1 = 1
Fn = Fn-1 + Fn-2 for n ≥ 2
A novice developer will implement this recursive function to generate Fibonacci sequence as
depicted in Figure 4.5.
fibo(int n)
{
if( n == 0)
return 0;
if( n == 1)
return 1;
return fibo(n-1) + fibo(n-2);
}
The complete application that generates Fibonacci numbers using recursion is illustrated in
Listing 4.10.
// RecursiveFibonacci.java
import java.util.*;
// Fibonacci.java
import java.util.*;
}
// if beyond 1, print f0 and f1 and proceed
System.out.print(f0 + “ ” + f1);
for(int i = 2; i <= n; i++)
{
// add previous 2 numbers
int f2 = f0 + f1;
System.out.print(“ ” + f2);
// update previous 2 numbers
f0 = f1;
f1 = f2;
}
}
■■ Type of arguments
■■ Number of arguments
■■ Order of appearance of the arguments
However, methods should not be overloaded by its return types. Example 4.1 illustrates the con-
cepts of Java method overloading with various method signatures for add() method.
Suppose we will extend our earlier Calculator application by providing overloaded methods for
adding various primitive data types (i.e. int, double, float and mixed types) as shown in Listing 4.12.
// AdditionCalculator.java
30
30.0
300.0
50.0
70.0
In AdditionCalculator application, the appropriate overloaded method will be called inside main()
depending on the input values automatically.
Listing 4.13 shows SortNumbers application that arranges the given integers in ascending order. It
defines a method sort() that takes array of numbers and sorts them. The sort() method does not have
to return the sorted sequence, as original sequence will get modified directly through the reference in
the method.
// SortNumbers.java
import java.io.*;
int n = Integer.parseInt(in.readLine());
// create array a of n size
int[ ] a = new int[n]; // to keep actual numbers
// read actual numbers
System.out.println(“Enter actual numbers: ”);
for (int i = 0; i < n; i++)
a[i] = Integer.parseInt(in.readLine());
// show
System.out.println(“Original numbers before
sorting ”);
for (int i = 0; i < n; i++)
System.out.print( a[i] + “ ”);
// call sort() method with array a
sort(a);
// show sorted sequence
System.out.println(“\nSorted sequence of numbers ”);
for (int i = 0; i < n; i++)
System.out.print( a[i] + “ ”);
}
}
negative number, zero or some positive number if the first string is less than, equal to or greater than
the second string respectively. Listing 4.14 illustrates the overloaded sort() method to perform this
alphabetic sorting of names.
The complete program that arranges the given names in alphanumeric order is depicted in Listing 4.15.
// SortNames.java
import java.io.*;
if(names[j].compareTo(names[i]) < 0)
{
// interchange values
String temp;
temp = names[i];
names[i] = names[j];
names[j] = temp;
}
}
}
}
oviya
Sorted names: anabel lavanya oviya peter rex
2 2 1 0
Recipe R = 3 0 1 0
2 1 2 1
Now, let us calculate how much ingredients we need in order to serve six people. Note that A will
serve three people. So, we need 2 × A ingredients that will serve six people, as illustrated below.
2 2 1 0
Recipe R1 = 2 × 3 0 1 0
2 1 2 1
Now let us consider the second case. Here, we will have to calculate ingredients to feed 3 people
pancakes, 12 people biscuits and 9 people waffles. Remember, our earlier recipe A will already serve
three people. We need to make one batch of pancakes, four batches of biscuits, and three batches of
waffles. Let’s represent this with the row vector as
The vector describing how much flour is needed is the first column of R. Let us represent it as a
column vector v
2
v= 3
2
Therefore, total number of cups of flour required can be calculated by taking dot product between
s and v as 1 × 2 + 4 × 3 + 3 × 2 = 20 cups. Similarly, by taking dot products with other columns we
can calculate the required ingredients such as eggs, milk and oil. These set of dot product with all
columns of the matrix is called matrix multiplication. So, we can multiply vector s with A to calculate
the required ingredients.
Therefore, to serve 3 people pancake, 12 people biscuits and 9 people waffles, we need 20 cups of
flour, 8 eggs, 11 cups of milk and 3 tablespoons of oil as shown above.
Listing 4.16 depicts calcIngredient() method that takes a vector of serving requirement and a recipe
matrix and then calculates the required number ingredients such as flour, eggs, milk and oil.
// Recipes.java
}
}
Another notable feature of this application is the power of code reusability, an important trait of
modular programming. The calcIngredient() is invoked by main() four times with different sets of
values. Otherwise, we should have defined four different methods to handle the four cases.
data-type… argument
In the method declaration, you need to specify the type followed by an ellipsis. Only one variable
length argument can be specified in a method, and this argument must be the last argument. Any
regular arguments must precede it.
Java treats a variable-length argument as an array and creates it. Arrays can also be passed to vari-
able length arguments. Listing 4.17 depicts a method show() that prints an integer and list of strings.
// ShowNames.java
id: 100
Name 0 : C
Name 1 : C++
Name 2 : Java
Name 3 : .NET
Name 4 : PhP
Name 5 : Python
id: 100
Name 0 : C
Name 1 : C++
Name 2 : Java
Name 3 : .NET
Name 4 : PhP
Name 5 : Python
4.13 Summary
1. Methods help to achieve modular programming
2. Each method is identified and called by its name
3. Methods can receive arguments. The arguments can be primitive data types, strings and
arrays
4. Method overloading allows a method name to be shared by several methods
5. Overloaded methods should differ by its arguments
6. Methods should not be overloaded by their return types
7. Array names behave as references, so a method need not return the array back to calling place
8. Method can call other methods
9. Methods can be defined with variable length arguments list
Key terms
Review questions
Multiple-choice Questions
1. Find out the output:
a[i] = a[i] + 1;
c[i] = a[i];
}
return c;
}
a. 1234512345 b. 2345612345
c. 1234523456 d. 2345623456
a. 1 2 3 4 5 b. 2 4 6 8 10
c. Compilation error d. Runtime error
a. 1 2 3 4 5 b. 2 4 6 8 10
c. Some garbage value will be displayed d. Compilation error
a. Compilation error
b. 2
c. 2.0
d. Runtime error
a. 100 b. 200
c. Overloading static and non-static d. Throws runtime exception
versions of f1() not allowed
6. Find out the output:
a. 100 b. 200
c. Overloading static versions of f1() d. RTTI encountered during run time
not allowed
a. 100
b. 100 100
c. Recursively prints 100
d. Compilation error as statements after return occurs
a. 20, 10
b. 10, 20
c. 10, 10
d. 20, 20
a. 4 b. 5
c. Array not initialized d. Syntax error in length()
a. 5 5 5 5 b. 4 4 4 4
c. 0 0 0 0 d. null null null null
15. Find out the output:
16. How will you modify STATEMENT-1 of the above example to print the following matrix:
36
25
14
a. b[r][c] = a[c][r]; b. b[r][c] = a[c][rows - 1 - r];
c. b[r][c] = a[cols - 1 - c][r]; d. b[r][c] = a[cols - 1 - c][rows - 1 - r];
case BLUE:
System.out.print(“Blue colour”);
break;
}
}
}
}
{
// call these functions
}
}
a. exchange(10,20); exchange(10.0,20.0);
b. exchange(“10”,“20”); exchange(“10.0”,“20.0”);
c. exchange(10l,20f); exchange(10.0f,20.0l);
d. None of the above
a. h
b. 104
c. Compilation error: No char version of show() exists
d. Runtime error: Unable to find char version of show()
}
public void show(float f)
{
System.out.println(f);
}
a. 10
b. 10.0
c. Compilation error: No double version of show() exists
d. Runtime error: Unable to find double version of show()
a. 10.0f
b. 10.0
c. 10
d. Runtime error: Unable to find float version of show()
Answers
1. d 2. b 3. b 4. a 5. a 6. a 7. a 8. b 9. a 10. c
11. c 12. b 13. a 14. a 15. a 16. b 17. a 18. a 19. a 20. a
21. a 22. c 23. b 24. e
Short-answer Questions
1. How do you define methods? How do you call methods in Java?
2. What is recursion? Explain recursion with an example.
3. What are the benefits and pitfalls of recursion?
4. Explain method overloading with an example.
5. Explain passing 1D arrays to methods.
6. Explain passing 2D arrays to methods.
7. Explain variable length arguments with an example.
Exercises
4.1. Develop a method squeeze() that will take an array of integers and returns an array without
duplicates.
4.2. Develop a method crypt() that will take a char array and return a modified array of chars.
Replace each character as a by c, b by d, c by e and so on.
4.3. Develop a method oddparity() that will return a boolean if the given binary array (0’s and 1’s)
has odd number of 1’s.
Objectives
■■ To explain object-oriented paradigm with encapsulation, information hiding, aggregation,
inheritance and polymorphism features
■■ To cultivate object-oriented thinking to design applications
■■ To create classes with data members and member functions
■■ To illustrate classes with Laptop application
■■ To write different access types for classes, data members and member functions
■■ To implement aggregation with OOCollege application
■■ To explain static variables and static methods
■■ To implement array of objects for Student application
■■ To implement methods with objects as arguments for BookStore application
■■ To understand the scope with this reference
5.1 Introduction
In chapters 1–4, the readers were exposed to Java as a structured programming language. Java lan-
guage was used to develop applications based on algorithmic steps and modular programming paradigm.
Although, Java can be used as a structured programming language, the power of Java is its object-oriented
features. Chapters 5–7 present Java as a language for object-oriented programming (OOP) paradigm.
colour
height
weight
family
bark
watch
sniff
(a) (b)
Figure 5.1. (a) Dog as a Real-world Entity (b) Dog with a Belt
of data from program leads to a software that is difficult to maintain and understand. Later, a new
software development methodology evolved, which allowed developers to bind data and functionality
together, and it is known as OOP methodology. Java is one of the important OOP languages, with a
wealth of features for object-oriented system development (OOSD).
OOP languages model the given task as objects, in other words, real-world entities such as laptops,
cars, bank accounts, cats and dogs. Structured programming languages specify conditions that every
object has to adhere while creating object, whereas OOP emphasizes the language to support objects’
conditions. For instance, in structured programming, a dog is represented by a set of functions such as
bark, watch, sniff and so on. A separate set of variables will define the dog’s colour, height, weight,
family and so on. So, you initialize dog’s variables and call some functions that operate on those vari-
ables and my goodness, you have a dog!
In contrast, OOP language sees dog as a real-world entity or object with behaviours (i.e. functions)
and states (i.e. variables that hold data values) as shown in Figure 5.1(a). So, OOP thinks in terms
of objects and not in terms of separate functions and variables. The integration of state variables and
behaviours into objects is called encapsulation. Encapsulation promotes information hiding. Infor-
mation hiding makes state variables and behaviour inaccessible to the external world. Aggregation is
another property of OOP language, which characterizes that an entity is composed of other entities.
For instance, a car is composed of engine, wheels, doors and so on, each of which is known as entities.
Aggregation expresses HAS-A relationship between entities. Consider a dog wears a belt in its
neck as in Figure 5.1(b). In this case, we say Dog HAS-A Belt. So Dog and Belt are two entities
where Dog contains Belt.
In OOP, we encounter inheritance – the ability to derive something specific from something
generic. For example, the entities cat and dog, both are classified as animals. Cats and dogs inherit
states and behaviours from generic entity animals. There are two types of inheritance – single
inheritance and multiple inheritance. In single inheritance, an entity inherits from just one generic
entity, whereas in multiple inheritance, an entity inherits from more than one generic entity. Here,
entities in inheritance express IS-A behaviour. For example, Dog IS-A animal. Java supports only
single inheritance. Polymorphism or runtime overriding is another unique feature of Java. Java
uses runtime type identification (RTTI) in order to identify the correct behaviour of a child class.
This syntax creates a class that can be a public class, private class, protected class or default class
without any of these three keywords. Also, it can be an abstract class or final class. A public class
is accessible to all class in all packages. A package is a collection of classes bundled together and
identified by a common name. Assume a package to be a directory with a collection of files. We will
discuss packages in Chapter 7.
A private class cannot be accessed by any other class in any package. Only member functions can
access its data members. A private class may allow other classes to access data members through its
member functions. A protected class is either accessible to its subclasses in any package or any class
within the current package.
An abstract class is an incomplete class, where objects cannot be created from abstract class. It
is a first step towards interfaces which is identified as a pure abstract class. These abstract classes
and interfaces tell those related classes that all of them should implement abstract methods and
interface methods with necessary method body. The final class cannot be subclassed. Suppose,
we want to restrict access to all subclasses, then the final class is more useful to achieve this
functionality.
Finally, a class can be defined without any of these keywords that we can call default class. Default
classes are accessible to all classes defined in the current package. A class can contain data members
(variables of primitive type or objects of a class) and member functions (methods).
We have so far learnt enough theory about OOP concepts. Now, it is time to start developing
applications using OOP concepts. Let us consider the following real-world entity, Laptop (shown in
Figure 5.3). Laptop has many states such as monitorSize, colour, processor, ram and hardDisk and
many behaviours such as turnOn, turnOff, idle and running.
Laptop
monitorSize
colour
processor
ram
hardDisk
turnOn
turnOff
idle
running
We can convert this entity into a Java class as a class diagram with data members and member
functions and is represented in Figure 5.4.
class Laptop
int monitorSize
String colour
String processor
int ram
int hardDisk
void turnOn
void turnOff
void idle()
void running()
Let us now convert this Java class diagram into a Java class that is accessible to any class in the
current package (i.e. in the current directory) as shown in Listing 5.1.
// Laptop.java
void turnOn()
{
System.out.println(“ Laptop switched on now…”);
}
void turnoff()
{
System.out.println(“ Laptop switched off now…”);
}
void idle()
{
System.out.println(“ Laptop is in idle
mode now…”);
}
void running()
{
System.out.println(“ Laptop is currently running …”);
}
}
Laptop
ibm
lenova
dell
hp
Once Laptop class is defined, we can then create objects of Laptop such as ibm, hp, dell and lenova
as shown in Figure 5.5. Further, Listing 5.2 depicts the public class that creates objects of Laptop.
// LaptopTest.java
public class LaptopTest
{
public static void main(String[] args)
{
// create object ibm
Laptop ibm = new Laptop();
ibm.turnOff();
When you compile LaptopTest.java, it will automatically compile Laptop.java, provided Lap-
top.java is available in the same directory where LaptopTest.java is saved. For brevity, many
novice Java users would prefer to save both classes in the same file. In such cases, you must keep
Laptop class as a default class without public keyword and save files with the name of the public
class which is now LaptopTest.java. Here, object names (also called instance) such as ibm, hp,
dell and lenova are references that hold the address of memory locations where Laptop objects are
available respectively. This process is known as creation or instantiation of objects. Also remem-
ber when program execution stopped, objects will be automatically destroyed by Java Virtual
Machine (JVM).
5.4 P
roblem: Designing Object-Oriented
College Application
Now, for example, we want to extend our understanding of classes to view some larger software
application with more classes. Suppose, we want to design an object-oriented college that has many
entities interacting with each other such as students, courses, professors, department and many others.
Figure 5.6 depicts the class diagram for this college.
Here, college aggregates many courses, many students, many professors and many departments.
Listing 5.3 depicts the simple application defining all these classes.
College
// OOCollege.java
class Course
{
String cid; // course id
}
class Department
{
String did; // department id
}
class Student
{
String sid; // student id
}
class Professor
{
String pid; // professor id
}
System.out.println(“College Started”);
}
{
OOCollege c = new OOCollege();
c.startCollege();
}
}
College Started
In the above syntax, data members can be declared optionally as public, private and protected, very
similar to access types of classes as discussed in section 5.3. If any of these three access types is not
present, then default package access will be assumed. So any class not declared in the same package
cannot access default variables.
Further, final data member does not allow its value to be modified once it is assigned. It is a way
to create constants as discussed in Chapter 1. Volatile variable allows its values to be accessed by
multiple threads and prevents certain compiler optimizations.
If a variable is declared as static, all objects share one copy of the variable. Therefore, if one object
changes the value, all other objects can see this new value. Hence, if a variable is not static, then it is
assumed to be instance variable and every object will have a separate copy. Finally, the value of the
transient variable will not be saved during object serialization.
Listing 5.4 illustrates the concepts of data members that are public, private, package access mem-
bers, static and final.
// DataMembersTest.java
class DataMembers
{
public int i = 100;
private float f = 200f;
double d = 300;
System.out.println(“d1.si ” + d1.si); // 10
System.out.println(“d2.si ” + d2.si); // 10
System.out.println(“DataMembers.si ” + DataMembers.si);
// 10
d1.i 100
d2.i 100
d1.d 300.0
d1.d 300.0
d1.si 10
d2.si 10
DataMembers.si 10
d1.si 11
d2.si 11
DataMembers.si 11
d1.si 12
d2.si 12
DataMembers.si 12
d1.si 12
d2.si 12
DataMembers.si 12
d1.max 1000
d2.max 1000
A method declaration consists of a method signature followed by method body. The method sig-
nature specifies the method’s name, return type, arguments list, access-types such as public, pri-
vate or protected, access modifiers such as abstract or final, static, native and synchronized. Also a
method can throw an exception (exceptions will be discussed in Chapter 7.). The method body will be
executed when the caller invokes this method by its name.
If a method is declared as abstract, it only consists of a method signature; there is no block of
statements. Furthermore, the class in which the abstract method is declared must also be declared
abstract. Finally, an abstract method cannot be declared final, static, native, synchronized or private
at the same time.
If a method is declared as final, the compiler ensures that the method cannot be overridden by
subclasses.
If a method is declared as static, that method is known as a class method because it can only access
class fields. However, if static is not specified, the method is known as an instance method because it
can access instance fields as well as class fields.
If a method is declared as native, only a method signature is present. The method body is written
in C language and stored in a platform-specific library. Finally, if a method is declared as synchro-
nized, only one thread at a time can execute method code. We will discuss method overriding in
Chapter 6, abstract and final concepts in Chapter 7 and native and synchronized methods in Chapter 12.
Listing 5.5 illustrates Student object that has data members rollno, name, year, m1, m2, m3, m4
and member functions getdata() to collect values from console, display() to show the values and
calc_result() to calculate result from the marks of a student.
// StudentTest.java
import java.io.*;
class Student
{
BufferedReader in = new BufferedReader (new InputStreamReader
(System.in));
// get data
public void getdata() throws IOException
{
rollno = Integer.parseInt(in.readLine());
name = in.readLine();
year = in.readLine();
m1 = Float.parseFloat(in.readLine());
m2 = Float.parseFloat(in.readLine());
m3 = Float.parseFloat(in.readLine());
m4 = Float.parseFloat(in.readLine());
}
// define method
public void display()
{
System.out.println(“Rollno = ” + rollno);
System.out.println(“Name = ” + name);
System.out.println(“Year = ” + year);
System.out.println(“Marks = ” + m1 + “, ” + m2 + “, ” + m3
+ “, ” + m4);
}
if (m1 >= 40 && m2 >= 40 && m3 >= 40 && m4 >= 40)
result = “pass”;
Rollno = 12001
Name = Rex
Year = 2012
Marks = 57.0, 7.0, 87.0, 98.0
Result = fail
// StaticMethodDemoTest.java
class StaticMethodDemo
{
public static int i = 100; // here i is a class variable, so
only one copy exists
public int j = 200; // j is an instance variable
System.out.println(s1.i);
s1.incr();
System.out.println(“s1.i : ” + s1.i);
System.out.println(“s2.i : ” + s2.i);
s2.incr();
System.out.println(“s1.i : ” + s1.i);
System.out.println(“s2.i : ” + s2.i);
System.out.println(“s1.i : ” + s1.i);
System.out.println(“s2.i : ” + s2.i);
}
}
100
s1.i : 101
s2.i : 101
s1.i : 102
s2.i : 102
main() calls incr() : 103
s1.i : 103
s2.i : 103
// StudentTest2.java
import java.io.*;
// initialize objects
for(int i = 0; i < max; i++)
s[i] = new Student();
// get details
// process
for(int i = 0; i < max; i++)
{
System.out.println(“Result of student” + i);
s[i].display();
s[i].calc_result();
}
}
}
// BookStore.java
class Book
{
int isbn;
String author;
String title;
ISBN: 1234
Title: Java
Author: Peter
Here init() method has a local variable namely isbn, apart from the instance variable isbn of
Book class. Java resolves this scope of variables through this reference. Therefore, this.isbn refers to
instance variable, whereas isbn refers to the local variable inside the method init().
5.10 Summary
1. Object-oriented paradigm binds data and code together, in contrast to structured programming
paradigm
2. Abstraction, encapsulation, information hiding, aggregation, inheritance and polymorphism are
powerful features of OOP
Key terms
Review questions
Multiple-choice Questions
1. Find out the output:
class Number
{
public int i = 15;
}
n.i = 25;
Number n2 = new Number();
n2 = n;
Number n3 = new Number();
n = n3;
System.out.println(n.i + “,” + n2.i + “,” + n3.i);
}
}
a. 25 15 15 b. 15 25 15
c. 15 15 25 d. 25 15 25
class Number
{
public int i = 15;
}
a. 15, 15 b. 20 20
c. 20 15 d. 15 20
class Data
{
public int i = 15;
public static String s = “hello”;
}
class Data
{
public static int i = 0;
}
System.out.println(t1.increment());
System.out.println(t2.increment());
System.out.println(Data.i); // statement-3
}
}
a. 0 0 1 b. 0 1 2
c. 1 2 3 d. 1 1 2
5. Find out the output:
class Data
{
int i = 10;
int j = 20;
}
a. 20, 10 b. 10 20
c. 10 10 d. 20 20
6. Find out the output:
class Data
{
static int i = 10;
int j = 20;
{
public static void main(String[] args)
{
Data d1 = new Data();
Data d2 = new Data();
d1.incr(); d2.incr();
System.out.println(
d1.i + “,” + d1.j + “,” + d2.i + “,” + d2.j);
}
}
a. 12 21 12 21
b. 10 20 11 21
c. 11 20 12 21
d. 11 21 12 21
class Data
{
public int[] a = new int[5];
}
a. 0 0 0 0 0 b. 1 1 1 1 1
c. null null null null null d. Runtime error
class Data
{
public int[] a = new int[5];
}
a. 0 0 0 0 0 b. 1 1 1 1 1
c. null null null null null d. Runtime error
9. Find out the output:
a. 0 b. 1
c. 2 d. Runtime error
a. 8 9 7 b. 8 9 9
c. 8 9 8 d. 7 8 9
System.out.println(m1 == m3);
System.out.println(m1.n == m2.n);
}
}
class A
{
public static int call(int i)
{
return ++i;
}
}
class B
{
public static int call(int i)
{
System.out.println(A.call(i--));
return 1;
}
}
a. 99 b. 100
c. 101 d. 1
13. What is the type of relationship that exists between the following classes?
class Wheel
{
public int no;
}
class Bike
{
Wheel[] wheels = new Wheel[2];
public enum color{RED, WHITE, BLUE, YELLOW};
}
a. is-a b. has-a
c. Abstract class relationship d. Interface relationship
class A { }
public class Test5 extends A
{
public void check()
{
boolean test = true;
if(test & Test5.this instanceof Test5)
System.out.println(“yes”);
else
System.out.println(“no”);
}
public static void main(String[] args)
{
a. yes b. no
c. If statement is not at all executed d. Error in calling check()
16. Find out the output:
class A { }
public class Test5 extends A
{
public static void main(String[] args)
{
Test5 t = new Test5();
boolean test = true;
if(test && t instanceof Test5)
System.out.println(“yes”);
else
System.out.println(“no”);
}
}
a. yes b. no
c. If statement is not at all executed d. Error in calling check()
class A { }
public class Test5 extends A
{
public static void main(String[] args)
{
boolean test = true;
if(test && this instanceof Test5)
System.out.println(“yes”);
else
System.out.println(“no”);
}
}
a. yes b. no
c. Compilation error d. Runtime error
class A { }
public class Test5 extends A
{
public static void main(String[] args)
{
if(Integer.valueOf(10) instanceof Number)
System.out.println(“yes”);
else
System.out.println(“no”);
}
}
a. yes b. no
c. Compilation error d. Runtime error
19. Consider three entities Dog, PetDog and Belt. What are the possible relationships which can be
expressed between these classes?
1. Dog, PetDog and Belt can be expressed as three independent classes
2. PetDog class can inherit from Dog class through is-a relationship
3. Dog class can inherit from PetDog class through is-a relationship
4. PetDog class can contain Belt class through has-a relationship
5. Dog class can contain Belt class through has-a relationship
a. 2, 4, 5 b. 2, 3, 4
c. 1, 3, 5 d. 1, 4, 5
class Belt
{
int size = 20;
}
class Dog
{
Belt belt = new Belt();
String color = “red”;
}
public class Test5
{
public static void main(String[] args)
{
Dog d = new Dog();
d.color = “white”;
d.belt.size = 40;
System.out.println(d.color + “,” + d.belt.size);
}
}
a. white, 40 b. red 20
c. white 20 d. red 40
a. 010101 b. 011011
c. 001101 d. 011101
a. 1234 b. 01234
c. Compilation error d. Runtime error
class Pen
{
public static void write()
{
System.out.println(“Pen”);
}
}
class InkPen extends Pen
{
public static void write()
{
System.out.println(“InkPen”);
}
}
Answers
1. b 2. a 3. d 4. b 5. a 6. a 7. a 8. b 9. c 10. a
11. a 12. c 13. b 14. d 15. a 16. a 17. c 18. c 19. a 20. a
21. a 22. c 23. a
Short-answer Questions
1. Explain the terminologies object, state, behaviour and class.
2. What is abstraction? Explain with an example.
3. Explain encapsulation and information hiding with an example.
4. Explain HAS-A and IS-A relationships with an example.
Exercises
5.1. Modify OOCollege application with additional private data members and member public
functions.
■■ Class Course: private String cid, String courseName, int credit, String pid (i.e. prerequisite
course id), getCourse() that returns Course and setCourse() that receives values through
arguments and assigns them to data members
■■ Class Department: private String did, String name, String location, getDepartment() and
setDepartment() public methods
■■ Class Student: String sid, String name, String address, String degree, String year, getStu-
dent() and setStudent() public methods
■■ Test objects of these classes inside main() with values
■■ private data members: private double radius (r), private double height(h)
■■ public void setCylinder(): to assign values to data members
■■ public double volume(): calculates and returns volume of the cylinder as PI*r*r*h
■■ public double areaSide(): returns area of side only without top and bottom sides as 2*PI*r*h
■■ public double area(): returns area of top, bottom and side as 2*PI*r (r+h)
■■ Develop a public class TestCylinder to test all these methods
■■ private data members: String fanType, String manufacturer, String model, boolean isOn
■■ public data members: enum Speed with 5 levels from 1 to 5
■■ public void setFan() and getFan() methods
■■ public void on(): switch on the fan
■■ public void off(): switch off the fan
■■ public void speedUp(): to increase current speed, if not maximum 5
■■ public void speedDown(): to reduce current speed, if not minimum 1
Objectives
■■ To introduce constructor, its importance and functionality
■■ To explain default constructor
■■ To explain constructor with parameters or arguments
■■ To define overloaded constructors
■■ To introduce Math class from java.lang package
■■ To explain different methods of Character class
■■ To create immutable strings with String class
■■ To manipulate strings with StringBuffer class
■■ To manipulate strings using StringBuilder class
■■ To explain inheritance and its types
■■ To call base class constructor, data members and member functions
■■ To implement Object-Oriented Dog application
■■ To introduce polymorphism with Instrument class
■■ To differentiate aggregation from inheritance
■■ To introduce java.lang.Object class
■■ To check object’s class type with instanceof operator
■■ To clone an object
■■ To prevent inheritance and overriding
■■ To allow restricted access to subclasses with protected type
■■ To explore visibility of classes and its members
■■ To create an inner class inside a class
6.1 Introduction
In Chapter 5, the readers were introduced to solve a real-world problem object-oriented way by think-
ing everything in terms of objects. For each object, states and behaviours of the object can be iden-
tified and represented by means of Java class. The difference between object instances and class
members is also known. In this chapter, we build on the traits of objects and classes. First, the reader
is exposed to object initialization using constructors. Further, some of the important Java Wrapper
classes along with their methods are introduced. This is followed by inheritance, another powerful
feature of Java. Finally, we make the reader to understand the visibility of data members and member
functions across classes within a package or across packages.
6.2 Constructors
A constructor is a special kind of method that has class name as its name and can be used to initialize
objects. It is called just after the memory is allocated for the object. Constructor is always public and does
not return any value including void. Just like any other method, a constructor can call any other method.
A constructor without any argument is called default constructor and it will be automatically called.
In contrast, a parameterized constructor has arguments and so it should be called manually during
object creation. Constructors can also be overloaded, very similar to overloading other methods. Con-
structors are called starting from the root class down the class hierarchy. The reader is introduced to
class hierarchy and inheritance in section 6.7.
// HelloConstructor
class HelloConstructor
{
public HelloConstructor()
{
System.out.println(“Hello Java”);
}
}
public class HelloConstructorTest
{
public static void main(String[] args)
{
HelloConstructor h = new HelloConstructor();
}
}
Hello Java
// HelloConstructor2Test.java
class HelloConstructor2
{
public HelloConstructor2(String name)
{
System.out.println(“Hello ” + name);
}
}
public class HelloConstructor2Test
{
public static void main(String[] args)
{
HelloConstructor2 h = new HelloConstructor2(“Rex”);
Hello Rex
// HelloConstructor3Test.java
class HelloConstructor3
{
public HelloConstructor3()
{
System.out.println(“Hello Java”);
}
public HelloConstructor3(String name)
{
System.out.println(“Hello ” + name);
}
public HelloConstructor3(int empId)
{
System.out.println(“Hello ” + empId);
}
}
public class HelloConstructor3Test
{
public static void main(String[] args)
{
new HelloConstructor3();
new HelloConstructor3(“Rex”);
new HelloConstructor3(2725);
}
}
Hello Java
Hello Rex
Hello 2725
Java application does not have to destroy the allocated memory manually through destructors.
Rather, memory space allocated to objects will be automatically cleaned up by JVM itself.
6.6.1 Math
The class Math provides many class methods for performing basic scientific operations. It sup-
ports methods to calculate absolute values using abs(), sin(), cos(), tan(), min(x,y), max(x,y), ceiling
using ceil(x,y), floor(x,y), pow(x,y) to find power, random() to generate random number and sqrt(x)
methods. Listing 6.4 explains some representative methods of Math class.
// MathTest.java
abs(–100.0) : 100.0
sin(90): 0.8939966636005579
min(10,20): 10
pow(10,2): 100.0
sqrt(25) : 5.0
Random number 0 : 0.44320911613762604
Random number 1 : 0.7391733959979383
Random number 2 : 0.7082800388148885
6.6.2 Character
The Character class supports many static and instance methods to manipulate a character. There are
important methods such as isDigit(), isLetter(), isLowerCase(), isUpperCase(), compare() to compare
two characters, compareTo() to compare two character objects, isWhiteSpace(), valueOf() to con-
vert char to Character wrapper and charValue() to convert Character wrapper to char primitive type.
Listing 6.5 depicts important methods of Character class.
// CharacterTest.java
public class CharacterTest
{
public static void main(String[] args)
{
C
Character.isDigit(‘a’): false
Character.isLetter(‘a’): true
Character.toLowerCase(‘A’): a
compare c and b: 1
6.6.3 String
The String class includes methods to perform many operations on strings. Strings in Java are immu-
table, which means, the original content of the string cannot be modified. Any operation on string will
create a new string.
String object can be created from char[], byte[] and String through various overloaded construc-
tors. Some important instance methods are charAt() to return a char at location, compare(str), length(),
toUpperCase(), toLowerCase(), trim(), concat(str) to concatenate two strings, substring(), getBytes()
to convert string to byte[] and a class method valueOf() that converts primitive data types to string.
For instance, Listing 6.6 explains the various string methods in detail.
//StringTest.java
System.out.println(“s1.compareTo(s2): ”
+ s1.compareTo(s2));
System.out.println(“s1.toLowerCase(): ”
+ s1.toLowerCase());
System.out.println(“s2.toUpperCase(): ”
+ s2.toUpperCase());
System.out.println(“s1.length(): ” + s1.length());
}
}
s1.charAt(2): L
s1.compareTo(s2): -32
s1.toLowerCase(): hello
s2.toUpperCase(): HELLO
s1.length(): 5
6.6.4 StringBuffer
The StringBuffer class allows a string’s original contents to be modified, that is the string is mutable. It
is safe for threads. StringBuffer can be created from String. There are two important methods: append()
to append any primitive data types, String or even StringBuffer as well as insert(loc, value) to insert a
primitive data type or String to the specified location. The length() returns the length of string buffer,
while reverse() reverses its contents. Listing 6.7 appends 100 random characters to string buffer.
//StringBufferTest.java
Welcome Admin
sb length: 13
HellonimdA emocleW
HellonimdA emocleW.&H9T\Q.
6.6.5 StringBuilder
The StringBuilder class also supports string processing features as StringBuffer. However, String-
Builder is very fast in computation, but not thread safe as StringBuffer. All methods of StringBuffer
are also available in StringBuilder. Listing 6.8 explains few StringBuilder instance methods.
//StringBuilderTest.java
sb length: 22
sb reverse: ?uoy era woHavaJ olleH
sb.insert: Hello?uoy era woHavaJ olleH
Hello?uoy era woHavaJ olleH
So, we have three options to handle strings – String class, StringBuffer and StringBuilder. Our
natural question is which one to use? Apply the following rule of thumb.
■■ If your text is not going to change, use a String class because a String object is immutable.
■■ If your text can change and will only be accessed from a single thread, use a StringBuilder
because StringBuilder is unsafe for threads.
■■ If your text can change and will be accessed by multiple threads, use a StringBuffer because
StringBuffer is synchronous and thread safe.
6.7 Inheritance
Inheritance is the ability of a class to derive something specific from a generic class. The generic
class is called super class or base class or parent class and the specific class is known as child class or
subclass or derived class. There are two types of inheritance:
■■ Single-level inheritance, where a child class inherits from its parent class
■■ Multilevel inheritance, where a class inherits from its parent, this parent in turn inherits from its
parent and so on (see Figure 6.1)
Vehicle Vehicle
Car Car
Hatch Back
For example as shown in Figure 6.2, class LibraryBook is a child class of a super class Book (that
we developed in Chapter 5). Here, we say LibraryBook inherits states and behaviours of objects of
Book class such as isbn, author, title and many others. Apart from deriving from Base class, Library-
Book can have its own data members such as number of copies and member functions representing
states and behaviours of objects (Listing 6.9).
Book
int isbn
String author
String title
Library Book
int nCopies
isbn = 1234
author = Rex
title = Hello Java
copies = 10
The extends keyword causes a subclass to inherit all data members and member functions declared
in a nonfinal super class (including the super class’s super classes). The subclass can access all
inherited nonprivate data members and member functions; it cannot access any inherited private data
members and member functions. In inheritance, objects are instantiated starting from base class down
in the class hierarchy.
Dog
String name
String color
String diet
Dog(name, color, diet)
Dog(color)
eat(food)
bark()
showDog()
PetDog StrayDog
String owner
Figure 6.3 depicts the class hierarchy of Dog. Here, PetDog and StrayDog are child classes of the
base class Dog. The OODog class aggregates PetDog and StrayDog objects. Listing 6.10 depicts the
object-oriented design of Dog.
//OODog.java
class Dog
{
String name;
String colour;
String diet;
super(colour);
}
class Instrument
{
String colour;
public void tune() { };
}
In this application, child class objects are assigned to base class reference by normal upcasting
which is something JVM will identify at compile time. During runtime, JVM correctly identifies the
appropriate child class version of the tune() method and invokes it. It does not complain to us that we
did not downcast.
Rather with a feature named runtime type identification (RTTI), it invokes appropriate tune()
method from any of the child class. This behaviour is known as polymorphism. Suppose if there is a
variation in the signature, say for instance, different arguments list, then JVM will consider these two
methods as overloaded instead of overridden methods. So, as overloading it will invoke either a base
class method or child class method depending on the input values.
One final note about overriding. A child class method, defined in another package other than the
package where base class is defined, can override the base class method which is only public or pro-
tected. It cannot override private or default access methods. Before leaving this topic, let us consider
the keyword protected. If you declare a super class field or method as protected, any method,
declared in any class that subclasses the class that declares the protected field or method, can access
that field or method.
// ObjectTest.java
class Cat
{
String name;
public Cat(String name1)
{
name = name1;
}
}
Cat@19821f , Cat@addbf1
cat1.equals(cat2) : false
cat1 class: class Cat
cat1’s hashcode : 1671711
Cloning allows a Java application to create a copy of an object. For that, the class should be
declared as cloneable as illustrated in Listing 6.13.
// BookShelf.java
import java.util.*;
class Book
{
type appears, then those data members and member functions are available to all classes within the
same package. Packages are discussed in detail in Chapter 7.
A static inner class is a static member of a class. Like any other static method, a static inner class
has access to all static methods of the outer class. Figure 6.6 depicts static inner class.
Local inner classes are declared within a block of code (say between curly braces) and are visible
only within that block. Finally, an anonymous inner class is a local class without name. Local inner
class is illustrated in Figure 6.7.
class OuterClass
{
public void method1()
{
.......
class InnerClass
{
.......
}
}
}
The member inner classes are instantiated with the instance of the outer class as shown in Example 6.1.
Similarly, static inner classes are instantiated with the syntax shown in Example 6.2.
Listing 6.15 depicts a member inner class OverTime, which is a member of outer class Employee. The
count() method of OverTime calculates the number of overtime days of an employee by accessing its
data member.
// Employee.java
public class Employee
{
// employee worked overtime these days
int[] overtimeDays = {1, 5, 18, 25, 31};
class OverTime
{
public void count()
{
System.out.println(“No. of overtime days: ” +
overtimeDays.length);
}
}
You will learn more about inner classes when you design graphical user interface (GUI) applica-
tions using Frames and Applets. Inner classes are highly useful to handle events generated by various
Abstract Windowing Toolkit (AWT) and Swing components. So you will appreciate the power of
inner classes while you learn GUI programming in Chapter 16.
6.17 Summary
1. Constructor is a special method used for initialization of objects
2. Default constructor is automatically called
3. Constructors can have arguments or parameters
4. Parameterized constructors should be manually called
5. Constructors can also be overloaded
6. Math class provides many methods for mathematic and trigonometric operations
7. Character class has methods to manipulate single character
8. String class supports many methods to create and manipulate strings
9. Strings are immutable in Java. That is, original string cannot be modified
10. StringBuffer allows a string’s original content to be modified
11. StringBuilder also supports string manipulation and is faster than StringBuffer
12. StringBuffer is thread safe, but not StringBuilder
13. Inheritance allows a child class to reuse data members and methods of super class
14. The keyword super is used to call base class constructor and data member
15. The keyword this refers to current object
16. A child class can override a base class method
Key terms
Review questions
Multiple-choice Questions
1. Find out the output:
class B extends A
{
short i = 10;
int j = 20;
public B()
{
System.out.println(add(i, j));
}
}
class A
{
int add(int i, int j)
{
return i + j;
}
}
a. 30
b. Compilation error: arguments do not match
c. Compilation error: adding int with short not permitted
d. Runtime exception
class A extends B
{
A() { System.out.println(“A”); }
}
class B
{
B() { System.out.println(“B”); }
}
a. B A b. A B
c. No output d. Compilation error during object creation
for A
class A extends B
{
A() { System.out.println(“A”); }
}
class B
{
B() { System.out.println(“B”); }
}
new B();
}
}
a. A b. A B
c. B d. B A
4. What is the output?
class A extends B
{
A() { System.out.println(“A”); }
}
class B
{
B(String s) { System.out.println(s); }
}
a. Compilation error b. A
c. A null d. null A
5. What is the output?
class A
{
void show() { System.out.println(“A”); }
}
class B extends A
{
public B() { System.out.println(“C”); }
void show() { System.out.println(“B”); }
}
{
A a = new A();
a.show();
a = new B();
a.show();
}
}
a. A C B b. A B
c. A B C d. None of the above
6. What is the output?
class Building
{
public Building()
{
System.out.println(“Building”);
}
public Building(int n)
{
this();
System.out.println(“Building” + n);
}
}
class Office extends Building
{
public Office()
{
System.out.println(“Office”);
}
public Office(int n)
{
this();
System.out.println(“Office” + n);
}
}
class Flower
{
public void smell()
{
System.out.println(
“Flower smells”);
}
}
class WinterFlower extends Flower
{
public void smell()
{
System.out.println(
“winter Flower smells”);
}
public void color()
{
System.out.println(
“winter Flowers color”);
}
}
public class Test7
{
public static void main(String[] args)
{
Flower f = new Flower();
f.smell();
f.color(); // statement-1
f = new WinterFlower();
f.smell();
f.color(); // statement-2
}
}
class Flower
{
public static void smell()
{
System.out.println(
“Flower smells”);
}
}
class WinterFlower extends Flower
{
public static void smell()
{
System.out.println(
“winter Flower smells”);
}
}
public class Test7
{
public static void main(String[] args)
{
Flower f = new Flower();
WinterFlower wf = new WinterFlower();
f.smell();
wf.smell();
}
}
class Flower
{
String color = “red”;
public String smell()
{
return “Flower smells”;
}
}
class WinterFlower extends Flower
{
class Cat
{
public Cat del(Cat c)
{
c = null;
return c;
}
}
a. c1, c2 b. c2, c3
c. c1, c3 d. None of the above
class Calculator
{
public int add(int i)
{
return 10 + i;
}
public int add(int... a)
{
int s = 0;
for(int j=0; j < a.length; j++)
s += a[j];
return s;
}
}
a. 3 b. 11
c. No output d. Compilation error
class Concatenator
{
Object s = “”;
public void concat(Object o)
{
s = s + “A”;
}
public void concat(Object... o)
{
s = s + “B”;
}
public void concat(Float... f)
{
s = s + “C”;
}
}
a. ABC b. BAC
c. CAB d. BCA
class Vowel
{
char[] v = {‘a’, ‘e’, ‘i’, ‘o’, ‘u’};
}
a. a e i o u b. No output
c. Compilation error d. Runtime exception
class A
{
void show(int i) { System.out.println(“A”); }
}
class B extends A
{
// insert a statement here
}
class A
{
public A() { System.out.println(“default constructor”); }
public A(int a) { System.out.println(“int constructor”); }
public A(char c) { System.out.println(“char constructor”); }
}
public class Test6
{
public static void main(String[] args)
{
new A();
}
}
class A
{
String s = “A”;
}
class B extends A
{
String s = “B”;
}
class C extends B
{
String s = “C”;
public C()
{
A a1 = new A();
B b1 = new B();
System.out.println(this.s + “,” +
super.s + “,” + b1.s + “,” + a1.s);
}
}
a. A, B, B, C b. C, B, B, A
c. B, B, A, C d. B, B, C, A
17. Find out the output:
class A
{
public A()
{
System.out.println(“A”);
}
}
class B extends A
{
private B()
{
System.out.println(“B”);
}
{
new B();
}
}
a. A B b. B A
c. A d. B
class A
{
public void show()
{
System.out.println(“A”);
}
}
class B extends A
{
public void show()
{
System.out.println(“B”);
}
}
class C extends B {}
a. A b. B
c. A B d. B A
e. No output
class A
{
static int i = 1;
a. 2 1 b. 2 2
c. 1 1 d. 1 2
a. hello
b. hellojava
c. javahello
d. java
21. What is the relationship that exists between the following classes?
class B extends A { }
class A { }
class Furniture
{
public Furniture(String s)
{
System.out.println(s);
}
}
class Chair extends Furniture
{
public Chair(String s)
{
super(“office furniture”);
System.out.println(s);
}
}
class Furniture
{
public Furniture(String s)
{
System.out.print(s);
}
}
class Chair extends Furniture
{
public Chair(String s)
{
System.out.print(s);
super(“office furniture”);
}
}
class A
{
public final void a()
{
System.out.println(“A”);
}
}
class B extends A
{
public void a()
{
System.out.println(“B”);
}
}
A a1 = new B();
a1.a();
}
}
a. A B b. B A
c. A A d. B B
e. Compilation error
class DoIt
{
void go(int... x) { System.out.print(“1”);}
void go(int d, char...x) { System.out.print(“2”);}
}
a. 1 2 b. 3 b c
c. 1 2 3 b c d. Compilation error
class Ball
{
public Ball() { System.out.println(“1”); }
public void Ball() { System.out.println(“2”); }
}
new Ball().Ball();
}
}
a. 1 2 b. 1
c. 2 d. 1 1
e. Compilation error
a. same1 b. same2
c. same1 same2 d. No output
if(c == d)
System.out.println(“same3”);
if(c.equals(d))
System.out.println(“same4”);
}
}
a. same3 b. same4
c. same3 same4 d. No output
a. 123456 b. 456123
c. 456 as 123 will be overwritten d. Some garbage value will be displayed
a. 123456 b. 456123
c. 456 as 123 will be overwritten d. Some garbage value will be displayed
a. cbafed b. fedcba
c. fed d. Some garbage value will be displayed
a. aBCD b. aBcd
c. abCD d. CDBa
class A
{
public A() { }
public A(int i) { }
}
class B extends A
{
public B() { }
public B(int i)
{
super(i);
}
}
public class Test61
{
public static void main(String[] args)
{
A a1 = new A(); // Line-1
B b1 = new B(); // Line-2
B b2 = new B(10); // Line-3
B b3 = new B(10.0); // Line-4
}
}
a. Line-1 b. Line-2
c. Line-3 d. Line-4
39. Which of the following are valid overloaded methods for the method add()
int add(int a, int b) { }?
a. int add(int a) { } b. float add(float a, float b) { }
c. float add(int a, float f) { } d. All of the above
class A
{
public A() {System.out.print(“A”); }
}
class B extends A
{
public B() {System.out.print(“B”); }
}
public class Test61
{
public static void main(String[] args)
{
A a1 = new A();
B b1 = new B();
A a2 = new B();
}
}
a. ABBAB b. BABAA
c. AABAB d. AABBA
Answers
1. a 2. a 3. c 4. a 5. a 6.b 7. a 8. a 9. b 10. c
11. a 12. b 13. a 14. d 15. a 16. b 17. a 18. b 19. a 20. a
21. a 22. a 23. c 24. e 25. d 26. a 27. d 28. d 29. c 30. b
31. a 32. b 33. b 34. a 35. a 36. b 37. a 38. d 39. d 40. c
Short-answer Questions
1. What is a constructor? Explain with an example.
2. Explain default constructor with an example.
3. Explain parameterized constructor with an example.
4. Explain constructor overloading with an example.
5. Explain important methods of Math class.
6. Discuss important methods of Character class.
7. Discuss important methods of String class.
8. Explain StringBuffer and its important methods.
9. Explain StringBuilder and its important methods.
10. What is the difference between StringBuffer and StringBuilder?
11. Explain inheritance and multilevel inheritance with suitable examples.
12. How will you call base class constructor? Give an example.
13. Explain overriding with an example.
14. Explain polymorphism with an example.
15. What is object cloning?
16. How to identify object’s class type?
17. How will you prevent inheritance?
18. How will you prevent overriding?
19. What is inner class? Explain all 4 types of inner class.
Exercises
6.1. Replace setCourse() method of Exercise 5.1 with a constructor to initialize the data members of
Course class.
6.2. Replace setCylinder() method of Exercise 5.2 with a constructor to initialize the data members
of Cylinder class.
6.3. Replace setPrism() method of Exercise 5.3 with a constructor to initialize the data members of
Prism class.
6.4. Replace setFan() method of Exercise 5.4 with a constructor to initialize the data members of
Fan class.
6.5. Develop a class MyString with your member functions for string processing.
6.6. Develop a class hierarchy for Food as shown in Figure 6.8.
Food
Create a class Lunch that has Fruit, Vegetable, Fish and Chicken. Create objects for Fruit,
Vegetable, Fish and Chicken. For example,
Assign values for data members and test getCalories() and getFood() methods. Design new m
ethods
for other classes too and test them.
Objectives
■■ To explain the need for abstract class and abstract methods
■■ To define abstract class, abstract methods and non abstract methods
■■ To implement an abstract class Flower
■■ To explain interfaces and its method definitions
■■ To explain the difference between interfaces and abstract classes
■■ To create Wearable and Flyable interfaces
■■ To explain enum and its applications
■■ To create packages and subpackages for class taxonomy
■■ To add classes to packages
■■ To import packages containing classes and interfaces
■■ To explain how packages help to avoid name collision
■■ To illustrate protected data members with package
■■ To define compile time errors and runtime exceptions
■■ To explain Java built-in exception class hierarchy with root class Throwable
■■ To introduce all runtime exceptions and IO exceptions
■■ To handle exceptions with try-catch-finally statements
■■ To pipe exceptions using multicatch statement
■■ To introduce checked exception that allows users to create their own exceptions by extending
Exception class
■■ To explain throw and throws statements
7.1 Introduction
In chapters 5 and 6, the readers were introduced to few of the powerful object-oriented features of
Java. For instance, object-oriented development involves designing classes with encapsulation, with
which we would bind data representing states and code representing behaviours of objects together.
Aggregation and inheritance help us to organize class based on whether classes exhibit part-of (or
has-a) relationship or is-a relationship. Member visibility allows us to specify access rights to other
classes depending on whether those classes access from within the same package or other packages or
are subclasses. Once classes are designed, we can create objects, initialize objects using constructors,
overload constructors and identify objects’ methods at runtime using polymorphism.
In this chapter, the readers are introduced to the remaining two important object-oriented features
of Java, namely abstract classes and interfaces. The readers learn how abstract classes allow us to
define some behaviours that we might think are common to several subclasses (in a single-class
hierarchy). They force all subclasses to perform actions for the behaviours. Abstract classes will also
behave as a normal class with its own states and behaviours. Then readers learn interfaces that are like
only managers; they will define some behaviours and expect all implementing classes (from multiple-
class hierarchies) to perform action for those behaviours. This will be followed by enum, which is a
feature to group a set of static final constants as a list.
The later part of this chapter introduces you to the concepts of code reusability. You can group
those common classes that may be used by many others into a package. Packages can also be orga-
nized hierarchically. The final part of this chapter is devoted to handling exceptions which are runtime
errors that are thrown to users indicating some unexpected interruption in the execution of your appli-
cation. So, you handle those errors so that the execution of your program does not terminate.
Listing 7.1 illustrates the abstract class Flower which defines a non abstract data member and
member function, besides an abstract method declaration, namely smell(). Therefore all subclasses
will provide implementation to the abstract method.
//FlowerObject.java
7.3 Interfaces
Interface is called pure abstract class. The reason is that interfaces can contain only data members and
abstract methods. In contrast, abstract classes can contain abstract and nonabstract methods. Whether
you declare or not, all data members in an interface are public final. That means, they will be identi-
fied as constants and you can even assign values. Similarly, all method declarations are public abstract
by default. Interface can also extend another interface.
As an example, let us define an interface Wearable so that we can say flowers such as rose and
jasmine are flowers as well as wearable as shown in Listing 7.2.
interface Wearable
{
public void canWear();
}
Now let us say flowers such as rose and jasmine are flowers as well as wearables. So we create
class Rose and Jasmine by extending class Flower and implementing wearable as shown in L
isting 7.3.
// WearableFlower.java
import java.util.*;
interface Wearable
{
public void canWear();
}
class Flower
{
public String colour;
public void getColour()
{
Scanner sc = new Scanner(System.in);
System.out.print(“Enter colour: ” );
colour = sc.nextLine();
}
}
class Rose extends Flower implements Wearable
{
Here, the object rose invokes getcolor() which is a method available in the base class Flower. The
other two methods are implementations of interface.
<<interface>>
Aircraft
Flyable
Bird
Crow
//FlyableObject.java
interface Flyable
{
public int wings = 2; // by default, public final
public void fly(); // public abstract, by default
}
class Bird
{
int leg; // number of legs
}
The interesting part in this application is the ability of the interface Flyable that represents com-
mon behaviours across multiple-class hierarchies. For instance, the class Aircraft belongs to one class
hierarchy, whereas the class Crow belongs to another class hierarchy namely Bird. Thus, interfaces
are something like bridges that represent the commonalities in multiple-class hierarchies, whereas
abstract classes capture generalization in a single-class hierarchy.
//Machine.java
class State
{
public static final int IDLE = 1;
public static final int RUNNING = 2;
public static final int STOPPED = 3;
}
`1
Here, the state of your welding machine is set to IDLE; So far so good. It prints its state value 1.
But it is not type-safe in the sense that you might set the state of your welding machine to any value
(that does not exist, of course) besides these three states such as
weldingMachine.state = 100;
System.out.println(weldingMachine.state);
So you set a state with value 100 that does not exist and JVM will not generate compilation error.
It does not prevent this setting and displays a value 100. So absolutely no type-safety!
Apart from type-safe problem, you cannot print string labels. The state prints 1 which is the numer-
ical value of its state, but not its string label IDLE. In fact, string labels are more meaningful than its
numerical counterparts. Further, there is no namespace. You need to access it by its class name prefix
such as State.IDLE but not simply IDLE.
So the solution for all these three limitations is enum. Java enum is a type-safe list of static final
constants, providing meaningful string labels and has its own namespace. Enum is created with the
syntax shown in Figure 7.6.
There can be several enum constants which are comma separated, and all these constants are by
default static and final. This implies you are not allowed to change its value. Trying to change enum
constants will generate compilation error. For instance, let us create enum State with three states as
shown in Example 7.1.
Then our Machine can be set with any of these three states from State enum as illustrated in
Listing 7.6.
//Machine1.java
public class Machine1
{
public enum State {IDLE, RUNNING, STOPPED};
State state;
//weldingMachine.state = 4; // ERROR
//System.out.println(weldingMachine.state);
}
}
RUNNING
If the state of the welding machine is assigned to any other value (such as 4) besides its constants,
JVM will generate compilation error. Also there are times that you might need to display the constants
in enum. Then values() method will display them for you as shown in Listing 7.7.
//Machine2.java
public class Machine2
{
public enum State {IDLE, RUNNING, STOPPED};
State state;
IDLE
RUNNING
STOPPED
// State.java
public enum State
{
IDLE(‘I’), RUNNING(‘R’), STOPPED(‘S’);
char code;
State(char c)
{
code = c;
}
};
Note that here State is considered to be an independent class. It need not be just a Java statement.
So you can save it as a Java file and compile it without any problem. Now it is easy to refine our
Machine application so that it will display enum constants along with their attribute values as depicted
in Listing 7.8.
//Machine3.java
public class Machine3
{
public static void main(String[] args)
{
// show all enum constants with its attributes
State[] states = State.values();
for(State s : states)
System.out.println(s.code + “-” + s);
}
}
I-IDLE
R-RUNNING
S-STOPPED
Enum constants can be sent to switch statement as an argument so that enum constants will act like
case options for the switch as illustrated in Listing 7.9.
//Machine4.java
enum State
{
IDLE(‘I’), RUNNING(‘R’), STOPPED(‘S’);
char code;
State(char c)
{
code = c;
}
};
switch(weldingMachine.state)
{
case IDLE:
System.out.println
(“Currently machine is idle”); break;
case RUNNING:
System.out.println
(“Currently machine is running”); break;
case STOPPED:
System.out.println
(“Currently machine is stopped”);
}
}
}
Apart from constructors, any other method can be added to enum just like normal members of a
class. Now let us develop an enum Age that will define three age groups namely NEW, HALFNEW
and OLD with some age ranges for each type; define a method that will return the age range of age
group and develop a static method that will return age group for the given age value. Listing 7.10
explains the complete application for this Age enum.
//Machine5.java
enum Age
{
NEW(0,2), HALFNEW(3,5), OLD(6,10);
Here, getRange() displays 0 and 2 as the minimum and maximum age of the weldingMachine
whose age group is NEW. In the second part, we want to find out the age group of a machine whose
age is 4 years. The getAge() returns HALFNEW as the age group for the 4-year-old machine.
In summary, enums are good for representing predefined list of values. Use it selectively. If you
want to add new values when the application is running, do not use enums.
7.5 Packages
Many times our Java applications consist of few classes; thereby we keep all such classes inside a
single directory. However it will be more difficult if our applications grow into several classes and
files. In such cases, we are grouping them into many categories according to their usability and func-
tionality and keeping them into multiple directories for effective taxonomy.
Java APIs are centred on packages. Some of the packages are already introduced such as java.lang
and java.io. Here, java is a package and lang is a subpackage within java package. Some more pack-
ages such as java.util, java.awt, java.applet and javax.swing will be introduced in Chapter 7 and 16.
Readers are advised to refer to Java API documentation for accessing a complete set of packages
available from Oracle (http://docs.oracle.com/javase/7/docs/api/overview-summary.html).
package package-name;
All those classes we want to bundle together should be saved under the subdirectory with the
ackage-name. Now, let us create a package tools with a class Pr as in Listing 7.11. The class Pr
p
provides overloaded print() and println() methods that will display string and integers. Pr also includes
another method get() that will read an integer from user.
package tools;
import java.io.*;
public class Pr
{
public static void print(String s)
{
System.out.print(s);
}
Here, we create a package named tools and bundle the class Pr into tools. We create a subdirectory
namely tools (see Figure 7.8) from the current directory (assume our current directory is basics) and
save Pr.java in tools directory and compile it.
jdk
basics
loops tools
// PaBiggest2.java
import tools.*;
import java.io.*;
The class Biggest2.java should be saved in the current directory, that is, basics. In this example, we
access the class Pr and utilize two of its methods namely print() and get(). Packages are also useful to
avoid name collisions and to support code reusability. We can create a package io as a subpackage of
tools (see Figure 7.9), so that tools.io package will be different from java.io package.
7.5.4 Subpackages
Subpackages can also be created within a package. Therefore, the classes and interfaces have to be
bundled inside a subpackage. For instance, in Listing 7.13, a subpackage console has been created
within tools package. We add a class Scan to console package.
jdk
basics
loops tools
io
package tools.console;
import java.io.*;
import java.util.*;
Once subpackage (i.e. subdirectory console within the current directory tools) has been created,
then it can be imported into a class where we access the classes and interfaces defined in the sub-
package. We can access subpackage items anywhere before this subdirectory, that is, in any parent
directory. Listing 7.14 shows a class ScanTest that imports all classes of the package console.
import tools.console.*;
import java.util.*;
import java.io.*;
A Achild
C D
Package P1 Package P2
Here, protected data members of class A are visible inside class A, inside class B as B is child class
of A, inside class C as class A and class C belong to the same package P1 and inside the child class of
A namely Achild (though Achild is defined in another package P2). However, class D cannot access
protected members of A as it is defined in P2.
// SimpleException.java
public class SimpleException {
public static void main(String args[])
{
int a = 20;
int b = 0;
int value = a/b;
System.out.println(“value: ” + value);
}
}
In this application, the println() statement displaying value will not be executed because in the
previous line, the integer division by zero is not allowed and it will raise an exception, thereby the
program terminates. So, we need to instruct the application what is to be done when division by zero
occurs. This process is known as exception handling.
Exception handling is a process of identifying possible runtime errors that are likely to happen and
handle or solve this exception so that normal execution will continue. Java supports three constructs
for handling exceptions. They are
■■ try-catch-finally statements, as shown in Figure 7.11
■■ try-resource statement; it will be introduced to the readers in Chapter 14.
■■ Multicatch statement
Try
{
// statements that will possibly throw one or more exceptions
}
catch(exception-type 1)
{
// handling code for exception-type1
}
catch(exception-type n)
{
// handling code for exception-type n.
}
finally
{
// statements to be executed after try block or catch block
}
Try block will contain statements that are likely to throw exceptions. If an exception has occurred,
control is transferred to any one of the catch blocks. Catch block will contain statements that can solve
this exception. Then execution will continue with finally block. Remember, finally block will be executed
irrespective of exceptions. Also, there can be any number of catch blocks for the given single try block.
The application depicted in Listing 7.16 checks three types of runtime errors. A user may enter s omething
other than int that causes parseInt() method unable to convert string into int, may supply a zero for second
number that causes division by zero and intentionally we try to access an array location outside its size.
// ExceptionTest.java
import java.io.*;
import java.util.*;
try
{
int a = Integer.parseInt(args[0]); // user may enter
other than int
int b = Integer.parseInt(args[1]); // user may enter
other than int
C:\jdk>java ExceptionTest 10 o
C:\jdk>java ExceptionTest 10 20
Trying to access outside array index
Think of all possible exceptions while designing your code
When parseInt() is unable to convert, then control is transferred to catch block of NumberFormat
Exception. When division by zero occurs, then control goes to catch block with ArithmeticExcep-
tion. Also, when array[2] is accessed, then control goes to the third catch block where ArrayIndexOut
ofBoundsException is handled. Finally block will be executed anyway irrespective of exceptions.
Exception class hierarchy should be followed when defining exception objects for catch blocks.
// MultiCatch.java
import java.io.*;
public class MultiCatch
{
public static void main(String[] args)
{
try
{
int a = Integer.parseInt(args[0]);
int b = Integer.parseInt(args[1]);
int sum = a / b;
}
catch(NumberFormatException | ArithmeticException e )
{
System.out.println(“Enter only nonzero integers for a
and b”);
}
}
}
C:\jdk>java MultiCatch 10 20
C:\jdk>java MultiCatch 10 0
Enter only nonzero integers for a and b
Throw Statement
The throw statement can be used to create an object of user-defined exception and used inside
try-catch block. For example, a school wants to check the age of a kid for possible admission to its
kinder garden programme. Listing 7.18 explains this application.
Throwable
Exception Error
NullPointerException
NumberFormatException
EOFExecption
IndexOutOfBoundsExcepton
FileNotFoundException
ArithmeticException
MalFormedURLException
ClassCastException
IllegalArgumentException
//UnderAgeExceptionTest.java
import java.util.*;
try
{
if (age < 2)
throw new UnderAgeException(age);
else
System.out.print
(“Your child will be admitted to Kinder
Garden in our school”);
}
catch(UnderAgeException e)
{
System.out.println(e.toString());
}
}
}
Throws Statement
A method can use throws statement to indicate that it might throw the exception back to the caller, so
that the caller can catch this exception and take appropriate action. Listing 7.19 is a revised school
admission application where checkAge() method may throw UnderAgeException exception.
//UnderAgeExceptionTest1.java
import java.util.*;
7.7 Summary
1. Abstract class is a generic root class which defines some behaviours that are to be performed by
subclasses
2. Abstract classes prevent others to instantiate objects, but can have its own members accessible
for its child classes
3. If a method in a class is abstract, then this class must be abstract
4. The subclass of an abstract class must perform the behaviour defined by abstract method. That
is it should provide implementation for abstract method. Otherwise, the subclass should also be
declared as abstract
5. Interfaces are called pure abstract classes
6. Interfaces can define constants and methods that are by default public abstract
7. All implementing classes of an interface must provide implementation to interface methods,
failing which compilation error will be generated
8. Interface can also extend another interface
9. Interfaces represent the commonalities in multiple-class hierarchies, whereas abstract classes
capture generalization in a single-class hierarchy
10. Enum allows us to represent a type-safe predefined set of static values
11. Enum behaves like a public class or interface with its members
12. Packages group classes into taxonomy; thereby classes can import classes and interfaces from a
package
13. Packages can define subpackages
14. Errors can be compile time errors or runtime exceptions
15. Runtime exceptions are handled using try-catch-finally statements
16. Try block includes those Java statements that are likely throw an exception
17. Catch block defines statements that will handle a possible exception type if generated
18. Finally block will be executed irrespective of exceptions whether thrown or not
19. Exception can be piped using multicatch statement
Key terms
Review questions
Multiple-choice Questions
1. Choose all incorrect statements:
1. Static variables can be serialized
2. Transient variables can be serialized
3. To serialize object, you need to implement writeObject() method
4. Objects are deserialized in first-in-first out order
a. 1, 2 b. 2, 3
c. 3, 4 d. 1, 4
2. What is the output?
a. greet() should not have method body b. MorningGreeting does not override greet()
c. Both 1 and 2 d. None of the above
7. How will you make member of a class visible to all subclasses of any package?
a. By declaring it private b. By declaring it protected
c. By declaring it public d. Any of the above
interface Device
{
public void volume();
}
class Phone implements Device
{
public void volume(){}
}
11. Find out the output for the command line: java Test7 hello java:
a. Test7
b. Hello
c. Java
d. Error: varargs cannot be applied to main()
a. Hello b. Finally
c. Hello Finally d. RuntimeException message
e. Hello Finally RuntimeException message
14. Find out the output:
catch(Exception e)
{
System.out.println(“inside catch”);
}
finally
{
System.out.println(“Finally”);
}
}
}
interface A
{
public void a();
}
abstract class B implements A
{
public void a(){};
}
class C extends B
{
public void a()
{
System.out.println(“C”);
}
}
class Test7
{
public static void main(String[] args)
{
new C().a();
}
}
a. C
b. Compilation error
c. Runtime error
d. Runtime Exception
interface A
{
public void a(String s);
}
abstract class B implements A
{}
class C extends B
{
public void a()
{
System.out.println(“A”);
}
public void a(String s)
{
System.out.println(“C”);
}
}
class Test7
{
public static void main(String[] args)
{
new C().a();
}
}
a. A b. A C
c. C A d. Runtime exception
interface A
{
void a(String s);
}
interface B extends A
{
void b(int i);
}
class C implements B
{
public void a()
{
a(“B”);
System.out.println(“A”);
}
public void a(String s)
{
b(100);
System.out.println(s);
}
public void b(int i)
{
System.out.println(“D”);
}
}
class Test7
{
public static void main(String[] args)
{
new C().a();
}
}
a. B A D b. D B A
c. A B D d. Runtime exception
18. Find out the output?
final class A { }
class B extends A {}
public class Test6
{
public static void main(String[] args)
{
new B();
}
}
{
try
{
int x = Integer.parseInt(“ten”);
}
catch (Exception e)
{
System.out.println(“Exception: ” + e.toString());
}
}
}
a. ten b. 10
c. NumberFormatException d. Compilation error
package tools;
public abstract class Furniture
{
public abstract void size();
}
import tools.Furniture;
class Chair extends Furniture
{
public void size()
{
System.out.println(“Kid’s size”);
}
public static void main(String[] args)
{
new Chair().size();
}
}
interface Furniture
{
int size = 3;
void setSize(int n);
}
interface Furniture
{
int size = 3; // statement-1
a. 1, 2, 3 b. 2, 3
c. 2, 3, 4 d. 1, 2, 3, 4
interface Furniture
{
public static int size = 3; // statement-1
static final int size = 3; // statement-2
public final int size = 3; // statement-3
public static final int size = 3; // statement-4
}
a. 1, 2, 3 b. 2, 3
c. 2, 3, 4 d. 1, 2, 3, 4
a. SMALL b. 0
c. 1 d. Compilation error
{
enum TeaSize {SMALL, MEDIUM, LARGE};
TeaSize size = TeaSize.SMALL;
System.out.println(size);
}
}
a. SMALL b. 0
c. 1 d. Compilation error
27. Assume tools and tools2 are packages available inside a directory. What is the output?
package tools;
public class Furniture
{
int i = 10;
protected int j = 20;
}
package tools2;
import tools.*;
public class Chair extends Furniture
{
public static void main(String[] args)
{
Furniture f = new Furniture();
System.out.println(f.i + “,” + f.j);
}
}
a. 10 20 b. 10 followed by exception
c. 20 followed by exception d. Compilation error
28. Assume tools is a subpackage of tools2. Then which of the following statements is correct?
package tools;
public class Furniture
{
int i = 10;
protected int j = 20;
}
package tools2;
import tools.Furniture;
public class Chair extends Furniture
{
public static void main(String[] args)
{
Furniture f = new Furniture();
System.out.println(f.i); // statement-1
System.out.println(f.j); // statement-2
Chair c = new Chair();
System.out.println(c.i); // statement-3
System.out.println(c.j); // statement-4
}
}
a. Statement-1 b. Statement-2
c. Statement-3 d. Statement-4
a. a b. 97
c. Error: try without catch d. Error: try without finally
{
System.out.println((int)c);
}
c = (char) ((int)c + 2);
finally
{
System.out.println(c);
}
}
}
a. a b. 97
c. 97 a d. 97 a followsing by exception message
{
int[] a = {1,2,3};
System.out.println(a[3]);
}
}
class A
{
int x = 10;
}
public class Test7
{
public static void main(String[] args)
{
A a = new A();
A b = new A();
a = null; b.x = 100;
System.out.println(a.x + “,” + b.x);
}
}
class A
{
int x = 10;
}
class B extends A
{
int y = 20;
}
public class Test7
{
public static void main(String[] args)
{
A a = new A();
B b = (B)a;
System.out.println(b.y);
}
}
{
m1();
}
}
a. 1 b. 1 2
c. 1 2 3 d. 1 1 1
a. 1 b. 2
c. Throws Exception d. Displays 1 indefinitely
class A
{
public void m1() {System.out.print(“A”); }
}
class B extends A
{
public void m1() {System.out.print(“B”); }
public void m2() {System.out.print(“C”); }
}
public class Test61
{
public static void main(String[] args)
{
A a = new A();
a.m1();
a = new B();
a.m1();
a.m2();
}
}
a. Compilation error b. A B C
c. A A C d. B B C
e. A followed by exception
class A {}
public class B extends A
{
public void m1() {System.out.print(“B”); }
public static void main(String[] args)
{
A a = new B();
B b = (B)a;
b.m1();
}
}
a. B b. No output
c. Compilation error d. throws ClassCastException
Answers
1. a 2. c 3. e 4. b 5. c 6. e 7. b 8. c 9. d 10. c
11. c 12. a 13. e 14. d 15. c 16. a 17. b 18. a 19. c 20. c, d
21. a 22. a 23. d 24. d 25. a 26. d 27. d 28. d 29. c, d 30. a
31. a 32. a 33. d 34. c 35. d 36. a 37. c 38. e 39. a 40. a
Short-answer Questions
1. What is an abstract class? Why do we need abstract classes?
2. Explain abstract class and abstract methods with an example.
3. What is an interface? Explain interfaces with an example.
4. Compare abstract classes and interfaces.
5. What is enum? Why do we need enums?
6. Explain advanced features of enum such as variables, methods and constructors of enum class.
7. Explain java package concepts with an example.
8. What is an exception? Explain exception handling concepts with an example.
9. Explain multi catch statement with an example.
10. Discuss exception hierarchy.
11. How to create user-defined exceptions?
12. Explain RuntimeException class with an example.
Exercises
7.1. Create an abstract class Breakfast with two abstract methods checkCarb(), and checkNutri-
ents(). If carb count is less than 200, breakfast is healthy. If it contains all nutrients such as
vitamins, minerals etc, breakfast is healthy. Create three sub classes Indian, Mediterranean and
Chinese and all subclasses should override the two abstract methods by providing appropriate
implementations. Create a public class that will create objects of these three breakfast imple-
mentations, and call implementation methods.
7.2. Consider Exercise 6.6, create interface Healthy with a method eat() indicating this is eatable
food. Class Food should implement Healthy and override eat() method. Let eat() display a mes-
sage You can eat this food.
7.3. Consider Exercise 6.6, create interface Juicy with methods squeeze() to prepare juice and drink()
to indicate it is a drinkable juice. Class Fruit should implement Juicy and override squeeze() and
drink() methods. Let squeeze() display a message Juice ready and drink() display a message
Have a nice drink. Test these classes and methods accordingly inside class Lunch.
7.4. Create enum TrafficLight with three constants RED, YELLOW and GREEN. Each constant has
a string attribute, “stop”, “wait” and “go” respectively. Define a method show() that displays
the attribute values of each light. Create a public class that displays these three lights and their
attribute values.
7.5. Create enum Snacks with three constants CHOCHOLATE(200), COOKIES(50), ICECREAM
(100), where attribute values indicate calories of the snack. Define a method setCalories(int)
that can change the attribute values of enum constants. Create a public class that will call
setCalories() with a new value. Also display enum constants and their calories.
7.6. Create a package tools in the current directory and a subpackage io inside tools package. Create
a class Print with a method s(String s) that prints a given string. Save Print onto io package.
Create a class PrintTest in the current directory, import Print class and call s(“hello”) and check
hello is printed onto the command window.
7.7. Provide overloaded methods for s() that will take variety of other types such as int, float,
double, long and char. Test these overloaded methods.
7.8. Create an exception NegativeBalanceException with a data member private double balance
and override toString() to print appropriate message. Create a public class Account with a data
member balance. Assign values to balance and accordingly throw this exception.
Objectives
■■ To introduce java.util class hierarchy
■■ To create Vector object; add primitives, wrappers and objects to vector; and retrieve elements
from vector
■■ To create Enumeration iterator to vectors and explain how to iterate over vector objects
■■ To implement type-specific vectors that will hold specific types only
■■ To create StringTokenizer with default delimiter and user-defined delimiters
■■ To create Stack and explain stack operation such as push and pop
■■ To implement type-safe stack
■■ To solve brackets matching problem using stacks
■■ To introduce Iterator interface and its methods
■■ To introduce Queue interface and queue implementations using PriorityQueue and LinkedList-
based queue
■■ To explain creating ArrayList and type-safe ArrayList
■■ To solve shopping cart problem using array list
■■ To search a key in an array using ArrayList
■■ To merge two arrays using ArrayList
■■ To remove duplicates from an array using ArrayList
■■ To create LinkedList and explain all its methods
■■ To implement type-safe LinkedList
8.1 Introduction
Holding data inside an application is the fundamental requirement for solving any problem. Java has
several ways to hold primitive data type values and objects (or rather, references to objects). In the pre-
vious chapters, the readers were introduced to some of the methods to store a single value or a collec-
tion of values. To hold a single value, variables were used and to store a set of values arrays were used.
The array is the most efficient container to store values and object references in a linear sequence.
Also, array elements can be randomly accessed with the index. Apart from efficiency of random access,
arrays are type specific. That means, arrays will store elements of the same type. For example, an int
array will hold only integers and a Dog array will hold only dogs. Storing an inappropriate element
to array will result into a compile time error. Java will notify all mistakes during compilation itself.
Though arrays are faster, they are static data structure which means array’s size is fixed and cannot
be changed once created, during runtime. For dynamic data structures, Java utilities library named
Collections has a reasonably complete set of classes in java.util package that provide sophisticated
ways to store objects and manipulate them. Whatever may be the container type such as Lists, Maps
and Sets, all containers will store objects (wrapper types or user-defined types) as java.lang.Object,
the root of all classes in Java. Since user objects are upcasted to Object type, you have lost the type
information of your object. In other words, container classes will not bother about type checking at
compile time. So you need to downcast into a specific type you want when you retrieve objects from
the container. This is where arrays are better than containers.
Part 3 of this book containing four chapters focuses on Java’s built-in support for data structures and
algorithms. For the sake of simplicity, we refer to all collection classes and interfaces available in java.
util package as containers. This chapter deals with all List containers. The Map and set containers are dis-
cussed in Chapters 9 and 10 respectively. Chapter 11 is devoted to the discussion on sorting and search-
ing support available in java.util package. In this chapter, we will lead you to the understanding of all List
and Queue types such as Vector, StringTokenizer, Stack, PriorityQueue, ArrayList and LinkedList.
We will see the features of each container, its advantages and how to apply them to different problems.
8.3 Vectors
The Vector class is one of the important classes for application development in Java. The Vector is a
growable array of objects. Similar to arrays, it contains objects that can be accessed using an integer
index. The size of the Vector can expand or shrink in order to accommodate adding and removing
objects after the Vector has been created. Vector can be created as shown in Figure 8.2.
Collection PriorityQueue
LinkedHashSet Vector
StringTokenizer
Stack
Arrays
Map
Collections
Vectors can be created with a default constructor or it can also take any of the collection types such
as List types, Set types or Map types. Remember Vector is also part of a Collection. So a vector can
contain even another vector.
Once Vector is created, then objects can be added, removed and retrieved from it as and when
required. Objects can be added to vector using add() and addElement() methods and retrieved
using get(index) and elementAt(index) by the given index position. The size() method returns its
size. The remove(index) and removeElementAt(index) methods remove an element at index and
removeElement(o) removes object o.
Listing 8.1 depicts a course vector that will hold list of courses and manipulate its contents using
various methods.
// CourseVector.java
import java.util.*;
{
public static void main(String[] args)
{
// create a vector
Vector v = new Vector();
// insert at 1
v.add(1, “BCOM”);
// remove BCA
v.removeElement(“BCA”);
// remove at 0
v.remove(0);
Element 2: MCA
BCOM
BSc
MCA
BE
BArch
Recall that Vector can hold object of any type in contrast to arrays. So, it is the responsibility of
the developer to downcast into appropriate type while retrieving elements. In the above example,
we downcast elements to String type while retrieving them from vector. Listing 8.2 illustrates
type-specific problem of a vector.
//AnimalsVector.java
import java.util.*;
class Cat
{
int i;
public Cat(int j) { i = j; }
}
class Dog
{
int i;
public Dog(int j) { i = j; }
}
class Fish
{
int i;
public Fish(int j) { i = j; }
}
// add animals
animals.add(new Cat(2));
animals.add(new Dog(5));
animals.add(new Fish(9));
}
}
Displaying Animals
Cat number: 2
Dog number: 5
Fish number: 9
Here, animals vector contains objects of different types such as Dog, Cat and Fish. Therefore,
objects have to be appropriately downcasted while retrieving using get() method.
8.3.1 Enumeration
Enumeration is the iteration interface that enables us to loop through the vector. With hasMoreEle-
ments() and nextElement() methods, you can check for elements and extract the next object. L
isting 8.3
explains adding Cat objects to a vector and retrieving elements using enumeration.
Listing 8.3. Cats Using Enumeration
// CatEnumerator.java
import java.util.*;
class Cat
{
int number;
Cat number: 0
Cat number: 1
Cat number: 2
Cat number: 3
Cat number: 4
For example, let us create an Integer vector (see Listing 8.4) that will hold only Integers. Any
attempt to add objects of any other type other than Integer will generate a compile time error.
// IntVector.java
import java.util.*;
200
100
500
8.4 StringTokenizer
The StringTokenizer class splits a string into a number of tokens that are delimited by \s, \t, \n, \r
and \f, by default. Delimiters can also be specified during initialization as a string. Figure 8.4 shows
the syntax for StringTokenizer.
// StringTokenizerTest.java
import java.io.*;
import java.util.*;
// nested st
StringTokenizer st3 = new StringTokenizer(s2, “*”);
while (st3.hasMoreTokens())
{
String str = st3.nextToken();
// tokenize again
I
am
a
bad
boy
Anita Trichy
Beryl Chennai
Cathy Bangalore
Anita
Trichy
Beryl
Chennai
Cathy
Bangalore
8.5 Stack
The Stack class supports a last-in-first-out (LIFO) behaviour of objects. The push() and pop() meth-
ods insert and remove objects, whereas peek() returns the top item on the stack. The empty() method
tests whether the stack is empty or not and search(o) method returns the position of o from top.
Stack will also behave as a vector as it inherits from Vector, and so usual Vector operations can be
performed on Stack too.
Listing 8.6 creates a Stack to push names of months in the reverse order and pops them one at a
time from the stack until the stack is empty.
// MonthStack.java
import java.io.*;
import java.util.*;
Dec
Nov
Oct
Sep
Aug
Jul
Jun
May
Apr
Mar
Feb
Jan
// CharStack.java
import java.util.*;
// BracketChecker.java
import java.io.*;
import java.util.*;
//
if stk is empty, given expr is perfectly balanced
if(stk.empty())
System.out.println(“The given expression ” + expr +
“ is perfectly balanced”);
else
System.out.println(“The given expression” + expr +
“ is NOT perfectly balanced”);
}
In this application, match() first receives an expression with all three bracket types from user
as a string. Then, it takes one character at a time from the string and checks if it is any of the three
open bracket types. If so, the character is pushed onto stack. If the character is of closing bracket
types, then stack is popped once. Otherwise, the next character will be read and processed. This
process will be repeated for all characters. The given expression is perfectly balanced if stack
is empty.
8.6 Iterators
An iterator is, like a cursor, an object, similar to enumeration that is used to move through the objects
and select each object from the container. The Iterator interface has two methods hasNext() and next()
to check whether container has some more elements to be read and to retrieve the actual element.
8.7 PriorityQueue
PriorityQueue is the implementation of the Queue interface. PriorityQueue stores elements in first-
in-first-out (FIFO) order, but not necessarily in this order. The offer() inserts an object to tail of queue.
The remove() and poll() delete elements from head of queue. The element() and peek() return the head
of queue without deleting it. If you want to preserve the order of insertion, then create a queue with
LinkedList.
As an illustration, assume a supermarket has one billing counter where each user’s shopping basket
will be billed. There are many customers waiting for billing in the queue. New customers will also
join the queue. Listing 8.9 simulates this supermarket scenario.
// SupermarketQueue.java
import java.util.*;
public SuperMarketQueue(Queue q)
{
billingCounter = q;
}
// process customers
q.addCustomer(r.nextInt(100));q.show();
q.addCustomer(r.nextInt(100));q.show();
q.service();q.show();
q.addCustomer(r.nextInt(100));q.show();
q.service();q.show();
}
}
In this program, queue is created with PriorityQueue and LinkedList. As discussed earlier,
riorityQueue need not maintain the queue’s FIFO behaviour. But, LinkedList-based queue maintains
P
FIFO ordering of customers. The readers will learn more about LinkedList in section 8.9. The rest of
the program is trivial. You add customers to queue with offer() and service them one at a time from
head of the queue using poll(). You service customers if queue is not empty. The isEmpty() checks
whether queue is empty or not.
8.8 ArrayList
Both ArrayList and LinkedList are two types of List interface. The List interface defines add() method
to insert objects, get() to retrieve objects and remove() to delete an object or an object by index and
size() returns size of the List. The List returns both iterator() and the sophisticated listIterator() that
are useful for ArrayList and LinkedList. One important point about List, it allows duplicate elements.
ArrayList is the resizable array implementation for the list. ArrayLists support faster random access
to elements, but relatively slow for insertion and deletion of elements. ArrayList is an exact equivalent
of Vector class but it is unsynchronized. Listing 8.10 explains various methods of ArrayList class.
// ArrayList1.java
import java.util.*;
list.add(breakfast[i]);
list.add(“French Fries”);
Coffee
Bread
Omlet
Juice
Coffee
Bread
Omlet
Juice
French Fries
Here, object-type can be any of the wrapper class types or any Java object including user-defined
object types. Example 8.1 depicts the creation of array list which can hold objects of type, class Item.
class Item { }
ArrayList<Item> items = new ArrayList<Item>();
In this example, items will hold an array of objects of type Item class.
// ShoppingCart.java
import java.util.*;
class Item
{
String name;
public Item(String s) { name = s; }
}
// type-specific arraylist
ArrayList<Item> list = new ArrayList<Item>();
// add to list
for(int i = 0; i < purchase.length; i++)
list.add(new Item(purchase[i]));
// show
ListIterator it = list.listIterator();
while(it.hasNext())
System.out.println(((Item)it.next()).name);
}
}
Laptop
Pen
Notebook
//SearchArrayList.java
import java.util.*;
// get a character
System.out.println(“Enter a character”);
String key = sc.next();
// check if exists in list
if(list.contains(key))
System.out.println(key + “ is a vowel”);
else
System.out.println(key + “ is NOT a vowel”);
}
}
Enter a character
u
u is a vowel
Enter a character
U
U is NOT a vowel
Here, Arrays.asList() converts the given array into a list with which ArrayList object is i nstantiated.
//MergeArrays.java
import java.util.*;
//merge
list1.addAll(list2);
// get a character
System.out.println(“Enter a character”);
String key = sc.next();
if(list1.contains(key))
System.out.println(key + “ is a vowel”);
else
System.out.println(key + “ is NOT a vowel”);
}
}
Enter a character
e
e is a vowel
Enter a character
E
E is a vowel
In this application, both lowercase and uppercase vowels are merged into a single list. Thereby this
application recognizes vowels case insensitively.
//RemoveDuplicates.java
import java.util.*;
// get a character
System.out.println(“Enter a duplicate char to
remove”);
String key = sc.next();
// show list
System.out.println(“After duplicates removed: ”
+ list.toString());
}
}
There is another interesting collection that will not allow you to add duplicates. So you need
not have to worry about eliminating duplicate elements. It is called set and will be introduced in
Chapter 10.
8.9 LinkedList
The LinkedList is another container that will store elements in a sequence. LinkedLists are highly
inexpensive for insertion and deletion operations, but relatively slow for random access. ArrayList
scores better for random access.
LinkedList supports several methods with which we can design other containers such as stack,
queue and deque. The add(), addFirst() and addLast() methods allow us to add elements to linked list.
The get(), getFirst() and getLast() methods retrieve elements from linked list. Similarly, remove(),
removeFirst() and removeLast() methods delete elements. Contains() checks for an element and size()
returns the size. Listing 8.15 explains the various methods of LinkedList class.
// LinkedList1.java
import java.util.*;
// add 10 integers
for(int i = 0; i < 10; i++)
list.add(i);
In the above example, we add integers as primitives and characters to LinkedList using automatic
boxing and unboxing methods. Using generics, we can create type-safe linked list that holds only the
specific values like arrays.
// LLStack.java
package tools;
import java.util.*;
class LLStack
{
// create LinkedList
private LinkedList list = new LinkedList();
if(!list.isEmpty())
return list.removeFirst();
return “Stack empty, cannot pop”;
}
So it is time for us to try our stack LLStack instead of java.util’s legacy Stack class for the brackets
checking application. Assume LLStack is stored in tools package, so that our application will import
tools package. Listing 8.17 illustrates our new BracketChecker application.
// BracketCheckerLLStack.java
import java.io.*;
import java.util.*;
import tools.*;
The above application uses our linked list-based LLStack to check proper nesting of parenthesis in
a given expression. However, there is one issue with our LLStack. Our LLStack is not type-safe. In
other words, it has been designed to push and pop elements as java.lang.Object. So now we need to
design our LLStack as generic one such that it will hold only type-safe elements.
// GenericLLStack.java
import java.util.*;
class GenericLLStack<T>
{
private LinkedList<T> list = new LinkedList<T>();
public T pop()
{
return list.removeFirst();
}
public T peek()
{
return list.getFirst();
}
{
return list.isEmpty();
}
public void show()
{
ListIterator it = list.listIterator();
while (it.hasNext())
System.out.print(it.next() + “ ” );
}
//stk.push(“Hello”); Error
Integer stack
pop: 3
99 9 2
character stack
pop: X
W D A
8.10 Summary
1. The java.util package includes few important interfaces such as Collection, Set, List, Queue and
Map. It also includes their corresponding implementations
2. It contains some important classes Collections, Arrays, Random, Date and StringTokenizer
3. The Vector is a growable array that can hold any primitives or objects of any type
4. The Vector can be created type-safe using generics
5. Enumeration is an iterator that can move through a vector
6. StringTokenizer will split a string into series of tokens
7. The split() method of String class can also split string into an array of strings
8. The Stack supports LIFO behaviour. Stack can also be used as vector as it extends Vector
9. Stack can be made type-safe
10. Java 1.2 supports Iterator interface, besides Enumeration interface
11. PriorityQueue is the implementation for Queue interface. It simulates FIFO behaviour, but not
necessarily
12. Design LinkedList-based Queue to obtain exact FIFO behaviour
13. ArrayList and LinkedList are the two List implementations
14. ArrayList is the resizable array implementation for the list. ArrayLists support faster random
access to elements, but relatively slow for insertion and deletion of elements
15. LinkedLists are fast for insertion and deletion of elements
16. ArrayList and LinkedList can be created type-safe
17. Data structures such as stack, queue, trees and doubly linked lists can be created using LinkedList
class
18. Generics can be applied to classes so that type-safe classes can be created
Key terms
Review questions
Multiple-choice Questions
1. What is the output?
class Train
{
public boolean equals(Object o)
{
boolean b = false;
if (o instanceof Train)
b = true;
return b;
}
}
public class Test8
{
public static void main(String[] args)
{
Train t1 = new Train();
Train t2 = new Train();
if(t1.equals(t2))
System.out.println(“same”);
else
System.out.println(“not same”);
}
}
class Train
{
public boolean equals(Train o) { } // method1
public boolean equals(Object o) {} // method2
boolean equals(Object o) { } // method3
boolean equals(Train o) { } // method4
}
a. method1 b. method2
c. method3 d. method4
3. For a given identical objects o1 and o2, if o1.equals(o2) returns true, then o2.equals(o1) will be
a. True b. False
c. May be true d. May be false
4. Which of the following in an interface?
a. Collection b. Collection
c. Collections d. None of the above
16. Which of the following interfaces define methods to store key-value pairs?
a. List b. Map
c. Set d. None of the above
17. I need a collection that stores key-value pairs. I do not worry about the insertion order or natural
order. Which of the following is the best for me?
a. HashSet b. HashMap
c. LinkedHashMap d. None of the above
18. Which of the following is a thread-safe collection?
a. Hashtable b. HashTable
c. HashMap d. Hashmap
e. None of the above
19. Which of the following stores key-value pairs and supports faster iteration?
a. HashMap b. LinkedHashMap
c. TreeMap d. None of the above
20. Which of the following stores key-value pairs and supports faster insertion and deletion?
a. HashMap b. LinkedHashMap
c. TreeMap d. None of the above
21. Which of the following stores key-value pairs and maintains natural sorted order?
a. HashMap b. LinkedHashMap
c. TreeMap d. None of the above
22. Which of the following is used to store key-value pairs?
a. Set b. Map
c. HashMap d. List
23. What is the correct way of creating ArrayList?
1. ArrayList list1 = new ArrayList();
2. List list2 = new ArrayList();
3. List<String> list3 = new ArrayList<String>();
4. List<String> list3 = new ArrayList<>();
a. 1 and 2 b. 3 and 4
c. 2 and 3 d. All of the above
24. What is the output?
a. Compilation error
b. ClassCastException
c. Displays 100 and throws NullPointerException
d. None of the above
26. Find out the output?
a. True b. False
c. Compilation error d. Runtime exception
27. What is the output?
a. [a,d,r,x] b. [r,a,x,d]
c. [x,r,d,a] d. random order because of unique
hash code
28. What is the output?
class Ball
{
static int i = 1;
public String toString()
{ return “Ball” + (i++); }
}
public class Test8
{
public static void main(String[] args)
{
ArrayList<Ball> l = new ArrayList<Ball>();
l.add(new Ball());
l.add(new Ball());
l.add(new Ball());
System.out.println(l);
}
}
a. 000 b. 012
c. 123 d. None of the above
a. 012 b. 123
c. 000 d. 111
33. Choose the incorrect array list declaration:
class Ball{}
1. List<Ball> l1 = new ArrayList<Ball>();
2. ArrayList<List<Ball>> l2 = new ArrayList<List<Ball>>();
3. List<List<Ball>> l3 = new ArrayList<ArrayList<Ball>>();
4. ArrayList<List<Ball>> l4 = new ArrayList<List<Ball>>();
a. 1 b. 2
c. 3 d. 4
class Ball
{
static int i = 1;
public String toString()
{ return “Ball” + (i++); }
}
public class Test8
{
public static void main(String[] args)
{
Vector<Ball> v = new Vector<Ball>();
for(int i = 0; i < 3; i++)
v.add(new Ball());
for(int i = 0; i < 3; i++)
System.out.print(v.get(i));
}
}
a. 6 b. 4
c. 1 d. None of the above
String s = “I*am*bad//you//are**bad”;
StringTokenizer st = new StringTokenizer(s, “*/”);
while(st.hasMoreTokens())
System.out.print(st.nextToken() +“ ”);
a. a b c d b. d c b a
c. abcd d. dcba
stk.add(“2”);
System.out.print(stk.get(1));
stk.pop();
stk.push(“1”);
System.out.print(stk.push(“2”) + “” + stk.pop());
a. 122 b. 222
c. 212 d. 211
39. What is the output?
a. 122 b. 121
c. 112 d. 221
41. What is the output?
a. [1,2,3,4] b. 1234
c. Compilation error d. No output
a. 12 b. 123
c. 1231 d. 2true2
class Car
{
public String toString()
{
return “Benz”;
}
}
public class Test8
{
public static void main(String[] args)
{
Car car = new Car();
System.out.println(car);
}
}
a. Benz b. Car
c. Car d. Null
46. For a given two objects o1 and o2, if o1.equals(o2) is true, then the hashcode of these objects
will be
a. Same
b. Different
c. Hashcode will not be generated for identical objects
d. None of the above
class A {}
public class Test8
{
public static void main(String[] args)
{
A a1 = new A();
System.out.println(a1.hashCode());
}
}
Answers
1. a 2. b 3. a 4. b 5. a 6. d 7. a 8. c 9. a, b 10. c
11. b 12. c 13. b 14. c 15. d 16. b 17. a 18. a 19. a 20. b
21. c 22. c 23. d 24. d 25. b 26. a 27. a 28. c 29. d 30. d
31. a 32. a 33. c 34. d 35. c 36. a 37. b 38. a 39. c 40. c
41. d 42. c 43. d 44. a 45. a 46. a 47. a
Short-answer Questions
1. Explain the important java.util classes and interfaces hierarchy.
2. Explain important methods of Vector class.
3. What are the advantages of Enumeration interface?
4. How Enumeration differs from Iterator interface?
5. What are the default delimiters for StringTokenizer?
6. Explain Stack with suitable example.
7. Can Stack behave like a Vector?
8. Explain important methods of PriorityQueue.
9. Differentiate Vector and ArrayList.
10. Explain important methods of LinkedList.
11. Create a doubly linked list using only LinkedList methods.
12. Create a circular linked list using only LinkedList methods.
Exercises
Objectives
■■ To introduce Map interface with an overview of its three implementation types
■■ To create Hashtable and store key-value pairs to Hashtable
■■ To add collections such as LinkedList and iterators to Hashtable
■■ To solve word counting of a text problem
■■ To check bracket pairs and brackets nesting in an expression
■■ To introduce HashMap and explain its methods
■■ To explain multimaps and nested HashMaps
■■ To explain LinkedHashMap to store pairs of elements
■■ To introduce TreeMaps and explain its natural ordering of its pairs
■■ To solve random number generation problem
■■ To explain how to create a property file
■■ To populate Hashtable pairs from a file using Properties class
9.1 Introduction
In Chapter 8, the readers were introduced to containers that will hold elements in sequence. List con-
tainers such as arrays and linked lists hold elements in a sequence. Each list type has some merits.
ArrayList is efficient like arrays. LinkedList is quick for insertion and deletion operations. Map is
an interface that will associate keys and their values, similar to dictionaries keeping words and their
meanings. In this chapter, the readers will be introduced to three flavours of Map implementations
namely HashMap, LinkedHashMap and TreeMap. All these maps have the same basic map inter-
face, but they differ in behaviours including efficiency and the order in which key-value pairs are held.
Performance of Maps is relatively better than Lists. Searching through ArrayList is slower, compared
to searching for a key in HashMap. Maps use hash code for efficient search. This results in dramatic
improvements in performance. LinkedHashMap makes insertion and deletion much faster, whereas
TreeMap maintains natural ordering of its pairs. Apart from these maps, you will also be introduced to
Hashtable, an old legacy class in earlier JDK versions and Properties which will load pairs from files.
9.2 Hashtable
Hashtable is an another interesting container that maps keys to values. Any non-null object can be
used as key or value. Hashtable is thread-safe and cloneable. Hashtable is a legacy class in util pack-
age. The put() inserts key and value to Hashtable, whereas get() retrieves value for the given key. The
keys() and elements() return an Enumeration. The containsValue() and containsKey() check the value
and key. The equals() checks the given object and remove() deletes a pair given key.
Listing 9.1 creates a Hashtable that will store user login details such as user name and his password.
import java.io.*;
import java.util.*;
System.out.println(“login.get(alex):” + login.get(“alex”));
System.out.println(“login.contains(123ff): ” + login.
contains(“123ff”));
System.out.println(“login.containsKey(rex): ” + login.
containsKey(“rex”));
System.out.println(“All keys”);
Enumeration ekeys = login.keys(); // all keys
while(ekeys.hasMoreElements())
System.out.println(ekeys.nextElement());
System.out.println(“All values”);
Enumeration evalues = login.elements(); // all values
while(evalues.hasMoreElements())
System.out.println(evalues.nextElement());
}
}
login.get(alex):12ff
login.contains(123ff): true
login.containsKey(rex): true
All keys
john
alex
rex
All values
235ff
12ff
123ff
Recall, Hashtable can store any key-value pairs as objects, which includes any container. Suppose
we want to map a set of linked lists as values for given keys. This can be easily done with Hashtables
as shown in Example 9.1.
The values() returns all values as a Collection, so you can create Iterator to your Hashtable too as
shown in Example 9.2.
Like other containers, Hashtable can also be created as a type-safe data structure. Therefore keys and
values can use generics for type-safety. For example, let us create a type-safe Hashtable where key is
a String and value an Integer as shown in Figure 9.1.
// WordCounter.java
import java.io.*;
import java.util.*;
while (st.hasMoreTokens())
{
// get next token
String word = st.nextToken();
// increment
count++;
}
else
{
// else new key, so initialize with count 1
ht.put(word, 1);
}
}
// display ht
System.out.println(ht.toString());
}
}
// SensitiveBrackerChecker.java
import java.io.*;
import java.util.*;
class SensitiveChecker
{
// create stack
Stack<Character> stk = new Stack<Character>();
// create scanner
Scanner sc = new Scanner(System.in);
Hashtable<Character, Character> ht =
new Hashtable<Character, Character>();
// return
return isProper;
}
3+2*(5+8)
The given expression is perfectly balanced
3+2*(5+6*{2+1}+3)
The given expression is perfectly balanced
3+2*[1+1}+1
Open and close bracket do not match
The given expression is NOT perfectly balanced
In this Sensitive bracket checker application, we keep brackets in a Hashtable. All open bracket
types will be keys and corresponding closing types are values. Whenever a closing bracket type is
encountered in the input string, our application will check whether stack top and this closing bracket
type are proper pairs by consulting Hashtable. If there is an entry in the Hashtable with these two
values, then they are couples.
9.5 HashMap
The HashMap is a container implemented with Hashtable. HashMap performs insertion and retrieval
in constant time. Performance can be tuned with capacity and load factor of the Hashtable. One
notable difference between HashMap and Hashtable is that HashMap allows null values for keys
and values. But HashMap is not thread-safe like Hashtable. Similar to Hashtable, HashMap provides
put(), get(), containsKey(), containsValue(), size() and values() methods for basic operations. There
are some differences between Hashtable and HashMap:
■■ Hashtable supports Enumeration, but not HashMap
■■ HashMap allows us to iterate over key-value pairs, but not Hashtable
■■ Removing elements during iteration is safe with HashMap, but not with Hashtable
Listing 9.4 depicts a type-specific HashMap that maintains country codes as keys and names of
countries as values. Both keys and values are stored as Strings. Apart from various Map methods, this
application explains different ways of iterating maps using Iterators and for-each statement.
// CountryMap.java
import java.util.*;
System.out.println(“IN: ” + map.get(“IN”));
System.out.println(“Contains key UK: ” + map.
containsKey(“UK”));
System.out.println(“Contains Value Germany: ” +
map.containsValue(“Germany”));
IN: India
Contains key UK: true
Contains Value Germany: true
All keys
[JP, US, IN, DE, UK]
All values
Japan
United States
India
Germany
United Kingdom
All keys and values using Iterator
JP,Japan
US,United States
IN,India
DE,Germany
UK,United Kingdom
9.6 Multimaps
A multimap is a map (such as HashMap or Tree Map) but it can map each key to multiple values.
Multiple values can be specified using any of the Lists such as array list or linked list. Figure 9.2
depicts an example that creates a multimap.
Here, values are stored as an Array List, where each list holds a set of strings.
// SuperMarketHMap.java
import java.util.*;
// init states
int j = 0;
stateCity.put(states[j++], citySMarket);
stateCity.put(states[j++], new HashMap());
stateCity.put(states[j++], new HashMap());
stateCity.put(states[j++], new HashMap());
}
In this program, the two-level hashmap is first initialized with state, city and supermarket infor-
mation. Then users are asked to supply state code and city name as inputs, and accordingly both
hashmaps are searched and the corresponding list of supermarkets are retrieved. Furthermore, asList()
from Arrays class is used to create a list from an array. The readers will learn more about Arrays at
the end of this chapter.
9.8 LinkedHashMap
LinkedHashMap, a subclass of HashMap, contains the behaviours of both Hashtable and LinkedList.
Since it uses a doubly linked list, it maintains the insertion order of elements with Least Recently
Used (LRU) method. It permits null values for its keys and values, insertions and deletions can be
done at constant time and iteration is slightly costly, compared to HashMaps.
LinkedHashMaps differ from HashMaps in few ways as shown below:
■■ LinkedHashMap preserves the order of elements insertion
■■ HashMap does not require the expense of maintaining the linked list. However, both are not
thread-safe
Listing 9.6 explains LinkedHashMap methods for retrieving language name given its code.
// LanguageLHMap.java
import java.util.*;
Listing 9.7 explains how linked hashmap preserves the order of insertion of elements. In contrast
hashmap just maintains its elements according to its hashcode.
// RhymesLHMap.java
import java.util.*;
Since Map is an interface, any of its implementations can be assigned to Map. So init() can receive
any of Map type such as HashMap and LinkedHashMap as arguments.
9.9 TreeMap
TreeMap is a red black tree-based implementation of maps. TreeMap maintains keys or key-value
pairs in sorted order automatically. The subMap() method returns a portion of TreeMap. TreeMap
provides log time performance for checking, retrieval and removal. As others, tree maps are not
thread-safe. A TreeMap can be simply created and put() and get() methods insert pairs and retrieve
value for a given key as usual. Example 9.3 depicts a tree map.
The first example simply creates an instance of TreeMap. The second example creates a tree map
whose value is again a tree map (you can call nested tree map of course). The inner tree map has List
as values.
Listing 9.8 illustrates the important methods of tree map. It also compares the output of hashmap,
tree map and linked hashmaps.
// RhymesTMap.java
import java.util.*;
From the output, you can easily understand that hashmaps hold pairs according to their hash code;
linked hashmap maintains the order of insertion of pairs and tree map maintains sorted sequence of its pairs.
//RandomNumberMap.java
import java.util.*;
class Counter
{
int i;
public Counter(int j) { i = j; }
public String toString() { return Integer.toString(i);}
}
// type-safe TreeMap
TreeMap<Integer, Counter> map = new TreeMap<Integer, Counter>();
// check if it exists
if(map.containsKey(rno))
((Counter)map.get(rno)).i++; // get its value
else // new count
map.put(rno, new Counter(1));
}
// show all numbers
System.out.println(map);
}
We can observe from the output of this application that random numbers (between 0 and 19) are
generated almost equally around 5000 times.
So, having seen three types of maps, which type scores better? This is a natural question we all
have in mind. You could follow a general rule of thumb to select any of the maps as below:
■■ Hashtable is suitable for threads
■■ HashMap is slightly better than Hashtable, but not thread-safe
■■ TreeMap is slower than HashMap, but suitable if you need the map in sorted order
■■ Linked HashMap is slower than HashMap, but it is preferred if more number of insertions and
deletions happen
9.11 Properties
Properties class, a subclass of Hashtable, manages key-value pairs as persistent objects in a file.
In each pair, key and values are String types. Before Properties class is instantiated, a property file
should be first created (using any text editor) as shown in Figure 9.3. Each property pair will use a
delimiter in between key and value. Some of the delimiters are =, : and \t characters. The characters #
and ! represent a comment statement in the property file.
# country.prop
lang=ta
currency=inr
capital=newdelhi
Once property list is created with a set of key-value pairs as a file, then we can call this list and
populate our Properties class using load() method. The getProperty() returns the value for the given
property key. Listing 9.10 illustrates how to populate Properties object using property list.
// PropertiesCountry.java
import java.util.*;
import java.io.*;
Here, load() populates properties object with property file using FileReader. FileReader is a Reader
available in java.io package. It opens the file for reading by load(). The readers will be introduced to
more about files in Part 4 of this book.
9.12 Summary
1. Map is another important interface that provides methods to add and retrieve key-value pairs of
objects
2. HashMap, LinkedHashMap and TreeMap are the three important map implementations
3. Hashtable is a popular legacy class of Java 1.0 and Java 1.1 for holding key-value pairs
4. Hashtable can be populated with property list from files
5. Hashtable can hold any collection types
6. For counting different words in a given text, Hashtable can keep words as keys and its count as
values
7. HashMap is an implementation of Map and it is same as Hashtable
8. HashMap is not thread-safe, but Hashtable is thread-safe
9. HashMap supports Iterator, whereas Hashtable supports only Enumeration
10. Lists can be added as values for HashMap, and this type of HashMap is called multimap
11. HashMap can contain other HashMaps and is known as nested HashMaps
12. LinkedHashMap is efficient for insertion and deletion of elements
13. TreeMap is a red black tree-based implementation of HashMap
14. Properties class manages key-value pairs as persistent objects in a file
15. The load() and store() methods open and save Property lists. Property list can be queried using
getProperty() method
Key terms
Review questions
Multiple-choice Questions
1. What is the output?
System.out.print(ht.get(“2”));
ht.put(“1”, “11”);
ht.put(“2”, “21”);
System.out.print(ht.get(“1”));
a. 2 1 b. 2 11
c. 21 11 d. None of the above
Hashtable<Integer,String> ht =
new Hashtable<Integer,String>();
ht.put(1, “one”);
ht.put(2, “two”);
System.out.println(ht.get(1));
a. One b. Two
c. Null d. No output
Hashtable<Integer,String> ht =
new Hashtable<Integer,String>();
ht.put(1, “1”);
ht.put(2, “2”);
ht.put(new Integer(1), “11”);
System.out.println(ht.get(1));
a. 3 b. 4
c. 2 d. Undefined value
6. Find out the output:
a. 4 b. 3
c. 2 d. NullPointerException
7. What is the output?
a. 4 b. 3
c. 2 d. None of the above
8. What is the output?
a. [1, 2, 2, 3] b. [2, 1, 3, 2]
c. [1, 2, 3] d. [3, 2, 1]
a. [a, b, c] b. [b, a, c]
c. [b, a, c, b] d. [a, b, b, c]
import java.util.*;
public class Test9
{
public static void main(String[] args)
{
HashMap<Integer,Details> map =
new HashMap<Integer,Details>();
Details d1 = new Details(“Rex”, “Pune”);
Details d2 = new Details(“Helen”, “Bangalore”);
map.put(5001, d1);
map.put(5002, d2);
map.put(5001, d1);
System.out.println(map.keySet());
}
}
class Details
{
String name, addr;
import java.util.*;
public class Test9
{
public static void main(String[] args)
{
HashMap<Integer,Details> map =
new HashMap<Integer,Details>();
Details d1 = new Details(“Rex”, “Pune”);
map.put(5001, d1);
map.put(5002, d1);
map.put(5003, d1);
Iterator it = map.values().iterator();
while(it.hasNext())
System.out.println(it.next() + “ ”);
}
}
class Details
{
String name, addr;
public Details(String name1, String addr1)
{
name = name1;
addr = addr1;
}
public String toString()
{
return name + “ ” + addr;
}
}
import java.util.*;
public class Test9
{
public static void main(String[] args)
{
HashMap<StudentID,Details> map =
new HashMap<StudentID,Details>();
StudentID id1 = new StudentID(5001);
StudentID id2 = new StudentID(5001);
map.put(id1, new Details(“Rex”, “Pune”));
map.put(id2, new Details(“Rita”, “Pune”));
System.out.print(map.size());
Iterator it = map.keySet().iterator();
while(it.hasNext())
System.out.print(
“ ” + ((StudentID)it.next()).rollNo);
it = map.values().iterator();
while(it.hasNext())
System.out.print(
“ ” + ((Details)it.next()).name);
}
}
class Details
{
String name, addr;
public Details(String name1, String addr1)
{
name = name1;
addr = addr1;
}
}
class StudentID
{
int rollNo;
public StudentID(int n)
{
rollNo = n;
a. [2, 1, 3] b. [1, 2, 3]
c. [21, 11, 31] d. [11.21.31]
a. [2, 1, 3] b. [1, 2, 3]
c. [3, 1, 2] d. [3, 2, 1]
15. What is the output?
16. Which of the following TreeMap method returns the least key greater than or equal to the given
key?
a. ceilingKey() b. floorKey()
c. lowerKey() d. higherKey()
17. Which of the following TreeMap method returns the greatest key less than or equal to the given
key?
a. ceilingKey() b. floorKey()
c. lowerKey() d. higherKey()
18. Which of the following TreeMap method returns a view of the portion of the hashmap whose
keys are less than the given key?
a. headMap() b. tailMap()
c. floorMap() d. ceilingMap()
19. Which of the following TreeMap method returns a view of the portion of the hashmap whose
keys are greater than the given key?
a. headMap() b. tailMap()
c. floorMap() d. ceilingMap()
a. [1, 2, 3] b. [3, 2, 1]
c. [2, 1, 3] d. [one, two, three]
Answers
1. b 2. a 3. d 4. d 5. b 6. b 7. b 8. c 9. a 10. d
11. b 12. a 13. a 14. b 15. a 16. a 17. b 18. a 19. b 20. b
Short-answer Questions
1. Explain Hashtable and its important methods.
2. Explain the important methods of Map interface.
3. What are the three implementations of Map interface?
4. What is the difference between Hashtable and HashMap?
5. How can you create a HashMap inside another HashMap?
6. What is Multimap?
Exercises
9.1. [Spelling Checker] Create a hash table containing 10 spelling errors and their correct words as
keys and values. For example, key appel and its value apple. Then read a string from user with
spelling errors and correct them by consulting the hash table.
9.2. Modify spell checking exercise by replacing hash table with hash map.
9.3. [Dictionary Lookup] Create a hash table to store a simple dictionary containing 10 words and
their list of synonyms. Read a word from the user and display list of its synonyms if that word
exists. Note: you may need a vector or linked list to store synonyms.
9.4. Modify dictionary lookup exercise by replacing hash table with hash map.
9.5. [Language Translator] Create a property file containing 10 entries of English words and their
possible Tamil/Hindi translations. Populate Hashtable with the property file data. Read an
English string of words and print its Tamil/Hindi equivalent by hash table lookup.
9.6. Modify language translator exercise by replacing hash table with hash map.
9.7. [Login Manager] Create a hash table containing a list of usernames and their passwords. Read
a username and a password of a user from keyboard and display appropriate message whether
username and password matches with an entry in the hash table. If username does not exist,
get new username and password from user and add an entry to hash table.
9.8. [Spam Detector] Create a hash table containing spam words and their risk probability values.
Read a line of text as email message from user. Print appropriate message as below:
■■ If email has no spam words, print Spam Free
■■ Otherwise, calculate the average of probability values of all spam words that appear in the
email. Print a message Less Spam if the value is in between 0.01 to 0.3, Moderate spam if
the value is in between 0.31 to 0.7 and High spam, if more than 0.7
Objectives
■■ To introduce implementations of Set interface
■■ To check whether Sets allow duplicates
■■ To introduce the add and remove operations on Sets
■■ To introduce the union and difference operations on Sets
■■ To develop counting duplicates application
■■ To introduce LinkedHashSet's insertion ordering
■■ To introduce TreeSet's red black tree implementation
10.1 Introduction
Sets are the third type of Java containers we are going to deal with in this book. Having seen Lists
and Map types, we might have observed that lists and maps allow duplicate values. However there are
many situations where we need to hold only unique elements. This is where sets score better. In this
chapter, the readers will be introduced to Set interface and its three implementations. Analogous to
Map types, sets also have HashSet, LinkedHashSet and TreeSet types.
The set interface has some interesting methods. The add() method adds an object to the set if
it is not a duplicate and returns a boolean indicating whether the object is added or not. Similarly,
remove() deletes an element from the set. The equals() checks for an element in the set.
The standard set algebraic operations can be performed on to sets. Assume there are two sets s1
and s2.
There are basically three types of set implementations: HashSet, LinkedHashSet and TreeSet. The
readers will be introduced to these three types in sections 10.3, 10.5 and 10.6 in more detail.
10.3 HashSet
HashSet stores its elements in a Hashtable and is considered to be the best set implementation as its
lookup time is short. However, the elements are stored according to its hashcode randomly. HashSet
can be created as shown in Figure 10.1.
Suppose we have an array list with a set of integers. We want to remove all duplicates that exist in
the list. It can be easily done with the set as shown in Listing 10.1.
import java.util.*;
public class SetTest
{
public static void main(String[] args)
{
int[] numbers = {60,20,20,40,30,50,50,10};
ArrayList<Integer> list = new ArrayList<Integer>();
// add numbers to list
for(int i = 0; i < numbers.length; i++)
list.add(numbers[i]);
HashSet<Integer> set = new HashSet<Integer>(list);
System.out.println(set);
}
}
If a HashSet is type-unsafe, then it will store objects of any type as there is no restriction on
HashSet. In Listing 10.2, let us create an unsafe hashset to store any object or collection.
import java.util.*;
class Cat
{
int i = 777;
}
set.add(new Cat());
set.add(new HashMap());
set.add(new Vector());
System.out.println(set);
}
}
To appreciate the power of inheritance and polymorphism, it is a programming practice not to cre-
ate object of individual implementation. Rather, you need to upcast to the appropriate interfaces. For
example, let us create a hash set by upcasting to Set interface as shown in Figure 10.2.
The functionality of Set will remain the same even if we change HashSet by other set implementa-
tions; thereby we will get different results depending on set implementations.
import java.util.*;
class Counter
{
int i;
public Counter(int j) { i = j; }
public String toString() { return Integer.toString(i); }
}
Enter a line of text: i speak i walk too drink too you drink a
drink
{drink=2, too=1, i=1}
10.5 LinkedHashSet
LinkedHashSet is a linked list-backed hash set which preserves the order of insertion of elements.
Though it is slightly slower than hash set, it is very efficient for insertion and deletion of elements.
Like other implementations, it is also not thread-safe. LinkedHashSet can be created as shown in
Figure 10.3.
Now let us remove duplicate numbers in a given list with linked hash set as shown in Listing 10.4.
import java.util.*;
public class SetTest2
{
public static void main(String[] args)
{
int[] numbers = { 60,20,20,40,30,50,50,10};
ArrayList<Integer> list = new ArrayList
<Integer>();
// add numbers to list
for(int i = 0; i < numbers.length; i++)
list.add(numbers[i]);
LinkedHashSet<Integer> set = new
LinkedHashSet<Integer>(list);
System.out.println(set);
}
}
In section 10.4, the readers were introduced to counting duplicate elements in a line of text using
HashMap. In Listing 10.5, let us rewrite the same application using LinkedHashMap. LinkedHash-
Map enjoys the feature of constant time performance in insertion and deletion of elements.
10.6 TreeSet
TreeSet is backed by red black tree similar to tree map and tree list. So tree set maintains sorted order
of its elements. Like others, tree set is also not thread-safe. It is substantially slower than hash set.
Now let us rewrite removing duplicate application (Listing 10.4) with tree set as shown in Listing 10.6.
// SetTest3.java
import java.util.*;
public class SetTest3
{
public static void main(String[] args)
{
int[] numbers = {60,20,20,40,30,50,50,10};
ArrayList<Integer> list = new ArrayList<Integer>();
// add numbers to list
for(int i = 0; i < numbers.length; i++)
list.add(numbers[i]);
HashSet<Integer> set = new HashSet<Integer>(list);
System.out.println(set);
}
}
Listing 10.7 compares all three set implementations of a set. You can observe how each set main-
tains elements in their own order.
import java.util.*;
public class CompareSet
{
public void add(Set s)
{
s.add(“apple”);
s.add(“orange”);
s.add(“kiwi”);
s.addAll(s); // trying to add duplicates, cannot be added
s.add(“aeiou”);
System.out.println(s);
System.out.println(“s contains apple: ” +
s.contains(“apple”));
}
10.7 Summary
1. HashSet, LinkedHashSet and TreeSet are the three set implementations
2. Sets do not allow duplicate elements
3. Each set implementation differs from its functionality and performance
4. HashSet is faster that other implementations but slower for insertion
5. LinkedHashSet is based on linked list and faster for insertion and deletion of elements
6. TreeSet maintains natural ordering of elements, so elements will be automatically sorted
Key terms
Review questions
Multiple-choice Questions
1. What is the output?
a. [1,2,1] b. [1,2]
c. [1] d. IllegalArgumentException
a. [1,2,3,4] b. [1,2,1,4,3]
c. [1,2,4,3] d. [2,1,4,3]
set1.add(2);
HashSet set2 = new HashSet();
set2.add(2);
set2.add(3);
System.out.println(set1.containsAll(set2));
a. True b. False
c. Compilation error d. Runtime exception
a. [2] b. [1,3]
c. [1,3,2] d. [1,2,3]
a. [2] b. [1,3]
c. [1,3,2] d. [1,2,3]
set1.add(2);
LinkedHashSet set2 = new LinkedHashSet();
set2.add(“four”);
set1.addAll(set2);
System.out.println(set1);
a. 3 5 b. 1 3
c. 4 4 d. 5 7
a. 5 7 b. 1 3
c. 5 3 d. None of the above
a. 1 7 b. 34
c. 35 d. 47
a. [73,55,96,69,86] b. [96,86,73,69,55]
c. Compilation error d. Runtime exception
class Cat
{
int id;
public Cat(int id1) {id = id1;}
}
public class Test10
{
public static void main(String[] args)
{
TreeSet<Cat> set = new TreeSet<Cat>();
set.add(new Cat(1));
set.add(new Cat(1));
System.out.println(set.size());
}
}
a. 1 b. 2
c. Compilation error d. ClassCastException
a. [1,2] b. [1,2,2]
c. [null,1,2,2] d. NullPointerException
a. [b, d, a] b. [d, b, a]
c. [a, b, d] d. [a, b, b, d]
18. A duplicate element is added to a set. Then which of the following about add() is true?
Answers
1. b 2. a 3. a 4. a 5. b 6. b 7. a 8. b 9. c 10. a
11. c 12. a 13. a 14. c 15. d 16. d 17. b 18. d
Short-answer Questions
1. Explain all methods for set algebraic operations.
2. Explain HashSet with a suitable example.
Exercises
10.1. Create three sets namely business, sports and technology containing news articles business
news, sport news and technology news respectively. Populate each set with three to four news
articles.
■■ Now print all articles that discuss a company, InfoSys
■■ Print all articles related to cricket
■■ Print all articles related to cricket and stump camera
10.2. Create three sets representing studentID of various courses namely UCS1, UCS2 and UCS3.
Populate each of these sets with few student roll numbers. Now
■■ Print all students who are enrolled in all these courses
■■ Print all students who are enrolled in UCS2
■■ Print all students who are enrolled in UCS2 and UCS3
11
Sorting and Searching
Objectives
■■ To introduce sorting and searching support available in java.util package
■■ To introduce all static methods of Arrays and Collections classes for array and list processing
■■ To copy an array and fill array with an object using Arrays class
■■ To convert an array into a list using Arrays.asList() method
■■ To compare two array objects and iterate array elements
■■ To sort primitive arrays using Arrays.sort() method
■■ To sort primitive object arrays using Arrays.sort() method
■■ To sort user-defined object array using Comparable interface with Arrays
■■ To sort user-defined object array using Comparator interface with Arrays
■■ To explain why do we need both comparable and comparator types
■■ To search sorted arrays for a key using Arrays.binarySearch() method
■■ To introduce max(), min(), reverse(), swap() and shuffle() methods of Collections class
■■ To perform sorting using Collections.sort() class
■■ To perform binary search using Collections.binarySearch() class
■■ To sort user-defined object List using Comparable interface and Collections
■■ To sort user-defined object List using Comparator interface and Collections
11.1 Introduction
The java.util package provides two ways to sort the given collections automatically. You can either
use Arrays class or Collections class. The Arrays and Collections classes provide methods to per-
form sorting and also searching for a key. Also a lot of features for comparison, checking, filling
and copying are provided in these two classes. The sort() available in these two classes performs the
necessary sorting. The wrapper objects can be sorted automatically by its built-in natural ordering. On
the other hand, user-defined objects can be sorted using Comparable and Comparator interfaces.
This chapter introduces you to sorting and searching methods available in java.util package.
// FillCopy.java
import java.util.*;
// ArrayCompare.java
import java.util.*;
public class ArrayCompare
{
Arrays.fill(a1, 10);
Arrays.fill(a2, 10);
System.out.println(“\n array 1”);
for(int i : a1)
System.out.print(i + “ ”);
System.out.println(“\n array 2”);
for(int i : a2)
System.out.print(i + “ ”);
System.out.println(“\na1 and a2 are : ” + Arrays.
equals(a1,a2));
Arrays.fill(s1, “Hello”);
Arrays.fill(s2, “Hello”);
System.out.println(“\n array 1”);
for(String s : s1)
System.out.print(s + “ ”);
System.out.println(“\n array 2”);
for(String s : s2)
System.out.print(s + “ ”);
System.out.println(“\ns1 and s2 are : ” + Arrays.
equals(a1,a2));
}
}
array 1
10 10 10 10 10
array 2
10 10 10 10 10
a1 and a2 are : true
array 1
Hello Hello Hello Hello Hello
array 2
Hello Hello Hello Hello Hello
s1 and s2 are : true
// SortIntegers.java
import java.util.*;
public class SortIntegers
{
public static void main(String[] args)
{
if (args.length == 0)
{
System.out.println(“Enter numbers for
sorting...”);
return;
}
int[] numbers = new int[args.length];
for(int i = 0; i < args.length; i++)
numbers[i] = Integer.parseInt(args[i]);
System.out.println(“Before sorting”);
for(int i = 0; i < numbers.length; i++)
System.out.println(numbers[i]);
Arrays.sort(numbers);
System.out.println(“After sorting”);
for(int i = 0; i < numbers.length; i++)
System.out.println(numbers[i]);
}
}
Before sorting
9
2
3
6
1
After sorting
1
2
3
6
9
// SortStrings.java
import java.util.*;
Given names
rita
alex
peter
xavier
benita
After sorting
alex
benita
peter
rita
Xavier
// SortStudents.java
import java.util.*;
In this application, Student class implements Comparable and overrides compareTo() method. The
compareTo() method compares this object with the argument object (say o). It returns a
■■ positive integer if this object is greater than o
■■ zero, if this object equals to o
■■ negative integer, if this object is less than o
The public class just creates an array of student objects, initializes them with values, performs sort-
ing using sort() and displays students using for-each statement.
Now let us use StudComparator class to sort student objects. The overloaded Arrays.sort() will do
the trick as depicted in Listing 11.6.
// SortStudents2.java
import java.util.*;
class Student
{
int rollno;
String name;
double marks;
// ArraySearch.java
import java.util.*;
System.out.println(“\nGiven array”);
for(int mark : marks)
System.out.print(mark + “ ” );
System.out.println(“\nSorted array”);
for(int mark : marks)
System.out.print(mark + “ ” );
Given array
10 55 93 85 38 72
Sorted array
10 38 55 72 85 93
Location of 55 is : 2
Here binarySearch() takes the sorted array and key to be searched as arguments and searches for the
key. It returns the location of the key if it is available in the array. If not found, it will return the next
available location where this key can be inserted. If there are some duplicate elements in the array,
searching for a duplicate element may return any location not necessarily the first duplicate’s location.
// CollectionsTest.java
import java.util.*;
System.out.println(“Given array”);
System.out.println(list);
System.out.println(“max: ” + Collections.max(list));
System.out.println(“min: ” + Collections.min(list));
Collections.reverse(list);
System.out.println(“After reverse: ” + list);
Collections.shuffle(list);
System.out.println(“After shuffle: ” + list);
Collections.swap(list, 1,2);
Given array
[39, 43, 24, 45, 15, 16, 23, 37, 37, 37]
max: 45
min: 15
After reverse: [37, 37, 37, 23, 16, 15, 45, 24, 43, 39]
After shuffle: [37, 37, 23, 16, 43, 24, 37, 39, 15, 45]
After shuffle with user-defined randomness: [45, 16, 24, 43, 39,
15, 37, 37, 23, 37]
After swapping 1 and 2: [45, 24, 16, 43, 39, 15, 37, 37, 23, 37]
After sorting: [15, 16, 23, 24, 37, 37, 37, 39, 43, 45]
The element 23 exists at 2
// CSortStudents.java
import java.util.*;
{
int rollno;
String name;
double marks;
public Student(int rno, String s, double m)
{
rollno = rno;
name = s;
marks = m;
}
{
CSortStudents st = new CSortStudents();
st.init();
System.out.println(“Given students before sorting”);
st.show();
st.dosort();
System.out.println(“Students details after sorting”);
st.show();
}
}
// CSortStudents2.java
import java.util.*;
class Student
{
int rollno;
String name;
double marks;
{
CSortStudents2 st = new CSortStudents2();
st.init();
System.out.println(“Given students before sorting”);
st.show();
st.dosort();
System.out.println(“Students details after sorting”);
st.show();
}
}
11.13 Summary
1. The java.util.Arrays class provides a set of static methods for sorting, searching, comparison,
copying and filling operations
2. The Arrays.sort() performs sorting of primitive arrays and wrapper object arrays
3. The comparable interfaces define user-defined object that is comparable with another object
4. An object is comparable if it extends Comparable interface and overrides compareTo() method
5. The comparator interface compares two user-defined objects via its arguments without touching
its own object
6. An object can compare two objects if it extends Comparator interface and overrides compare()
method
7. Two arrays can be compared to check whether contents are same or not
8. Collections class supports a set of static methods such as Collections.max(), Collections.min(),
Collections.shuffle() and Collections.reverse() to find maximum, minimum and reverse of the
given List
9. The Collections.shuffle() shuffles the contents of the given list based on some position
10. The Collections.swap() interchanges two elements of a list
11. The sort() and binarySearch() methods performs the required sorting and searching operations
12. The binarySearch() needs presorted array or List in order to be able to perform binary search
13. The binarySearch() will return unpredictable results if the given input is not sorted
14. Similar to Arrays class, Collections class can sort list of primitive types, wrapper types and
user-defined type of objects
15. The Comparable and Comparator interfaces define the required sorting strategy to sort the
user-defined objects
Key terms
Review questions
Multiple-choice Questions
1. Given a list of int values, how will you sort these int values?
a. Arrays.sort() b. Collections.sort()
c. TreeSet class d. All of the above
2. Given a list of wrapper class values, how will you sort these wrapper class values?
a. Arrays.sort() b. Collections.sort()
c. TreeSet class d. All of the above
3. Given an array of objects, how will you sort this object array?
a. Arrays.sort()
b. Collections.sort()
c. TreeSet along with Comparator or Comparable
d. All of the above
int[] a = {1,2,3,4,5};
a = Arrays.copyOf(a, 4);
for(int i :a)
System.out.print(i);
a. 12345 b. 1234
c. 2345 d. 23451
7. What is the output?
int[] a = {1,2,3};
a = Arrays.copyOf(a, 4);
for(int i :a)
System.out.print(i);
a. 0123 b. 2310
c. 3120 d. 1230
8. How will you compare two arrays?
a. Arrays.equals() b. Arrays.equal()
c. System.equals() d. System.equal()
e. None of the above
9. What is the output?
String[] s1 = {“a”,“b”};
String[] s2 = {“a”,“b”};
System.out.println(Arrays.equals(s1, s2));
a. True b. False
c. Compilation error d. Runtime exception
10. What is the output?
System.out.println(Arrays.equals(c1, c2));
}
}
class Cat
{
int a;
public Cat(int i) { a = i;}
}
a. True b. False
c. Compilation error d. Runtime exception
11. What is the output?
a. True b. False
c. Compilation error d. Runtime exception
12. What is the output?
a. 215794 b. 124579
c. 291954 d. None of the above
a. adb b. dab
c. bad d. abd
int[] a = {1,2,3};
System.out.print(Arrays.binarySearch(a, 2));
String[] s = {“a”,“b”, “c”};
System.out.print(Arrays.binarySearch(s, “c”));
a. 12 b. 23
c. 31 d. 13
int[] a = {1,2,3};
System.out.print(Arrays.binarySearch(a, 4));
String[] s1 = {“a”,“d”, “b”};
System.out.print(Arrays.binarySearch(s1, “b”));
a. –3 –2 b. –4 –2
c. –5 –2 d. None of the above
int[] a = {1,3,2};
Arrays.sort(a);
System.out.print(Arrays.binarySearch(a, 3));
String[] s1 = {“a”,“d”, “b”};
Arrays.sort(s1);
System.out.print(Arrays.binarySearch(s1, “b”));
a. 21 b. 31
c. 32 d. 12
int[] a = {1,3,2,5,6};
Arrays.sort(a);
System.out.print(Arrays.binarySearch(a, 3, 1, 2));
a. [a, b, c, d] b. [b, c, a, d]
c. [b, c, d, a] d. [c, b, d, a]
19. What is the output?
a. [a, b, c, d] b. [b, c, a, d]
c. [d, c, b, a] d. [c, b, d, a]
20. Find out the output:
Integer[] a = {1,3,2,5};
List list = Arrays.asList(a);
Collections.sort(list, Collections.reverseOrder());
System.out.print(list);
a. [5, 3, 2, 1] b. [1, 2, 3, 5]
c. Compilation error d. Runtime exception
21. What is the output?
Collections.sort(list);
Collections.rotate(list,2);
System.out.print(list);
a. [a, b, c, d] b. [b, c, a, d]
c. [b, c, d, a] d. [c, d, a, b]
a. da b. ad
c. bc d. cb
a. True b. d
c. 3 d. None of the above
24. What is the output?
a. 2 b. 24
c. 4 d. 42
Answers
1. a, c 2. b 3. c 4. a 5. c 6. b 7. d 8. a 9. a 10. b
11. a 12. a 13. d 14. a 15. b 16. a 17. b 18. a 19. a, c 20. a
21. d 22. a 23. c 24. a
Short-answer Questions
1. Explain fill, arraycopy and equals methods of Arrays class with an example.
2. How will you sort primitive data types and string using Arrays class?
3. Explain the sorting of array of user-defined objects with Comparable.
4. Explain the sorting of array of user-defined objects with Comparator.
5. Explain binarySearch method with an example.
6. Discuss five static methods of Collections class.
7. What is the difference between Arrays.sort() and Collections.sort()?
8. Explain the sorting of list of user-defined objects with Comparable.
9. Explain the sorting of list of user-defined objects with Comparator.
Exercises
Objectives
■■ To explain process, multitasking, thread and multithreading
■■ To differentiate sequential execution and threaded execution
■■ To introduce thread creation ways: Thread and Runnable
■■ To explain variables inside local cache and master copy at main memory for threads
■■ To instantiate thread and start a thread
■■ To make thread to sleep
■■ To make thread to yield control to another threads
■■ To find the sum of an array using two threads
■■ To suspend calling thread using join
■■ To create daemon threads and explain its life
■■ To introduce thread priority and also its three constants
■■ To explain the importance of Runnable interface
■■ To synchronize threads for resource sharing using synchronized methods
■■ To introduce synchronized block for resource sharing
■■ To design ThreadedBank application
■■ To coordinate multiple threads using wait, notify and notifyall
■■ To define life cycle of a thread
■■ To introduce java.concurrent package
■■ To create ConcurrentHashMap and test it with multiple threads
■■ To introduce java.concurrent.atomic package
12.1 Introduction
Generally computer software performs several tasks simultaneously. For example, a word processor
responds to our mouse click and key press while performing page alignment of a document. Each
of these independent tasks is accomplished using a thread. Multitasking operating systems will run
more than one program (also called process) at a time with a single CPU.
A process is a program in execution and will have its own address space. Sometimes a thread is
called lightweight process and is a single sequential flow of control within a process. Therefore a
single process will have many concurrently executing threads. Multithreading is a compelling feature
of Java language. Every application you create will start with one thread called main thread and Java
allows an application to create other threads.
Multithreading is highly essential when you develop an application that has several user interface (UI)
components such as buttons, combo boxes and text fields. Apart from performing your main task, your
application should listen to the events happening on these UI components. These events include users
clicking buttons, selecting items from combo boxes, pressing keys and others. Each of these activities or
events will be handled by a separate thread, and all these threads will concurrently execute indefinitely.
Multithreading has many more applications besides handling UI components. Resource sharing
is another important application of multithreading. Suppose when there is a common resource that
needs to be concurrently accessed and updated by many threads, then all threads must cooperatively
perform tasks on this resource.
Concurrent programming requires a different understanding of the flow of execution. In sequen-
tial execution, a control flows from the start to the end of a process. Whereas in concurrent execution,
the same block of code is executed by many threads simultaneously; thereby you get several outputs
at the same time. When your application is multithreaded, it will make your application running slow
because of several threads executing simultaneously.
Developing a multithreaded application is tricky and needs alternative thinking because of the
complexity of threading. This chapter aims to explain all the necessary basics of concurrency so that
the readers will be able to develop reasonably good multithread applications.
Thread 1
Thread 2
Thread
Single-threaded Multithreaded
Program Program
Therefore, each thread will execute run() method independently giving many outputs. Figure 12.2
explains this Thread behaviour.
With this basic understanding of Thread class and how to override run() method, we will now
develop an application that will count numbers. As a multithreaded program, we allow several threads
to count numbers independently and simultaneously. Remember, the counting behaviour should be
inserted inside the overridden run() method. Listing 12.1 depicts this multithreaded counter.
// CounterThread.java
Inside Thread4 : 0
Inside Thread3 : 0
Inside Thread0 : 0
Inside Thread2 : 0
Inside Thread1 : 0
Inside Thread2 : 1
Inside Thread0 : 1
Inside Thread3 : 1
Inside Thread4 : 1
Inside Thread3 : 2
Inside Thread0 : 2
Inside Thread2 : 2
Inside Thread2 : 3
Inside Thread2 : 4
Inside Thread2 : 5
Inside Thread1 : 1
Inside Thread1 : 2
Inside Thread1 : 3
Inside Thread1 : 4
Inside Thread1 : 5
Inside Thread0 : 3
Inside Thread0 : 4
Inside Thread0 : 5
Inside Thread3 : 3
Inside Thread3 : 4
Inside Thread3 : 5
Inside Thread4 : 2
Inside Thread4 : 3
Inside Thread4 : 4
Inside Thread4 : 5
Here, Counter is created as a Thread object and thread behaviour is incorporated inside run()
method. The thread has to be started and start() method inside constructor does this task. Unless start()
method is called, the thread will never be started. The start() should be defined as a last statement
inside constructor as control will immediately branch to run() without executing further statements.
Each thread will execute its copy of run() separately and simultaneously, causing all threads to
print the value of its variable i. Note that even though for loop iterates fixed number of times (say up
to max), displaying value of i of one thread will be interrupted by another thread. Therefore, no for
loop will finish displaying its i values in one go.
Inside main(), we create five Counter thread objects with thread number and maximum value for
counting. The main() simply instantiates Counter objects and returns to command prompt. In other
words, main() is part of main thread so it dies after the instantiation. One interesting behaviour of
threads is that every time you run the program you will get different sequence of outputs. Because we
cannot predict which thread will display which value of the variable i. Different JDK implementations
will follow different thread scheduling policies.
// CounterThread2.java
Inside Thread2 : 0
Inside Thread0 : 0
Inside Thread2 : 1
Inside Thread0 : 1
Inside Thread0 : 2
Inside Thread0 : 3
Inside Thread0 : 4
Inside Thread0 : 5
Inside Thread2 : 2
Inside Thread2 : 3
Inside Thread2 : 4
Inside Thread2 : 5
Inside Thread1 : 0
Inside Thread4 : 0
Inside Thread3 : 0
Inside Thread4 : 1
Inside Thread1 : 1
Inside Thread4 : 2
Inside Thread3 : 1
Inside Thread4 : 3
Inside Thread1 : 2
Inside Thread4 : 4
Inside Thread3 : 2
Inside Thread3 : 3
Inside Thread3 : 4
Inside Thread3 : 5
Inside Thread4 : 5
Inside Thread1 : 3
Inside Thread1 : 4
Inside Thread1 : 5
The sleep() makes the thread to sleep for the specified duration (here 100 ms) and must be kept
inside a try-catch block. The sleep() throws InterruptedException when another thread interrupts this
current thread which it is sleeping. You are highly advised to play with this program by varying
sleep() time to analyze different outputs by the threads.
// CounterThread3.java
{
public static void main(String[] args)
{
for(int i = 0; i < 5; i++)
new Counter(i, 6); // count upto 6
}
}
Inside Thread0 : 0
Inside Thread0 : 1
Inside Thread0 : 2
Inside Thread2 : 0
Inside Thread1 : 0
Inside Thread2 : 1
Inside Thread2 : 2
Inside Thread0 : 3
Inside Thread3 : 0
Inside Thread4 : 0
Inside Thread3 : 1
Inside Thread0 : 4
Inside Thread0 : 5
Inside Thread2 : 3
Inside Thread2 : 4
Inside Thread1 : 1
Inside Thread2 : 5
Inside Thread3 : 2
Inside Thread4 : 1
Inside Thread3 : 3
Inside Thread1 : 2
Inside Thread1 : 3
Inside Thread1 : 4
Inside Thread1 : 5
Inside Thread3 : 4
Inside Thread3 : 5
Inside Thread4 : 2
Inside Thread4 : 3
Inside Thread4 : 4
Inside Thread4 : 5
// MultiThreadedAdder.java
import java.util.*;
public Adder(int[] a)
{
arr = a;
start();
}
try
{
sleep(10);
}
catch(InterruptedException e) { }
System.out.println(“Original array”);
for(int i : a)
System.out.print(i + “ ”);
// collect sums
int sum = t[0].sum + t[1].sum;
// show
System.out.println(“Final Sum: ” + sum);
}
Original array
3 0 0 1 3 3 8 3 4 8 8 5 8 3 7 6 4 0 8 0 2 6 1 0 3 4 8 8 6 6
8 1 1 6 8 5 0 4 2 6 3 5 6 6 0 8 6 7 3 9 3 3 6 9 1 1 7 5 0 8
3 8 9 7 3 2 3 1 8 8 6 6 0 4 3 4 5 3 9 2 3 1 5 0 6 2 7 5 7 4
1 9 6 1 6 4 5 5 6 6
Thread sum = 226
Thread sum = 220
Final Sum: 446
The Adder class is simply a thread that will receive an array through its arguments, and it calculates
the sum inside the run(). The public class is bit long and does a lot of things for us. It generates an array
of random integers. The constant MAX defines the maximum size for the array, currently 100 elements.
Of course you can set any value for MAX, your application will run, no problem! The System.array-
copy() does the trick of dividing the array into two subarrays. The rest of the code is self-explanatory.
The main thread just instantiates two threads and hands over the two subarrays to them. It waits until
both threads finish their execution and collects the individual sums and adds them to get the final sum.
// JoiningThread.java
public JoiningThread()
{
start();
}
System.out.println(“World”);
}catch(InterruptedException e) { }
}
Hello
Hello
Hello
Hello
Hello
Hello
Hello
Hello
Hello
Hello
World
Now let us revisit our earlier multithreaded adder application (section 12.5) which calculates the
sum of integers in an array. The main thread was made to wait for 100 ms so that the two adder threads
will finish its calculation. After this waiting period, the main thread collects the individual sums and
prints the final sum. The main drawback with this application is the waiting time. As a developer, we
need to make a wild guess. The waiting time we guessed may be too long or too short we never know.
So the better solution will be to suspend the main thread’s execution until both adder threads complete
their execution. Listing 12.6 rewrites our multithreaded adder with join() method.
// MultiThreadedAdder2.java
import java.util.*;
public Adder(int[] a)
{
arr = a;
start();
}
Original array
2 2 3 8 3 6 4 2 6 6 0 4 1 1 7 5 2 8 0 2 8 9 6 4 1 1 8 8 9 7
2 6 6 3 1 0 0 8 2 9 6 0 6 3 6 4 5 3 4 1 6 1 4 8 6 3 0 2 1 7
2 1 3 9 8 7 9 2 8 3 7 2 1 4 0 5 3 6 2 0 9 0 3 0 5 8 0 3 7 7
6 8 3 3 5 0 8 6 7 5
Thread sum = 208
Thread sum = 213
Final Sum: 421
The Thread.main() waits indefinitely until both threads t[0] and t[1] complete their execution by
calling join() methods of t[0] and t[1].
should appear before start() method, failing which the thread will be assumed normal thread and
control branches to run(). In Listing 12.7, the readers will know how daemon threads are created in
order to say Good Morning.
// GoodDaemon.java
public class GoodDaemon extends Thread
{
int number;
public GoodDaemon(int i)
{
number = i;
setDaemon(true);
start();
}
Thread.main() terminates
Once setDaemon() is called, thread will be identified as daemon thread. In run(), the daemon thread
goes for a long sleep and then it will have to display a string good morning indefinitely. The main()
simply creates 10 daemon threads and terminates immediately; by the time all daemon threads are still
sleeping. Since main() thread is terminated before all daemon threads return from their sleep, all dae-
mon threads eventually terminate along with main() thread without displaying the string good morning.
So how to make all daemons say good morning. You will have to do two things. First reduce
waiting time for all daemons. Second allow Thread.main() to sleep for a while so that all daemons
complete their greetings as shown in Listing 12.8.
// GoodDaemon2.java
public class GoodDaemon2 extends Thread
{
int number;
public GoodDaemon2(int i)
{
number = i;
setDaemon(true);
start();
}
// FloorThread.java
setPriority(priority);
start(); // start the thread
}
In this example, the Flooring thread performs an expensive arithmetic operation by adding PI
value, E value and floor value and a division. This expression is iteratively added many times. This
will sufficiently allow a thread to spend longer time in calculation. Suppose if one thread begins its
calculation with CPU, other high-priority thread will grab CPU time, thereby the first thread will wait.
Here, thread 1 enjoys a highest priority of 10 and priority decreases with other threads. Also note that
variable i is declared as volatile.
When multiple threads use the same variable, each thread will receive its copy of the local cache
for this variable. So, when a thread updates the value of this variable, it is actually updating in the
local cache not in the main memory. The other thread which is using the same variable doesn’t know
anything about the values changed by another thread. By declaring this variable as volatile, variable
will not be stored in local cache. Whenever a thread updates the values, it is updated directly to the
main memory. So that other threads will use the updated value from main memory.
Thus volatile keyword is used with a variable declaration to indicate JVM that a thread accessing
the variable must always merge its own private copy of the variable with the master copy in the main
memory. Accessing a volatile variable synchronizes all cached copies of the variables in the main
memory. Volatile should be applied to instance data members and not static data members.
The Runnable interface simply provides run() method. Rather it does not provide any thread
behaviour. So you will have to create a Thread inside your class to provide thread behaviour and
call start() method of the thread to perform usual thread initialization and to call run() as shown in
Example 12.1.
public Countable()
{
t.start();
}
With this basic understanding of Runnable interface, we all now can rewrite a counter thread using
Runnable interface. Listing 12.10 illustrates this countable thread.
// CountableThread.java
Inside Thread1 : 0
Inside Thread0 : 0
Inside Thread2 : 0
Inside Thread4 : 0
Inside Thread3 : 0
Inside Thread4 : 1
Inside Thread2 : 1
Inside Thread0 : 1
Inside Thread1 : 1
Inside Thread0 : 2
Inside Thread2 : 2
Inside Thread4 : 2
Inside Thread3 : 1
Inside Thread4 : 3
Inside Thread2 : 3
Inside Thread0 : 3
Inside Thread1 : 2
Inside Thread0 : 4
Inside Thread2 : 4
Inside Thread2 : 5
Inside Thread4 : 4
Inside Thread4 : 5
Inside Thread3 : 2
Inside Thread3 : 3
Inside Thread3 : 4
Inside Thread3 : 5
Inside Thread0 : 5
Inside Thread1 : 3
Inside Thread1 : 4
Inside Thread1 : 5
Inside Countable class, you simply implement Runnable interface, instantiate a thread within this
current object, start the thread inside constructor and override run() method. Once start() is called
inside constructor, then flow of control begins executing run() method. With run(), the thread simply
sleeps for a while (using t.sleep() instead of sleep()), performs counting, displays thread number and
count value and terminates itself. The main() initializes five threads and terminates.
r eading and another for writing data to this record. These are the examples of resource sharing prob-
lem. Communication among threads will result into two types of errors as shown in the following
scenarios:
■■ Two threads are trying to update common resource via different methods
■■ Two sequential statements about a common resource are executed by two different threads
In order to understand scenario-1, let us start with an example as shown in Example 12.2.
Example 12.2. Two Threads Updating Common Resource Via Different Method Calls
Step1: count = 0;
Step2: incrementCount() { ++count; }
Step3: decrementCount() { --count; }
Step4: print count
Suppose a single thread executes the statements as shown in Figure 12.4. It will not be any problem
and the thread will print its count value 0 correctly.
Assume now that there are two threads t1 and t2. Thread t1 executes step2 and t2 executes step3
almost simultaneously (as we have only one CPU) with its own local copy of count (i.e. count = 0 for
both t1 and t2). The t1 will have its count value incremented to 1 and t2 will have its count value decre-
mented to –1. Both t1 and t2 will store their values to count; thereby one thread’s value will be overwrit-
ten by another thread. It is generally unpredictable which thread will overwrite the value of which thread.
There might be two overwriting cases for both threads as shown in Figure 12.5 Case 1 and Case 2.
Let us explain scenario-2 with another example as depicted in Example 12.3.
Step1: count = 0
Step2: count = count + 1
Step3: print count
If a single thread executes these steps, it starts with step1, executes it and continues with step2 and
step3 printing count value 1 correctly. In contrast, assume count is shared by two threads t1 and t2.
The t1 executes step2 and t2 executes step3 simultaneously. The count value printed by t2 could be 0
instead of 1. The count value incremented by t1 may not be visible to t2; unless t1 completes updat-
ing count with a new value before t2 accesses it. Therefore operations done by t1 and t2 should be
properly communicated among themselves.
In order to solve resource sharing problem, the requests to access a common resource should be
serialized. Assume there is something like a lock available. Whenever a thread wants to access this
resource, it gets a lock, locks the resource and uses it. Once it is finished, it releases the lock so that
other threads that are waiting for will access it. Of course, there will be a race among all blocked
threads to get hold of the resource just released. In this case, priority of threads will play a vital role
and high-priority threads will enjoy the resource.
// BankAccount.java
class BankAccount
{
private int balance = 0;
The credit(), debit() and get() methods are declared as synchronized methods. By declaring synchro-
nized, access to balance by these methods is streamlined. Synchronized method streamlines requests
for common resources by several threads. When one thread currently executes a synchronized method,
all other threads will be blocked until the first one finishes. The updates to resource done by the first
thread will be made visible to all other threads. All subsequent invocations by other threads will use
the updated value only. This way synchronized method handles both errors as discussed earlier.
Having created BankAccount class, now it is easy for us to create Credit and Debit threads to per-
form deposits and withdrawal of money from account as depicted in Listing 12.11.
// ThreadedBank.java
import java.util.*;
class BankAccount
{
private int balance = 0;
}
public synchronized int get()
{
return balance;
}
}
acc.credit(r.nextInt(20));
System.out.println(“Balance after Thread ” + number +
“ credit: ” + acc.get());
}
}
}
}
public void run()
{
while (true)
{
try {
sleep(1000);
}catch(InterruptedException e) { }
acc.debit(r.nextInt(10));
System.out.println(“Balance after Thread ” + number +
“ debit: ” + acc.get());
}
}
}
public class ThreadedBank
{
public static void main(String[] args)
{
BankAccount b = new BankAccount();
for(int i = 0; i < 5; i++)
{
new CreditThread(i, b); // thread number i
new DebitThread(i, b);
}
}
}
The CreateThread simply deposits money (as a random integer) to bank account after sleeping for
a while and shows the current balance after this deposit. Similarly DebitThread after sleeping for a
while withdraws money from the same account and displays the current balance of this account. Both
threads will loop indefinitely until you break the execution. The main() thread just creates credit and
debit threads and terminates.
class BankAccount
{
private int balance = 0;
synchronized(this)
{
balance += amt;
}
}
}
In this example, credit() method should synchronize the changes to balance only. The if statement that
checks whether amount to be deposited is negative is very specific to this thread only and need not be
part other threads. So if statement is safely excluded from synchronization. In the same way, debit()
method can also be rewritten using synchronized block as illustrated in Example 12.6.
class BankAccount
{
public void debit(int amt)
{
if (amt < 0)
{
System.out.println( “Negative amount cannot be
withdrawn too”);
return;
}
synchronized(this)
{
balance -= amt;
}
}
}
Very similar to previous example, if the amount to be withdrawn is negative, then it cannot be with-
drawn too. So this checking is not part of common resource and can be ignored and need not be
included in the synchronized block.
// CarDealer.java
{
this.c = c;
this.e = e;
start();
}
try {
sleep(100);
} catch(InterruptedException e) { }
}
else
System.exit(0);
}
}
}
In this example, engineer thread object currently waits for a call from marketing manager thread
object. This is accomplished by a wait() method inside a synchronized block of Engineer thread. Once
it is awaken by marketing manager thread, it takes the customer for a test drive and goes back to sleep.
The marketing manager object simply assigns customer to an engineer object for test drive. It will
also keep track of total number of customers currently served. The car dealer instructs the marketing
manager object through max the maximum number of customers it can schedule for test drive. Once
customer arrives, marketing manager thread notifies engineer thread so that engineer object can per-
form test drive. Marketing manager thread calls exit() to terminate the application once it reaches the
maximum customers to be taken for test drive.
start()
New Runnable
run()
Running
wait()
yield()
sleep()
Dead Blocked
// ConcurrentHMTest.java
import java.io.*;
import java.util.*;
import java.util.concurrent.*;
import java.math.*;
Here all 5 threads concurrently insert key-value pairs to concurrent hash map. In the getString(),
a BigInteger is created with 28 – 1 bits and a Random object. This number is then converted into a
string with radix 32. This random string is used as keys and values by threads. The run() simply inserts
random strings into the concurrent hash map and prints the contents of the updated map. The main()
instantiates thread objects and terminates.
// AtomicCounter.java
import java.util.concurrent.atomic.*;
import java.util.concurrent.*;
class Counter
{
AtomicInteger c = new AtomicInteger(0);
The getAndIncrement() gets and increments the resource while get() returns the contents of the
resource variable. The AtomicCounter is a thread object and we create threads that will call methods
from Counter object in order to increment and retrieve the contents of the resource variable. The
Thread.main() thread will wait for all threads to finish their execution so that it will finally show the
contents of the resource variable.
import java.util.concurrent.atomic.*;
import java.util.concurrent.*;
import java.util.*;
class Strings
{
AtomicIntegerArray array;
Random r = new Random();
catch(InterruptedException e) { }
StringBuffer sb = new StringBuffer();
for( int i = 0; i < 5; i++)
sb.append((char)str.get());
The init() of Strings class instantiates an instance of AtomicIntegerArray that keeps ASCII values
of uppercase and lowercase alphabets. The get() returns any one of the ASCII values from the lock-
free thread-safe array. The run() simply creates a string of five characters using string buffer and
displays the generated string. The main() calls init() and initializes threads (here 1000 threads) that
will generate and display strings.
// BankAccountLock.java
import java.util.concurrent.locks.*;
{
mylock.unlock();
}
}
First we obtain a lock as an instance of ReentrantLock. With this lock object, we can lock all
resource variables by calling lock(). Try block will contain all resources that are to be locked. Once
finished its execution, unlock() is called to release the lock inside finally block.
Now our revised ThreadedBank will use the above BankAccountLock object so that its credit and
debit threads will perform transactions as depicted in Listing 12.17.
// ThreadedBankLock.java
import java.util.concurrent.locks.*;
import java.util.*;
acc.credit(r.nextInt(20));
System.out.println(“Balance after Thread ” + number +
“ credit: ” + acc.get());
}
}
}
acc.debit(r.nextInt(10));
System.out.println(“Balance after Thread ” + number
+ “ debit: ” + acc.get());
}
}
}
public class ThreadedBankLock
{
public static void main(String[] args)
{
BankAccountLock b = new BankAccountLock();
for(int i = 0; i < 5; i++)
{
new CreditThread(i, b);
new DebitThread(i, b);
}
}
}
12.21 Summary
1. A process is a program in execution
2. Thread is a lightweight process and it will have its own address space
3. Thread is a single sequential flow of control within a process
4. A thread is created with Thread class or Runnable interface
5. The body of the run() method will be executed concurrently by many threads
6. A thread must be started explicitly
7. The sleep() makes thread to release CPU to other threads
8. The yield() voluntarily relinquishes CPU to other threads
9. Java program starts its execution with main Thread
10. A thread will go on sleeping by calling join() method of another thread
11. Daemon threads are service threads for other threads running in the background
12. Daemon threads will terminate when all non-daemon threads terminate
Key terms
Review questions
Multiple-choice Questions
1. For the following class, choose the correct thread class:
a. 1 b. 2
c. 12 d. 21
e. Unpredictable
3. What is the output if you create an object as new A().run(“3”) ?
a. 12 b. 123
c. 13 d. 23
e. None of the above
a. 2 b. 22
c. 222 d. None of the above
a. hello
b. hello hello
c. hello followed by IllegalThreadStateException
d. hello hello followed by IllegalThreadStateException
e. None of the above
a. hello
b. hello hello
c. hello hello indefinitely
d. None of the above
11. Which of the following about sleep() and yield() are true?
a. sleep() forces the current thread to go for sleep for specified period
b. yield() voluntarily relinquishes CPU to other threads
c. sleep() and yield() are static methods in Thread class
d. All of the above
12. Assume two threads t1 and t2. If t1 calls join() method of t2 as t2.join(), then which of the fol-
lowing is true?
a. t1 goes to indefinite wait until t2 finishes
b. t2 goes to indefinite wait until t1 finishes
c. t1 goes to indefinite wait until t2 calls notify()
d. t2 goes to indefinite wait until t1 calls notify()
14. How will you make a thread to merge its own private copy of the variable with the master copy
in the main memory?
a. Create this variable as synchronized b. Create this variable as volatile
c. Create this variable with high priority d. None of the above
class Account
{
private int balance = 10000;
public void debit(int amt)
{
if (amt < 0)
return;
synchronized(this)
{
balance -= amt;
}
}
}
a. Two threads cannot access amt b. Two threads cannot access balance
c. Two threads cannot access amt as d. None of the above
well as balance
17. Which of the statements are true considering class Account?
class Account
{
private int balance = 10000;
public synchronized void debit(int amt)
{
if (amt < 0)
return;
synchronized(this)
{
balance -= amt;
}
}
}
a. Two threads cannot access amt b. Two threads cannot access balance
c. Two threads cannot access d. None of the above
amt as well as balance
18. Which of the following is true about sleep() and wait()?
a. sleep() does not release the lock while the thread is sleeping
b. wait() does not release the lock while the thread is waiting
c. sleep() releases the lock while the thread is sleeping
d. wait() releases the lock while the thread is waiting
19. Which of the following are true?
a. The wait(), notify() and notifyAll() belong to java.lang.Thread class
b. The notify() can awake any specific thread of its choice from all waiting threads
c. The notifyAll() awakes all wait() and yield() threads from sleeping
d. None of the above
20. What is the output when a thread of type A is started?
a. 1 b. 12
c. Indefinite wait d. None of the above
21. Which of the following is true with respect to Account?
class Account
{
synchronized int balance = 10000;
public void debit(int amt)
{
balance -= amt;
}
}
a. Two threads can access balance b. Only one thread can access balance
c. Any number of threads can access balance d. Synchronized cannot be applied to balance
22. Assume a class A has two synchronized methods m1() and m2(). Then which of the following
is true?
a. The m1() and m2() cannot be called by two different threads
b. The m1() and m2() can be called by two different threads
c. There cannot be two synchronized methods in a class
d. None of the above
23. Assume a class A has two synchronized methods m1() and m2() and one non-synchronized
method m3(). Then which of the following is true?
a. The m1() and m2() cannot be called by two different threads
b. The m1() and m2() can be called by two different threads
c. There cannot be two synchronized methods in a class
d. The m3() can be called by many threads
}
}
a. 1
b. 2
c. 12
d. No output
a. a b. aa
c. a followed by a after 1 sec d. a followed by a after 1 min
Answers
1. a 2. a 3. c 4. b 5. d 6. c 7. c 8. c 9. b 10. a
11. d 12. a 13. d 14. b 15. a, b 16. b 17. c 18. a, d 19. d 20. d
21. d 22. a 23. a 24. c 25. c 26. d 27. c 28. d
Short-answer Questions
1. Explain process, multitasking, thread and multithreading.
2. What are the ways of creating threads?
Exercises
12.1 For CounterThread.java, instantiate 10 threads and observe the output. Then instantiate 100
threads, 1000 threads and 10000 threads and observe the output.
12.2 For CounterThread2.java, instantiate 10 threads and observe the output. Then instantiate 100
threads, 1000 threads and 10000 threads and observe the output. Now compare this output
with the output of the previous exercise.
12.3 For CounterThread.java, vary sleep time from 100ms to 1000ms and instantiate 100 threads
and observe the output. Now again increase sleep time to 10000ms and 10000 threads and
observe the output. What is your perception?
12.4 Create a 10-D array with random digits (0-9) populated by 10 threads simultaneously. Scale
the dimension and number of threads to 100 and check your output.
12.5 Design MultiThreadedNDAdder application that will sum all element values of an N-D array.
Scale N from 3 onwards.
12.6 Modify ThreadedBank.java application by increasing the number of CreditThread and Deb-
itThread from 5 to 50 and observe the credit and debit operations. Now increase threads to
1000 and then to 10000 and observe the credit and debit operations.
13
Processing Byte
and Object Streams
Objectives
■■ To create File object to obtain the details of files and directories such as length, date created,
date modified, its name and many others
■■ To filter file names in a directory using FileNameFilter
■■ To filter absolute path names using FileFilter
■■ To introduce input stream types
■■ To read file contents using FileInputStream
■■ To read strings into byte array using ByteArrayInputStream
■■ To write bytes to file using FileOutputStream
■■ To copy files as bytes
■■ To process primitive data type values using DataInputStream and DataOutputStream
■■ To generate students mark list using Data IO
■■ To create Serializable objects
■■ To write Serializable objects to files using ObjectOuputStream
■■ To read Serializable objects from files using ObjectInputStream
■■ To write students marks as Serializable objects to file
■■ To read students Serializable objects and generate mark list
■■ To prevent a variable from serialization by declaring it as transient
13.1 Introduction
So far all of your data you created would have been lost and would not be persistently available once
you close the application. Files allow you to store your data in a persistent way in disk. Java file process-
ing is centred on streams. Streams can represent different sources and destinations such as disk files,
source programs and devices. For instance, streams are interfaces between two entities; input source
and output destination where source could be a program and destination could be a disk and vice versa.
Streams support several types of data such as bytes, characters, primitive data types and objects.
Streams help us to communicate with files by many ways such as sequentially, randomly, using buff-
ering, byte by byte, character by character, word by word, line by line and many others.
There are two stream types: one for reading from source (input streams) and the other for writing
to destination (output streams). Our program will use input streams to read data from data source
and output streams to write data to destination. The earlier Java 1.0 supported byte streams while Java
1.1 added character streams and the recent Java 1.4 included nio (new IO) for better performance.
Java IO stream classes are archived in java.io and java.nio packages that you will import inside
your application. There are many classes, each having its own purpose that you should clearly iden-
tify. In this chapter, the readers will be introduced to the variety of byte and object stream classes
with which you will be able to develop applications, apart from File class. The readers will explore all
character-oriented stream classes, random access files and NIO features in Chapter 14.
// File1.java
import java.io.*;
// rename
System.out.println(“Renaming data.txt as datanew.txt”);
File fnew = new File(“datanew.txt”);
f1.renameTo(fnew);
// create dir
System.out.println(“creating new directory: test”);
File f2 = new File(“test2”);
f2.mkdir();
getName: io
getParent: e:\rajkumar\javacourse
getPath: e:\rajkumar\javacourse\io
isDirectory: true
isFile: false
length: 65536
canRead: true
canWrite: true
lastModified:1350711948468
// FilterFiles.java
import java.io.*;
E:\Rajkumar\javacourse\io>java FilterFiles.txt
data.txt
data1.txt
datanew.txt
dummy.txt
dummy2.txt
dummy2copy.txt
dummynew.txt
fish.txt
news.txt
news2.txt
student.txt
The FilterName implements FilenameFilter interface and overrides accept(). The accept() returns
true if a file ends with the required extension. In main(), you create a file object and FilenameFilter for
the required extension. The list() of File object receives FilterName object as argument and collects all
file names based on whether a file ends with the required extension. Finally the string array containing
all file names that satisfied the condition will be displayed.
// FilterDirs.java
import java.io.*;
E:\Rajkumar\javacourse\io>java FilterDirs .
E:\Rajkumar\javacourse\io\test
E:\Rajkumar\javacourse\io\test2
E:\Rajkumar\javacourse\io
E:\Rajkumar\javacourse\JavaSample
E:\Rajkumar\javacourse\jblearning_javabook
E:\Rajkumar\javacourse\LabSourcecode
E:\Rajkumar\javacourse\OOP
E:\Rajkumar\javacourse\out
E:\Rajkumar\javacourse\Princeton
E:\Rajkumar\javacourse\src
E:\Rajkumar\javacourse\util
Here listing all directory names is very similar to listing all file names satisfying the condition on
the file name. The listFiles() lists all File objects that are directory names in a given directory by tak-
ing filter as argument. The condition is defined in accept() method that checks whether the file object
is a directory or not with isDirectory() method.
The FileInputStream is an interesting class that can be used to read the contents of a file. The read()
will read a byte from the stream. Listing 13.4 explains the process of reading a file.
// FileRead1.java
import java.io.*;
The first step in file processing is to open a file for reading. The file to be read has to be given as
argument to the constructor as a string or File object. If the specified file is not available in the current
directory, then JVM will throw FileNotFoundException. So this exception should be catched. If file
is opened successfully, then read() reads a byte from the stream and displays it as a character. The
stream keeps reading data until there is no more byte to read with available() method. Finally, the
opened file should be closed with close() without fail. Remember read() returns –1 when it reaches
end of file.
// FileRead2.java
import java.io.*;
public class FileRead2
{
public static void main(String[] args) throws IOException
{
File file = new File(args[0]);
FileInputStream in = new FileInputStream(file);
// create buffer to hold file contents
byte[] b = new byte[(int)file.length()];
// read into buffer
in.read(b);
System.out.println(“Using byte array: ” + new String(b));
in.close(); // close stream without fail
}
}
Here, single read(), reads an entire content of the file, which is displayed as a single string.
// BAIStest.java
import java.io.*;
while(s.available() > 0)
System.out.print((char)s.read());
s.close(); // close stream without fail
}
}
Here getBytes() converts the given string into byte array. The byte array input stream is set to the
byte array b and read() easily reads a byte one at a time and it is displayed.
// FileWrite1.java
import java.io.*;
E:\Rajkumar\javacourse\io>type dummy.txt
Rajkumar, how are youHello Java World
The flush() transfers the contents of the buffer to the output file immediately. Also note that how
you can specify file mode either for append or overwrite its contents.
// BAOStest.java
import java.io.*;
E:\Rajkumar\javacourse\io>type dummy2.txt
Java is one of the interesting languages
// FileCopy.java
import java.io.*;
E:\Rajkumar\javacourse\io>java FileCopy
E:\Rajkumar\javacourse\io>type dummy2.txt
Java is one of the interesting languages
E:\Rajkumar\javacourse\io>type dummy2copy.txt
Java is one of the interesting languages
Here, file input stream reads one byte at a time and writes to file output stream until the end of file is
reached. However, you can also read the entire file contents into a byte array so that you can write the
entire byte array in a single step. Listing 13.10 will copy the source file to target file in a single step.
// FileCopyByte.java
import java.io.*;
in.close();
out.close(); // close stream without fail
}
}
E:\Rajkumar\javacourse\io>javac FileCopyByte.java
E:\Rajkumar\javacourse\io>java FileCopyByte dummy.txt dummy3.txt
E:\Rajkumar\javacourse\io>type dummy.txt
Rajkumar, how are youHello Java World
E:\Rajkumar\javacourse\io>type dummy3.txt
%
One important point you must understand is the way the program copies byte array. That is write()
takes read() as argument directly.
// DataIOstream.java
import java.io.*;
dos.writeInt(5001);
dos.writeBytes(“Rex\n”);
dos.writeUTF(“India”);
dos.writeDouble(75.50);
dos.flush();
dos.close();
5001
Rex
India
75.5
Here we cascade DataOutputStream with FileOutputStream so that data we write will be stored
using FileOutputStream. In the same way, we can read primitive type values from a file using FileInput-
Stream. To store string values, you can either use writeBytes() or writeUTF(). You will use readLine()
to read the string that is stored using writeBytes(). Generally, readUTF() will recover data properly.
Now the issue is we need to store the values of all students in a file persistently so that we can read the
file contents at any time. In order to generate the results of students you will have to perform these tasks:
1. Store students details to the file using DataOuputStream
2. Open the file for reading using DataInputStream
3. Read values of records and calculate result
4. Display mark list
The complete program that performs the above tasks is given in Listing 13.12.
// MarkList.java
import java.io.*;
import java.util.*;
sc.nextLine(); // discard \n
// close stream
dos.flush();
dos.close();
}
float m1 = dis.readFloat();
float m2 = dis.readFloat();
float m3 = dis.readFloat();
float m4 = dis.readFloat();
System.out.print(“Marks: ”);
System.out.print(“Mark1 ” + m1 + “ ”);
System.out.print(“Mark2 ” + m2 + “ ”);
System.out.print(“Mark3 ” + m3 + “ ”);
System.out.print(“Mark4 “ + m4);
// calculate result
String result = “fail”;
if (m1 >= 40 && m2 >= 40 && m3 >= 40 && m4 >= 40)
result = “pass”;
System.out.println(“\nResult: ” + result);
}
// close stream
dis.close();
}
Enter mark2 78
Enter mark3 85
Enter mark4 35
This MarkList application has two methods. First storeMarks() receives values for students from
user and stores those students’ information in a file. It will ask first the maximum number of students
whose values are to be stored. Based on this value, it will collect all information about each student
and store them in the file using writeXXX() methods of DataOutputStream.
The second method processMarks() simply opens the file using DataInputStream and iterates
through the file and retrieves values using readXXX() methods. Result is calculated based on stu-
dents’ marks and is displayed.
need to downcast it to our original object type. In this book, we focus on how to write objects to files
using ObjectOutputStream and read file data using ObjectInputStream classes.
In Listing 13.13, you might see how to store objects of type Fish to files and read those Fish objects.
// StreamingFish.java
import java.io.*;
public Fish(int i)
{
id = i;
}
public String toString()
{
return Integer.toString(id);
}
}
E:\Rajkumar\javacourse\io>java StreamingFish
0
1
2
3
4
The Fish object is simply made Serializable object and rest of the code in Fish class is normal.
We just assign number to each fish and override toString() that will return fish number as a String. In
main(), we create object output stream that will allow us to write our serializable objects to file using
writeObject() method. The writeObject() stores Fish objects to file and then the stream is closed. As
a reverse process, we read serialized objects back from the same file using readObject() method. The
retrieved object should be downcasted to Fish type and must be caught for a possible exception of type
ClassNotFoundException without fail.
13.11 P
roblem: Generating Students’ Mark
List – Revisited
In section 13.9, you have learnt how to store and retrieve students’ details to file using D
ataInputStream
and DataOutputStream. Though data IO, classes allow us to store primitive data types, it will store
details as a sequence of bytes, not as student objects themselves. So we will lose information that these
bytes constitute a particular students’ details. Therefore the solution is to use Object IO. Listing 13.14
illustrates you how to store and retrieve array of student objects to and from file.
// StreamingStudents.java
import java.io.*;
import java.util.*;
// calculate result
String result = “fail”;
if (m1 >= 40 && m2 >= 40 && m3 >= 40 && m4 >= 40)
result = “pass”;
System.out.println(“\nResult: ” + result);
}
}
sc.nextLine(); // discard \n
stud[i].m2 = sc.nextFloat();
// SerializableAccount.java
import java.io.*;
Account number: 0
Balance: 0.0
Account number: 1
Balance: 0.0
Account number: 2
Balance: 0.0
Account number: 3
Balance: 0.0
Account number: 4
Balance: 0.0
All five bank accounts with accno and balance are stored as objects in a file. However, while you
retrieve them you will notice balance amounts are not visible. Only a default value of 0.0 will be
displayed. This way we can prohibit the visibility of sensitive and nonsharable information during
object serialization.
13.13 Summary
1. A stream is a group of bytes or characters that can be associated with physical objects such as
disks and devices
2. Streams help us to communicate with files by many ways such as sequentially, randomly, using
buffering, byte by byte, character by character, word by word and line by line
3. Each stream has a unique purpose and should be used accordingly
4. The File class represents the path name of a file or a set of files in a directory
5. The mkdir() creates a directory whereas mkdirs() creates a directory including its parent
directories
6. FilenameFilter is an interface that is used to filter file names based on some condition
7. FileFilter allows you to filter files not only based on their names but also based on their
properties or attributes.
8. InputStream classes are responsible for providing features in order to read data from data
sources
9. OutputStream classes are responsible for supporting features so as to write data from programs
to output destinations
10. FileInputStream allows us to read files as bytes using its read() method
11. FileOutputStream contains write() method in order to write bytes to files
12. The ByteArrayInputStream class uses a byte array as the source
13. The FileOutputStream writes data to the designated file, if the output file is available. If it is not
available, the stream will create the file and write data
14. The flush() transfers the contents of the buffer to the output file immediately
15. The readXXX() of DataInputStream and WriteXXX() of DataOutputStream will do reading and
writing primitive data types, where XXX denotes any primitive data type
16. Serializable objects can be transmitted over a network to another machine which can even run
on different Operating System
17. The writeObject() and readObject() methods of Object IO transmit serializable objects over
network
18. Transient variables will be not serialized
Key terms
Review questions
Multiple-choice Questions
1. Assume foo does not exist already. Which of the following is true?
a. 0 b. Null
c. 100 d. Exception
13. Assume class Test13 as in Example 12. What is the output?
a. 12 b. 21
c. 11 d. 22
e. None of the above
14. What is the output?
class A
{
int i = 1;
public A() {System.out.print(“2”);}
}
a. 112 b. 122
c. 221 d. None of the above
a. 2403 b. 1234
c. 1324 d. 1243
e. None of the above
a. 1234 b. 2413
c. 1324 d. 1423
e. None of the above
class A {}
class B implements Serializable
{
A a = new A();
int i = 1;
public B() {System.out.print(“2”);}
}
public class Test13 extends B
{
int j = 3;
public Test13() {System.out.print(“4”);}
a. 240 b. 2413
c. 2410 d. 2430
in.close();
}
}
a. 2234 b. 2423
c. 2324 d. 4232
e. None of the above
a. 23425
b. 35224
c. 22335
d. None of the above
Answers
1. b 2. b 3. d 4. b 5. d 6. e 7. d 8. c 9. b 10. a
11. b 12. c 13. b 14. c 15. a 16. b 17. a 18. b 19. b
Short-answer Questions
1. How to display properties of a file?
2. What are the file comparison methods?
3. Explain all methods related to directories.
4. Explain reading and writing bytes from files.
5. Explain all DataInputStream methods.
6. Explain all DataOutputStream methods.
7. Explain the process of serializing objects.
8. Explain the process of deserializing objects.
9. How will you prevent data from serialization?
Exercises
Objectives
■■ To introduce Reader and Writer abstract classes
■■ To introduce all Reader types such as FileReader, BufferedReader and PipedReader
■■ To read files as characters using FileReader
■■ To read files as lines of text using BufferedReader
■■ To count word frequencies of a given file
■■ To generate index for the given text file
■■ To write characters to file using FileWriter
■■ To copy file contents using FileReader and FileWriter
■■ To write lines of text to files using BufferedWriter
■■ To write bytes to PipedWriter and to read from PiperReader
■■ To design alphabet generator application using Piped IO and threads
■■ To format output strings using PrintWriter
■■ To create RandomAccessFile for direct access for reading and writing
■■ To convert bytes to characters using InputStreamReader
■■ To create channels and buffers using NIO
■■ To read bytes from FileChannel using ByteBuffer
■■ To write bytes to FileChannel using ByteBuffer
■■ To write characters to FileChannel using CharBuffer
■■ To lock files for atomic write operations to FileChannel
14.1 Introduction
Java 1.1 has provided significant improvements with its character-oriented streams over the earlier
Java 1.0 which supported only byte-oriented streams. In Java 1.1 characters are represented with
a 16-bit Unicode character representation. The main advantage of character streams is its support
for internationalization. Though character streams have definite advantages, they are not meant to
replace byte streams. This is why many byte streams are still retained so far and have a lot of applica-
tions. Moreover character streams are represented internally over byte streams.
In this chapter, the readers are exposed first to all important character stream classes that are avail-
able in Java, so that you will be able to develop efficient applications. Then, the readers are introduced
to buffered streams classes that will improve the performance of your applications. Further, the read-
ers learn how to bridge input streams and character streams so that byte streams can be converted to
character streams. Then the readers create streams that will allow you to open file for both reading
and writing and move through the file randomly with file pointers using random access file. Finally,
the readers are introduced to the features of java.nio package.
InputStream Reader
FileInputStream FileReader
ByteArrayInputStream CharArrayReader
PipedInputStream PipedReader
BufferedInputStream BufferedReader
// FileReader1.java
import java.io.*;
{
public static void main(String[] args) throws
IOException
{
if (args.length != 1)
{
System.out.println(“Enter file name for
reading...”);
System.exit(0);
}
while((c=fr.read()) != -1)
sb.append((char)c);
System.out.println(“Stringbuffer: ” + sb.toString());
fr.close();
}
}
You can also read the file contents into a char array in a single bulk read instead of reading c haracter
by character. In this way, your scheduler can minimize the number of disk read. Listing 14.2 tells you
all those details about reading characters into char array.
// FileReader2.java
import java.io.*;
fr.read(b);
System.out.println(“Using char array: ” + String.
valueOf(b));
fr.close();
}
}
/ FileWordCounter.java
import java.io.*;
import java.util.*;
{
public static void main(String[] args) throws IOException
{
if (args.length != 1)
{
System.out.println(“Enter file name for word
counting...”);
System.exit(0);
}
ht.put(word, 1);
}
}
// display ht
System.out.println(ht.toString());
}
}
Input:
it was a rainy day
it was a cold day
i was delighted by the weather
but i was alone
Output:
{rainy=1, was=4, weather=1, cold=1, it=2, i=2, delighted=1,
but=1, the=1, by=1, day=2, a=2, alone=1}
The main() first ensures if user has sent the file name as a command line argument. If not, the appli-
cation will report a message asking users to type file name for counting and terminates. If an input
file name is specified correctly, then FileReader reads one character at a time from file and appends
to string buffer. This way a long input string is created from string buffer, so that StringTokenizer
generates tokens from string buffer and the frequencies of unique words are stored in the Hashtable.
// bufferedReader1.java
import java.io.*;
{
if (args.length != 1)
{
System.out.println(“Enter file name for
processing...”);
System.exit(0);
}
String s;
int count = 0;
while (( s = br.readLine()) != null)
{
System.out.println(s);
count++;
}
br.close();
}
}
Output:
it was a rainy day
it was a cold day
i was delighted by the weather
but i was alone
No. of lines: 4
The given input file news.txt contains four lines of text. The readLine() will read one line at a time
from the file that is connected to FileReader. The while loop terminates when readLine() returns null,
indicating there is no more a line of text.
// TextIndexGenerator.java
import java.io.*;
import java.util.*;
// display
System.out.println(ht.toString());
}
}
Input: news.txt
it was a rainy day
it was a cold day
i was delighted by the weather
but i was alone
Output:
The input file news.txt contains four lines (assume: line 0 to line 3). The Hashtable maps each word
to a set of line numbers as int using HashSet. For instance, the word rainy appears in line number 0
only. Similarly, the word was appears in all lines.
In Chapter 1, the readers were introduced to Scanner class which can read a file and generate
tokens. So, in the above example, instead of BufferedReader you can also use Scanner with a d elimiter
“\n” so that it will return all tokens delimited by new-line as shown in Example 14.1.
// read file
Scanner sc = new Scanner(new File(args[0]));
sc.useDelimiter(“\n”);
OutputStream Writer
FileOutputStream FileWriter
BufferedOutputStream BufferedWriter
PipedOutputStream PipedWriter
PrintStream PrintWriter
// FileWriter1.java
import java.io.*;
For writing characters to file, you can either use write() or append(). To prevent overwriting, you
will have to create FileWriter with append mode to be true.
// FileCopy2.java
import java.io.*;
// create streams
FileReader in = new FileReader(args[0]);
FileWriter out = new FileWriter(args[1]);
// copy char by char
int c;
while((c = in.read()) != -1)
out.write((char)c);
// close files
in.close();
out.close();
}
}
E:\Rajkumar\javacourse\io>type dummy.txt
Hello Java, how are you!
This is another appended line?
E:\Rajkumar\javacourse\io>type dummynew.txt
Hello Java, how are you!
This is another appended line?
Once user supplies two file names representing source file and destination file, copying files is
straightforward. Just you need to read a character from source file with read() and write that character
to destination file using write() until you reach the end of file. The read() returns –1 when end of file
is reached.
// FileCopy3.java
import java.io.*;
public class FileCopy3
{
public static void main(String[] args) throws
IOException
{
// check command line arguments
if( args.length != 2)
{
System.out.println(“Syntax: java FileCopy2 file1
file2”);
System.exit(0);
}
// close files
in2.close();
out2.close();
}
}
E:\Rajkumar\javacourse\io>type dummy.txt
Hello Java, how are you!
This is another appended line?
E:\Rajkumar\javacourse\io>type dummy3.txt
Hello Java, how are you!
This is another appended line?
The users are expected to supply two files in the command prompt. They denote source and desti-
nation file names. The copying process is trivial; the program reads a line from stream and writes to
output file along with the new-line character.
Now let us create PipedWriter that will write a string to pipe and PipedReader reads from the pipe
if pipe has some available data. Listing 14.9 illustrates the use of piped character streams.
// PipeReadWrite.java
import java.io.*;
// Close pipes
reader.close();
writer.close();
}
catch (IOException e)
{
System.err.println(e.toString());
}
}
}
The connect() connects both pipes together. You can use connect() that is available in both pipe
types. The ready() checks whether some data are available.
Problem: Alphabets Generator Pipe
With the understanding of pipe IO character streams, we are now ready to solve slightly bigger problem
using threads. Assume we have two threads. One thread converts the given lowercase characters into
uppercase and writes them one at a time to PipedWriter object. The other thread reads those characters
one at a time from PipedReader object. Listing 14.10 demonstrates both writing and reading threads.
// CapitalizingPipe.java
import java.io.*;
{
sleep(200); // sleep for 100 milliseconds
char upper = Character.toUpperCase(c[count++]);
System.out.println(“Written uppercase letter to
pipe: ” + upper);
writer.write(upper);
}
catch(InterruptedException e) { }
catch(IOException e) { }
}
}
}
char c = (char)reader.read();
System.out.println(“Read uppercase letter from
pipe: ” + c);
if(c == ‘Z’)
break;
}
catch(InterruptedException e) { }
catch(IOException e) { }
}
}
}
String s = “abcdefghijklmnopqrstuvwxyz”;
new Capitalizer(writer, s);
new ReadCapitals(reader);
}
}
The Capitalizer thread receives PipedWriter object and the string as inputs. The toCharArray()
converts the given string into a series of characters. We do this conversion because we want to write
to pipe one character at a time. The write() inside run() writes this character to the pipe. The thread
terminates when it has finished sending all 26 lowercase alphabets to stream.
The ReadCapitals thread simply reads characters from the pipe using PipedReader using read().
The thread terminates if the last character read is z. Inside main(), we create a string of all lowercase
alphabets and instantiate both threads.
// PrintWriter1.java
import java.io.*;
{
public static void main(String[] args) throws
IOException
{
PrintWriter out = new PrintWriter(“dummy.txt”);
PrintWriter out2 = new PrintWriter (
new FileOutputStream( “dummy2.txt”));
out.print(100);
out.println(“rex”);
out.print(new Integer(10));
out2.print(200);
out2.println(“peter”);
out.close();
out2.close();
Java supports C-style features to format the output string. Though its features are very similar to C,
it supports more features such as Locale and Date formatting. However, if the formatting specification
for Locale or Date formats is incompatible to input data, then JVM will through an exception. The
format() formats multiple arguments based on a format string. The format specifiers are used to design
the format string. Figure 14.4 depicts some frequently used format specifiers.
In Listing 14.12, you will see some of the format specifiers in use.
// FormatSpecifiers.java
import java.io.*;
The PrintWriter can write the formatted output string to the connected stream. For example, if
PrintWriter is connected to FileWriter then the formatted output will be written to file as illustrated
in Listing 14.13.
// PWFormatting.java
import java.io.*;
PrintWriter can also be used as a replacement for System.out so that the outputs will be transferred to
command prompt. Let us now develop an application as shown in Listing 14.14 to write data to screen.
// PWprompt.java
import java.io.*;
Hello Java !
100000
In the constructor, System.out is an output stream (in our case command prompt) and true flushes
the buffer contents to the stream immediately, without which you will not be able to see the output in
the command prompt immediately.
using writeByte() methods. The length() determines the length of the file. Listing 14.15 explains all
important methods of random access file.
// RAF.java
import java.io.*;
System.out.println(“Length: ” + file.length());
System.out.println(“current file pointer: ” + file.
getFilePointer());
file.close();
file.skipBytes(12); // 41 + 12 = 53
System.out.println(“Skip 12 bytes: ” + file.
getFilePointer());
file.close();
// go to end of file
file = new RandomAccessFile(“employee.dat”,“rw”);
file.seek(file.length()); // advance file pointer to the
length of the file
file.writeDouble(12345.6789);
file.close();
}
}
Length: 93
current file pointer: 61
At byte 0: 1001
At byte 4: R e x
At byte 12: Trichy
At byte 20: 1002
At byte 24: R i a
At byte 32: Chennai
At byte 41: 1003
At byte 45: M i a
At byte 53: Mumbai
Ar byte 12 Trichy
At byte 32: Chennai
Skip 12 bytes: 53
// FileReadISR.java
import java.io.*;
byte[] b =
“This string is stored as bytes and read with reader”.
getBytes();
// store bytes
out.write(b);
// close it without fail
out.close();
// use reader
BufferedReader in = new BufferedReader(new InputStreamReader(
new FileInputStream(“dummyisr.dat”)));
// show
String s;
while ((s = in.readLine()) != null)
System.out.println(s);
// close
in.close();
}
}
Channel Buffer
Buffer1
Channel Buffer2
Buffer3
Channels are similar to standard IO streams, but they are platform-independent version of a stream.
Channels are same as normal streams. But there is a difference; streams are unidirectional whereas
Channels are bidirectional. FileChannel is one of the implementations of Channel that is used for read-
ing, writing and manipulating files. The getChannel() returns FileChannel that is connected to FileIn-
putStream, FileOutputStream and RandomAccessFile. Example 14.2 obtains you a FileChannel.
A Buffer is a container that will hold all data that are either to be stored or just now read from Chan-
nel. Buffer is an interface between our program and Channel. Whenever data are read, they are read
directly into a buffer. Similarly whenever data are written, they are written to buffer only. Buffer is
implemented as a byte array with necessary features for structured access to data. The allocate() cre-
ates a buffer with a required size given as argument as shown in Example 14.3.
There are several types of buffers (as depicted in Figure 14.6) to deal with different primitive data
types and all buffers are instances of Buffer interface such as
■■ ByteBuffer
■■ CharBuffer
■■ ShortBuffer
■■ IntBuffer
ByteBuffer
MappedByteBuffer
CharBuffer
ShortBuffer
IntBuffer
LongBuffer
FloatBuffer
DoubleBuffer
■■ LongBuffer
■■ FloatBuffer
■■ DoubleBuffer
// FileReadNIO.java
import java.io.*;
import java.nio.*;
import java.nio.channels.*;
buff.clear();
fc.read(buff);
buff.flip(); // now buffer read mode
while(buff.hasRemaining())
System.out.print((char) buff.get());
}
}
The flip() is an interesting method with which you can flip a buffer from read mode to write mode
and vice versa. That is, the same buffer is used for reading and writing. The hasRemaining() checks
if buffer has some more bytes for reading. The rewind() resets the position of pointer to the beginning
of the buffer. The get() reads one byte at a time from buffer. The bulk read into byte[] is also possible
with the overloaded get().
// FileWriteNIO.java
import java.io.*;
import java.nio.*;
import java.nio.channels.*;
In the beginning, you saw the different kinds of buffer. But so far we have been using only Byte-
Buffer. Now let us see how to create other types of buffers. Unfortunately, Java does not provide
us ways to directly instantiate buffer types. So you need to use methods from ByteBuffer that will
give you different perceptions of other buffers. In Listing 14.19, you will notice how a CharBuffer is
created and a string is stored using put().
// CharBuffer1.java
import java.io.*;
import java.nio.*;
import java.nio.channels.*;
The asCharBuffer() gives us the perception of CharBuffer, so that we will be able to store strings.
// FileCopyNIO.java
import java.io.*;
import java.nio.*;
import java.nio.channels.*;
{
if(args.length != 2)
{
System.out.println( “Usage: java FileCopyNIO file1
file2”);
System.exit(1);
}
buff.clear();
fcin.read(buff);
buff.flip(); // now read mode
fcout.write(buff);
}
}
E:\Rajkumar\javacourse\io>type nio.txt
Hello Java How are you
E:\Rajkumar\javacourse\io>type nio2.txt
Hello Java How are you
//FileLocking.java
import java.io.*;
import java.nio.*;
import java.nio.channels.*;
This FileLocking application connects FileChannel to random access file. Once you have created
file channel and buffer, you can call overloaded lock() to lock entire file or parts of a file so that you
will perform atomic operations on the file. Later the random access file is opened in read mode so that
read() will fill up buffer with the contents of the file and buffer contents are displayed.
14.13 Summary
1. Java 1.1 supports character streams and Java 1.4 supports NIO
2. Each character is represented using 16-bit Unicode representation
3. All character streams are subclasses of either Reader or Writer, both are abstract classes
4. FileReader allows us to read characters from files
5. FileNotFoundException will be thrown if file is not assigned for reading or writing
6. BufferedReader allows us to read files line by line
7. Characters can be written to file using FileWriter
8. PipedWriter can write bytes to pipes
9. PipedReader can read data from pipes if pipe is ready
10. The connect() method connects both input pipes and output pipes
11. With PrintWriter, we can format output strings
12. PrintWriter can also be used instead of System.out to send data to command promt
13. PrintWriter is another way of storing primitive data types to files
14. A RandomAccessFile behaves as both input file and output file
15. InputStreamReader converts bytes to characters
16. The channels and buffers are cornerstone of NIO
17. The allocate() method creates buffer
18. FileChannel allows us to read or write to files by using buffers
19. You can get FileChannel by calling getChannel() available in FileInputStream, FileOutputStream
or RandomAccessFile
20. The flip() flips buffer from read mode to write mode and vice versa
21. Locks can be obtained on files so that atomic write operations can be performed
Key terms
Review questions
Multiple-choice Questions
1. How many bytes can you read?
out.writeInt(20000);
out.close();
a. 32 b. 16
c. 8 d. 4
e. None of the above
a. 32 b. 16
c. 8 d. 4
e. None of the above
a. 3 b. 4
c. 6 d. 7
e. None of the above
6. How will you detect end of file while reading using FileReader?
a. The read() returns null b. The read() returns –1
c. The read() returns 0 d. None of the above
10. Which of the following are the valid file modes for random access file?
a. r b. w
c. rw d. r+w+
e. None of the above
a. IllegalArgumentException b. FileNotFoundException
c. IOException d. None of the above
a. FileNotFoundException b. IOException
c. Opens in append mode d. None of the above
file.writeChars(“Rex\n”);
file.writeUTF(“Trichy”);
System.out.println(file.getFilePointer());
a. 13 b. 14
c. 20 d. 24
e. None of the above
a. R b. h
c. T d. None of the above
29. How will you change ByteBuffer from read mode to write mode and vice versa?
a. flip() b. swap()
c. exchange() d. None of the above
Answers
1. c 2. c 3. d 4. e 5. a 6. b 7. b 8. c, d 9. b 10. a, c
11. c 12. d 13. c, d 14. b, c 15. d 16. a 17. b 18. b, c 19. b 20. b
21. a 22. d 23. b 24. d 25. c 26. a 27. a 28. d 29. a
Short-answer Questions
1. Differentiate read() and readLine() methods.
2. Differentiate append() and write().
Exercises
14.1. [File Tokenizer] Design an application that will read file from command line and print the fre-
quency of words excluding stop words. For example, words like a, an, the, that, of and others
are stop words. Prepare at least 20 stop words and use them for your filtering. Hint: you can
reduce the amount of computation by representing stop words as a set.
14.2. [File Translator] Read a source file containing English text and property file containing trans-
lation words from user and display its translated content to a target language such as Tamil,
Hindi, French, Spanish, German or others. Prepare a property file containing at least 10 words
that are used for translation.
14.3. [Sport News Service] Download few news articles about sports from Google or Yahoo sports
and save them in your local disk. Develop an application that reads a topic from user such as
cricket and displays those lines in files where this topic appears.
14.4. [Business News Service] Modify the above application for business news articles.
14.5. [Dictionary Lookup] Download some free dictionary data from internet and save it in your
local disk. Then read a word from user and display its meaning by consulting the dictionary.
14.6. [Login Manager] Modify Exercise 9.7 so that you can prepare a property file containing few
usernames and passwords. Receive username and password from keyboard and check his cre-
dentials. If there is a match, give him a message Login successful. If username does not exist,
collect username and password from user and insert a new entry. Hint: you need Hashtable or
HashMap to manipulate these key-value pairs.
14.7. [Spam Detector] Modify Exercise 9.8, so that all spam words are stored in a file and consulted
for checking your input email files whether they are spam or not.
14.8. [Stock Quote Service] Download stock prices of Indian companies from Yahoo! finance or
Google finance and save them into a file in your local disk. Read a company name from user
and display its current stock price from the file.
14.9. [Address Book Manager] Create a class Address that represents name, mobile number and
email details as strings. Design a public class AddresBookManager that supports the f ollowing
operations
1. Add new address
2. Edit address
3. Remove address
Objectives
■■ To explain class hierarchy of swing components and containers
■■ To introduce three containers: JFrame, JPanel and JApplet
■■ To draw geometric shapes such as lines, arcs, ovals, rectangles, polygons and polylines using
methods from Graphics class
■■ To generate random multilines
■■ To draw random rectangles
■■ To load images using Toolkit and ImageIcon and display them
■■ To design multithreaded blinking balls
■■ To paint random circles using JApplet
■■ To use Graphics2D class methods for painting geometric shapes such as lines, curves, rect-
angles, ellipses and arcs
■■ To introduce Colors, GradientPaint and TexturePaint classes
■■ To draw arbitrary shapes using GeneralPath class
■■ To apply translation, rotation, scaling and shear transformations to coordinate system
■■ To clip a shape or image against another shape
■■ To introduce affine transformations on images
15.1 Introduction
In part 1–4, the readers were introduced to Java basics, Object-oriented programming, all Java contain-
ers to hold objects and Java threads and IO streams. Part 5 of this book introduces you to Graphics
programming, GUI development using JFrames and GUI development using JApplets. Swing is an
e fficient Java Platform, which is a part of Java Foundation Classes (JFC), for graphical user interface
(GUI) programming. So here is a word UI. What is word UI for? It stands for user interface. Still not
clear! UI is any object that allows interaction between users and the computer. For example, you might
think of mouse, keyboard, music, video, button, combo box and window; all are UIs. We separate all
graphical objects such as button, combo box and windows and call them as GUIs. So swing is a piece
of software package that handles all interactions between a user and computer. So far, we have used
only one UI for our computations namely command window and it gives us textual view of the inputs
and outputs and Swing takes us to the next level of user interaction with its graphical UI components.
Java’s journey with GUI started with Abstract Windowing Toolkit (AWT) introduced in Java 1.0.
The set of classes and interfaces available in Java 1.0 was very limited and mostly not suitable for
large-scale GUI projects. Besides, AWT was very much prone to platform-specific bugs and not fully
based on object-oriented design principles. Then came Java 1.1 with object-oriented design support.
Java’s journey ended with its well-matured GUI tool kit with Java 1.2 or Java 2. This robust, versatile
and flexible library is called Swing. Swing is considered to be lightweight components as it depends
less on the target platform and uses less native GUI resources.
Swing GUI components are prefixed with J. Even though all AWT components are still supported
in Java, those components are deprecated and will fade away very slowly. Hence this book will
attempt to base GUI design on top of Swing instead of AWT components. Therefore you will learn all
GUI programming principles, tricks and techniques using Swing instead of AWT. In this chapter, the
readers will be led to the understanding of the Swing GUI basics, in particular an overview of compo-
nents and containers that are necessary to develop graphics applications using Java 2D graphics API.
In chapters 16 and 17, the readers will be introduced to all components that are required to develop
GUI using JFrame (Chapter 16) and JApplet (Chapter 17).
As part of Java 2D graphics, java.awt.geom package defines all shapes such as point, line, curve, rect-
angle, arc, ellipse, etc. and performs operations related to 2D geometry. You will be using Graphics2D
class from AWT package to draw various shapes that are defined in geom package. One final note: readers
are expected to be able to read Javadoc of Swing classes (in Sun’s API) to learn about the structure and use
of various methods. Note that some of these methods are static methods and variables (mostly constants).
Java containers will hold all components. The AWT package provides Applet, Frame, Panel and
Window containers. These containers are extended in Swing package and we will be using JFrame,
JPanel, JApplet and JDialog in order to hold swing components as depicted in Figure 15.1.
Container
The javax.swing package contains a wealth of components with which you will be able to feed input
values and display outputs in GUI applications. Figure 15.2 depicts a subset of the class h ierarchy of
swing components. The java.awt.Container is the base class for javax.swing.Jcomponent which in
turn is the base class for all swing components such as JButton, JLabel and so on.
Container
JComponent
// FirstFrame.java
import javax.swing.*;
The setSize(300,200) creates this frame with 300 pixels width and 200 pixels height. The
setLocationRelativeTo(null) centres the frame to screen while the setDefaultCloseOperation() m
ethod
with a constant closes the frame; otherwise you need to press Cntl-C to break the execution.
Instead of creating a JFrame inside public class, we can convert the public class itself as a frame
and the constructor can be used for initializing the frame properties as shown in Listing 15.2.
// MyFrame.java
import javax.swing.*;
import java.awt.*;
The background colour for the frame can be painted using setBackground() method that takes
colour value as a static constant. Instead of directly calling setBackground(), you can also call it from
getContentPane(). The getContentPanel() of JFrame returns something called ContentPane and you
set the required colour to the ContentPane instead of JFrame. In fact, whatever component you add
Content pane
Figure 15.3. Content Pane
to JFrame is simply added to only ContentPane and not directly to JFrame. But for certain methods
like setBackground(), you need to add to ContentPane. Basically, a frame has two parts – header and
content pane – as shown in Figure 15.3. So all java components are only added to content pane even
though we say we add components to frame.
(0,0) 50 w = 150
60
(50, 60)
h = 100
g.drawPolygon(); // outline
g.fillPolygon(); // solid
g.drawOval(); // outline
g.fillOval(); // solid
}
One more final point you need to observe before moving on to learning all those methods for draw-
ing graphical primitives. That is about the painting coordinate system. Conventionally we assume an
origin (0, 0) at the centre of a paper and plot all graphics. But Java follows a different painting origin.
The origin (0, 0) indicates the pixel at the top-left corner of the painting canvas. The x axis goes
horizontally and y axis goes vertically downwards. The lower right pixel will hold upper coordinate
for the screen as depicted in Figure 15.5. Generally all shapes will be painted just below the starting
coordinate and enlarges to its width and height. Also in Figure 15.5, an ellipse is painted from (0, 0)
with a width of 150 and height of 100 pixels.
// LinesFrame.java
import javax.swing.*;
import java.awt.*;
//super.paintComponent(g);
g.setColor(Color.RED);
g.setFont(new Font(“Times”, Font.BOLD, 24));
g.drawString(“Hello Java Frame”, 100, 100); // at (100,10)
g.drawLine(100,150, 300, 150); // (100,150) to (300,150)
g.drawLine(150,200, 300, 250);
g.drawLine(350,100, 350, 200);
}
}
public LinesFrame()
{
add(panel);
setTitle(“Drawing Lines”);
setSize(400,400);
setLocationRelativeTo(null); // centres to screen
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // closes
frame
setVisible(true);
}
The setFont() method uses Font object as argument. The java.awt.Font object is created with three
arguments: the font name, whether PLAIN, BOLD or ITALIC and size in points such as 20 points.
You can have different font names such as Times, Courier and SansSerif.
// MultilinesFrame.java
import javax.swing.*;
import java.awt.*;
import java.util.*;
x = r.nextInt(w);
y = r.nextInt(h);
g.drawLine(w/2, h/2, x, y);
}
}
}
public MultilinesFrame()
{
add(panel);
Here we use JPanel as a canvas for painting. The paintComponent() method is automatically invoked by
JVM in order to draw the graphics. The setColor() defines colour for the graphics objects. The Color object
will be created with random values for red, green and blue. All lines are drawn from the origin to a random
point. The origin is the centre point of the frame, which is nothing but half of its width and height. The ran-
dom point is generated using nextInt() method from util.Random class. Rest of the code is self-explanatory.
■■ The drawRoundRect(x, y, w, h, aw, ah) paints a round rectangle where aw and ah specifies the
width and height of the arc.
■■ The fillRoundRect() fills the round rectangle with the predefined colour.
■■ The draw3DRect(x, y, w, h, raised) paints 3D rectangle. Also you should specify a boolean
value mentioning you want your rectangle raised or lowered
■■ The fill3DRect() is same as 3D rectangle with a predefined colour
Now let us develop a simple application that will generate all these six rectangles with different
colours as depicted in Listing 15.5.
// RectangleFrame.java
import javax.swing.*;
import java.awt.*;
public RectangleFrame()
{
add(panel);
setTitle(“Drawing Rectangles”);
setSize(500,500);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
public static void main(String[] args)
{
RectangleFrame f = new RectangleFrame();
}
}
The setColor() defines colour for the graphics with colour specified as constants such as Color.red,
Color.RED, Color.pink and so on. Note that your colour constants support both lowercase and upper-
case static variables. The Color can be specified with its colour constant or its rgb values which can
take any value from 0 to 255. The setXORMode() performs XOR on two colour values. The intersec-
tion of the two objects will be painted with the XOR colour. The setPaintMode() restores the drawing
back to the original colour. Also we call base class’ super.paintComponent(g) method to clear the
contents of the paint buffer. Further round rectangles assume half of the diameter of the arc’s width
and height to all four corners of the rectangle.
Also we should generate a random point where our rectangles will begin painting. Remember a ran-
dom location should be within the size of the frame. So our nextInt() should generate appropriate point
considering the width and height of the frame. Listing 15.6 illustrates random rectangle generator.
// RandomRectangle.java
import javax.swing.*;
import java.awt.*;
import java.util.*;
{
RandomRectangle f = new RandomRectangle();
}
}
// OvalFrame.java
import javax.swing.*;
import java.awt.*;
g.setColor(Color.BLUE);
g.drawOval(50, 150, 100, 50); // horizontal ellipse,
width > height
g.setColor(Color.MAGENTA);
g.fillOval(200, 150, 100, 50); // filled horizontal ellipse
g.setColor(Color.GREEN);
g.drawOval(50, 250, 50, 100); // vertical ellipse, width <
height
g.setColor(Color.CYAN);
g.fillOval(150, 250, 50, 100); // filled vertical ellipse
}
}
public class OvalFrame extends JFrame
{
Oval panel = new Oval();
public OvalFrame()
{
add(panel);
setTitle(“Drawing Circles and Ellipses”);
setSize(350,400);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
public static void main(String[] args)
{
OvalFrame f = new OvalFrame();
}
}
30
15
(X, Y)
Listing 15.8 demonstrates painting of few arcs both outline and filled with colours.
// ArcFrame.java
import javax.swing.*;
import java.awt.*;
g.setColor(Color.MAGENTA);
g.fillArc(0, 0, getWidth(), getHeight(), 180, 45);
g.drawArc(0, 0, getWidth(), getHeight(), 225, 45);
g.setColor(Color.GREEN);
g.fillArc(0, 0, getWidth(), getHeight(), 270, 45);
g.drawArc(0, 0, getWidth(), getHeight(), 315, 45);
}
}
public ArcFrame()
{
add(panel);
setTitle(“Drawing Arcs”);
setSize(300, 300);
setLocationR elativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
This application generates four arcs and four filled-in arcs one after another starting from angle
0 degree to 360 degrees. The arcs are drawn inside the enclosed frame whose dimension can be
obtained with getWidth() and getHeight() methods. We assume start angles for the arcs start at 0 and
continues in steps of 45. The arc angle for all arcs and filled arcs is always 45.
// PolygonFrame.java
import javax.swing.*;
import java.awt.*;
import java.util.*;
{
Polygons panel = new Polygons();
public PolygonFrame()
{
add(panel);
setTitle(“Drawing Polygons”);
setSize(350, 275);
setLocationRelativeTo(null); // centres to screen
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // closes
frame
setVisible(true);
}
The static getDefaultToolkit() returns an object of Toolkit, and with this instance you can call getI-
mage() with the filename as String. The getImage() returns the corresponding Image object. Alter-
natively, you can use getImage() from ImageIcon class to load the image. Listing 15.10 displays the
image onto the canvas.
// ImageFrame.java
import javax.swing.*;
import java.awt.*;
class Img extends JPanel
{
public void paintComponent(Graphics g)
{
super.paintComponent(g);
public ImageFrame()
{
add(panel);
setTitle(“Displaying Images”);
setSize(500, 400);
setLocationRelativeTo(null); // centres to screen
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // closes
frame
setVisible(true);
}
// BlinkingBall.java
import java.awt.*;
import javax.swing.*;
import java.util.*;
// paint updates
p.update(g);
}
}
aintComponent() inside JPanel, we need to override paint() inside JApplet. The applet receives
p
graphics context through the Graphics object as an argument of paint().
// CircleApplet.java
import javax.swing.*;
import java.awt.*;
import java.util.*;
Inside main(), JFrame instance is created and JApplet instance is added to frame. Since we define
main() inside the applet, we can execute this applet as a normal Java application. The aim of this
application is to just introduce JApplet as a container for swing components and to override paint()
so that we will be able to draw graphical objects and display images. The JApplet architecture,
functionality and applications are huge and we will differ the discussions to Chapter 17.
Graphics2D g2 = (Graphics2D)g;
Line2D.Double line = new Line2D.Double(x1, y1, x2, y2);
And then draw as
g2.draw(line);
Alternatively you can just use constructor itself to instantiate
object as
g2.draw(new Line2D.Double(x1, y1, x2, y2));
(cx, cy)
(x1, y1)
(x2, y2)
(cx1, cy1)
(x2, y2)
(x1, y1)
(cx2, cy2)
The program depicted in Listing 15.13 paints Lines, QuadCurves and CubicCurves. Also, you will
observe how setPaint() paints the panel with a colour. You can also use setCurve() method to define
coordinates for quad curve and cubic curve instead of using constructor for initialization.
// GeometricPrimitives2D.java
import javax.swing.*;
import java.awt.*;
import java.awt.geom.*;
g2.setPaint(Color.green);
// create new CubicCurve2D.Double
CubicCurve2D.Double c = new CubicCurve2D.Double();
// curve from (250,250) to (320,225)
// two control points: (275, 200) and (300, 275) in between
end points
c.setCurve(250, 250, 275, 200, 300, 275, 320, 225);
g2.draw(c);
}
}
The Arc2D.Double and Arc2D.Float classes define arcs. Besides the usual origin from top-left
corner, dimension in terms of width and height and both angle values representing start angle and arc
angle, you need to specify arc closure. There are three types of arc closures: Arc2D.CHORD, Arc2D.
OPEN and Arc2D.PIE as depicted in Figure 15.12.
In the example shown in Listing 15.14, you will notice rectangles, ellipses and arcs drawn with
ifferent colours. Hope you will remember circles are nothing but ellipses with equal height and
d
width. Also, the program paints all three arc types.
// GeomPrim2.java
import javax.swing.*;
import java.awt.*;
import java.awt.geom.*;
g2.setPaint(Color.red);
// draw Rectangle2D.Double
g2.draw(new Rectangle2D.Double(20, 20, 100, 50));
g2.setPaint(Color.green);
// draw RoundRectangle2D.Double
g2.draw(new RoundRectangle2D.Double(20, 100, 100, 50,
20, 20));
g2.setPaint(Color.blue);
g2.draw(new Ellipse2D.Double(150, 20, 100, 50));
g2.draw(new Ellipse2D.Double(150, 100, 50, 50));
g2.setPaint(Color.magenta);
g2.draw(new Arc2D.Double(20, 175, 100, 50, 90, 135, Arc2D.
OPEN));
g2.draw(new Arc2D.Double(150, 175, 100, 50, 90, 135,
Arc2D.CHORD));
g2.draw(new Arc2D.Double(75, 175, 100, 50, 90, 135,
Arc2D.PIE));
}
}
public GeomPrim2()
{
add(panel);
setTitle(“Rect Ellipse Arcs”);
setSize(350,350);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
public static void main(String[] args)
{
GeomPrim2 gp = new GeomPrim2();
}
}
15.18 F
illing with Color, GradientPaint
and TexturePaint
The awt.Graphics class just supports solid colour with which you will paint the shape. But, solid fill-
ing is not appealing; the entire surface is painted with a single colour. Also you will have to use only
limited colour choices either with predefined colour constants or with rgb values from 0 to 255 repre-
senting colour values. The Color class in 2D graphics apart from colour constants allows us to specify
float values for rgb in the range of 0.0f to 1.0f. Internally the corresponding float value is converted to
int value by multiplying 255 and rounding up. For example, let us define a colour with float type for
rgb as shown in Figure 15.13.
Once colour object is created, then you can use setPaint() method to paint Graphics2D context
with new colour. Remember colour object can also be instantiated as an argument inside setPaint().
The GradientPaint class blends two colours with a smooth transition from one colour to the second
colour. So to fill a shape with a gradient paint, you will have to first create a GradientPaint object,
invoke setPaint() method with this GradientPaint object and finally fill() will fill the shape with this
gradient paint. Figure 15.14 explains you how to create GradientPaint object and Figure 15.15 depicts
the blending of two colours.
As depicted in Figure 15.15, the area in between gradient line (also delimited within dotted lines)
will be painted with the blended colours. The area covered by c1 will be painted with colour c1.
Similarly area covered by c2 will be painted with colour c2. Therefore, horizontal gradient line results
into blending left to right; diagonal gradient line results into blending of colours diagonally and verti-
cal line results into blending of colours vertically.
Besides colour filling and gradient filling, there is one more type of filling possible with shapes,
known as texture filling. A texture should be created using a BufferedImage first. Then this texture
will be painted repeatedly like laying floor with tiles. The TexturePaint class represents a texture.
Then a rectangle should be defined using this texture image, and this rectangle will be replicated over
the shape. The texture image will be automatically scaled to fit into the rectangle. For example, let us
create a texture as shown in Figure 15.16.
c1
c2
c1
c2
Here our texture image consists of a rectangle with red and an ellipse filled in with magenta. This
texture rectangle can be repeated over and over again on the shape. In Listing 15.15, you will find all
these three types of filling in use.
// FillRect2D.java
import javax.swing.*;
import java.awt.*;
import java.awt.geom.*;
import java.awt.image.BufferedImage;
g2.setPaint(c3);
g2.fill(new Ellipse2D.Double(150, 20, 100, 50));
g2.setPaint(Color.pink);
g2.fill(new Arc2D.Double(150, 100, 100, 50, 90, 135, Arc2D.
OPEN));
BufferedImage bi =
new BufferedImage(5, 5, BufferedImage.TYPE_INT_RGB);
Graphics2D gg = bi.createGraphics();
gg.setColor(Color.green);
gg.drawRect(0, 0, 5, 5);
gg.setColor(Color.pink);
gg.fillOval(0, 0, 5, 5);
Rectangle r = new Rectangle(0, 0, 5, 5);
g2.setPaint(new TexturePaint(bi, r));
public FillRect2D()
{
add(panel);
setTitle(“Geometric Primitives”);
setSize(300,275);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
is not invoked first, then JVM will generate IllegalPathStateException. Listing 15.16 draws two arbi-
trary shapes: one diamond and one random figure using lines and quad curve. Also setStroke() defines
thickness in points for lines.
// GeneralPath2D.java
import java.awt.*;
import javax.swing.*;
import java.awt.geom.*;
// define a rectangle
path.moveTo(50,50);
path.lineTo(75, 75);
path.lineTo(50, 100);
path.lineTo(25, 75);
path.lineTo(50,50);
Graphics2D g2 = (Graphics2D)g
g2.translate(100,100); // move to (100,100)
g2.rotate(180); // rotate coordinate system 180 degrees
// Transformation2D.java
import java.awt.*;
import javax.swing.*;
import java.awt.geom.*;
g2.setPaint(Color.green);
g2.fill(new Rectangle2D.Double(0, 0, 50, 50));
g2.translate(100, 100);
g2.rotate(30.0 * Math.PI/180.0);
g2.scale(2.0, 2.0);
g2.setColor(Color.red);
g2.fill(new Rectangle2D.Double(0, 0, 50, 50));
}
}
public Transformation2D()
{
add(panel);
setTitle(“2D Transformations”);
setSize(350,350);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
We will develop another application that will apply shear transformation for the coordinate system
as depicted in Listing 15.18.
// Shear2D.java
import java.awt.*;
import javax.swing.*;
import java.awt.geom.*;
g2.setPaint(Color.green);
g2.fill(new Rectangle2D.Double(50, 50, 75, 75));
public Shear2D()
{
add(panel);
setTitle(“Shear Transformations”);
setSize(350,200);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
public static void main(String[] args)
{
Shear2D gp = new Shear2D();
}
}
15.21 2D Clipping
Clipping is another interesting feature in Graphics2D class. Clipping is a process of removing all
uninterested portions of the given image or shape by rendering only the interested portion of the shape
or image. In order to perform clipping, you need to first define clip boundary within the panel by using
setClip() method. Then clip() will render the portion of the shape that is common to clip boundary and
the given shape. In Listing 15.19, a rectangle is clipped against an ellipse.
// Clip2D.java
import java.awt.*;
import javax.swing.*;
import java.awt.geom.*;
class Panel2D extends JPanel
{
// ImageTrans2D.java
import javax.swing.*;
import java.awt.*;
import java.awt.geom.*;
public ImageTrans2D()
{
add(panel);
setTitle(“Transformation on Images”);
setSize(500, 400);
setLocationRelativeTo(null); // centres to screen
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // closes
frame
setVisible(true);
}
15.23 Summary
1. Swing toolkit is part of JFC for designing GUI applications
2. Swing components and containers start with a letter J to distinguish AWT components and
containers
3. The geom package defines all geometrical shapes
4. The JFrame, JPanel and JApplet are some important swing containers
5. To draw a shape, paintComponent() is overridden inside JPanel
6. The paintComponent() receives Graphics context as an argument, so that all of its drawXXX()
and fillXXX() can be used to paint outline and filled shapes
7. The drawing panel starts at top-left corner, x axis denotes its width and y axis denotes its height
8. The add() adds a component into container directly instead of adding them to content pane
9. The drawImage() paints an image that is loaded with Toolkit or ImageIcon class
10. The JApplet can be used as a container to create shapes
11. The Graphics2D class extends Graphics class and contains draw() and fill() methods for p ainting
shapes
12. The shapes are defined in geom package
13. The shapes can be created with Float precision or Double precision in contrast to int precision
of Graphics context
14. The Color object can take innumerable colour choices with float values for rgb
15. The GradientPaint blends two colours together by specifying blending region
16. The TexturePaint allows us to create a paint pattern so that it will be repeatedly painted like
floor tiles
17. Arbitrary shapes can be drawn using GeneralPath
18. The translation, rotation, scaling and shear are important transformations that can be applied to
coordinate plane instead of shapes
19. The clip() from Graphics2D class removes uninteresting portions of a shape against a clipping shape
20. The AffineTransform object performs transformations such as translation, rotation, scaling and
filtering on images
Key terms
Review questions
Multiple-choice Questions
1. Which of the following are true about Swing and AWT?
a. AWT components are heavy-weight components
b. Swing components are lightweight components
c. Look and feel of the GUI can be changed in Swing, but not in AWT
d. For drawing, AWT uses screen rendering where Swing uses double buffering
e. All of the above
2. Which of the following are true about JComponent?
a. Abstract class b. Supports look-and-feel
c. Supports keystroke handling d. All of the above
3. What method you override to draw graphics primitives such as lines and circles?
a. paint() b. paintComponent()
c. draw() d. All of the above
drawLine(100,100,200,100)
drawLine(100,100,300,300)
15. How to draw rectangle at (50,50) with height 20 and width 30?
a. drawRect(50,50,20,30); b. drawRect(50,50,30,20);
c. drawRect(20,30,50,50); d. drawRect(30,20,50,50);
e. None of the above
draw(new Line2D.Double(100,100,300,100));
28. Which class blends two colours with a smooth transition from one colour to another?
a. TexturePaint b. GradientPaint
c. BlendedPaint d. None of the above
Answers
1. e 2. d 3. b 4. b 5. c 6. b 7. c 8. b 9. b 10. b
11. c 12. a 13. c 14. a 15. b 16. a 17. a 18. d 19. c 20. a
21. d 22. a 23. a 24. a 25. a,b 26. a 27. d 28. b 29. b 30. a
31. b 32. d
Short-answer Questions
1. Write an overview of swing containers.
2. What is content pane?
3. How to draw lines and strings?
Exercises
15.1. Display at least five smileys (smiling humaniod face) with multiple colours.
15.2. Display the following graphical objects: cube, prism, cylinder, sphere and cone.
15.3. Display a chess board (8×8 squares) with red and black colours.
15.4. Draw various ellipses of same size so that it appears like a flower.
15.5. Draw diamond inside another diamond recursively (upto N levels).
15.6. Draw the image of the coloured heart.
15.7. Simulate the sine, cosine and tan waves with different colours.
15.8. Draw few fractal images as you like. Hint: refer any graphics book on fractal geometry.
15.9. Display the animated analog clock.
15.10. Draw few random art images. Basically x and y coordinate values range from –1 to +1 along
with sin() and cos() values for rgb values. (Good reference at http://www.random-art.org/.)
15.11. Generate large random numbers (say 1000 numbers) and sort them using bubble sort. D isplay
the progress of sorting by various lines.
16
GUI Development
Using JFrame
Objectives
■■ To explain the general structure of any GUI application
■■ To create JLabel and JButton using swing package
■■ To develop a digital clock as a JLabel
■■ To introduce event handling, ActionEvent and ActionListener
■■ To explain different layout managers such as FlowLayout, BorderLayout, GridLayout,
BoxLayout and Box
■■ To use JPanel to design multiple layouts for the frame
■■ To explain the three fillers for Box namely strut, glue and rigid area
■■ To introduce event types, their listeners, adapters and all methods
■■ To paint JLabel with random colours whenever a button is pressed
■■ To move a filled circle to random locations whenever a button is pressed
■■ To create textfield, password textfield and text area
■■ To display the contents of a file in text area
■■ To develop a textfield that accepts only digits
■■ To develop text copy cat application
■■ To create checkboxes, radiobuttons, comboboxes and lists
■■ To create dialog windows
■■ To create file choosers and colour choosers
■■ To create message dialogs, confirm dialogs, option dialogs and input dialogs
■■ To design course registration form using JFrames
16.1 Introduction
In Chapter 15, the readers were introduced to the art of developing graphics applications and the class
hierarchy for Swing Components and Containers. To just recall, an instance of a component can be
displayed on the screen and similarly an instance of a container will hold an instance of a component.
The readers have learnt how to use the instances of containers such as JApplet, JFrame and JPanel.
Though you have come across some of the components such as JButton, JLabel and others, you
never had an opportunity to develop applications utilizing swing components so far. In this chapter,
you will be exposed to all interesting swing components with which you can development efficient
GUI applications using JFrame. Chapter 17 focuses on GUI development using JApplet. One final
thought, you might also wonder whether it is possible to automatically generate GUI forms by drag-
ging and dropping very similar to .NET framework. Though Java GUI API needs simple hard coding
of components, you might also leverage automatic GUI builders (aka, IDE) for Java such as Eclipse
and NetBeans, especially if your GUI becomes very large.
public ClassName()
{
// instantiate all components
Creating a label in swing will be very simple. Just you need to instantiate JLabel class with the
required text as an argument. Labels can also be created with an image as an argument. The setText()
assigns the given text to label at runtime. You can also create a border to label with setBorder()
method for which you need to create a border first and assign it to label. Remember all swing borders
are available in swing.border package that should be first imported.
Buttons are created in swing using JButton class. Similar to JLabel you should instantiate it with
a text so that you can push the button. Just as JLabel you can instantiate a button with an image. The
setMnemonic() allows you to set a keyboard character for button so that you can select it along with
Alt key. The setToolTipText() sets a text to button that will be displayed when mouse is hovered on it.
When you create a button with an image and text, setHorizontalAlignment() and setVerticalAlign-
ment() methods can be used to align the image and text horizontally or vertically. In the same way,
setHorizontalTextPosition() and setVerticalTextPosition() methods control the position of the text with
respect to the image. Listing 16.1 explains to us how to create a label and button in swing.
// Buttons.java
import javax.swing.*;
import java.awt.*;
public Buttons()
{
// instantiate components
Label can be aligned to frame with the static constants LEFT, RIGHT or CENTER. When a label
is created with an image some more alignments such as BOTTOM, TOP, etc. can be specified. The
swing components are added to frame according to the specified layout. Here we use the default lay-
out of frame which is BorderLayout. We add label to north and button to south. Remember there are
two ways for adding components – with constants such as NORTH and string such as “South”. You
will learn further details of various layouts and their applications in section 16.5. The main() simply
instantiates the frame and sets frame properties such as title, size, closing and visibility.
When you run this application you might see how the label and button are placed in north and
south of the frame. However when you press the button or press Alt-b you will observe the frame is
not closing. That is the button does not recognize the action of the user, the button press using mouse
or keyboard key. In Java terminology, these actions are called events and the program should handle
these events. This process is refered to as event handling, which is discussed in section 16.4.
// ClockLabel.java
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.util.*;
try
{
Thread.sleep(1000);
}
catch(InterruptedException e) {
System.out.println(“Clock Interrupted..”);
}
}
}
}
// Buttons2.java
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
{
// create components
JLabel lblLogin;
JButton btnExit;
public Buttons2()
{
// instantiate components
lblLogin = new JLabel(“Login Frame”, JLabel.CENTER);
btnExit = new JButton(“Exit”);
f.setVisible(true);
}
}
The JLabel does not define any events and we are of course not interested in it. The major update
of this program from the earlier one is the final part of the constructor. For each event of the compo-
nents we are interested in, we should register listener with an instance of an implementation class for
the ActionListener interface. The implementation class must be defined as an inner class. So there
will be as many inner classes as that of components. Also you must remember, all listeners should be
registered at the end of the constructor as a last statement.
The BtnExitL inner class simply implements ActionListener and overriddes actionPerformed()
method. The System.exit() simply closes the frame. This is in addition to setDefaultCloseOperation
(JFrame.EXIT_ON_CLOSE) method that will close the window by its window closing button. The
Java 1.1 event handling is an elegant way of handling events. Here the user interface is clearly sepa-
rated from its implementation. The implementations of user interface components are defined as inner
classes effectively supporting excellent object-oriented design. We need not bother about the number
of components, the inner classes scale up very well. You will learn more about different types of
events that are generated by components and how to handle them in section 16.6.
16.5.1 FlowLayout
The FlowLayout is the simplest of all layouts where components are placed left to right in the order
they appear. When the end of line is reached, the flowing continues in the next line. By default,
FlowLayout aligns each component to FlowLayout.CENTER. However you can also align compo-
nents to LEFT as well as to RIGHT. Also the space between two components is 5 pixels horizontally
and vertically by default. But you can customize as you wish when you instantiate FlowLayout. All
components are compacted according to their size. Figure 16.2 illustrates the creation of flow layout.
FlowLayout()
FlowLayout(FlowLayout.LEFT)
FlowLayout(FlowLayout.RIGHT, 10, 20) // hspace = 10, vspace = 20
pixels
Now let us create a frame that will display a label and button using flow layout as depicted in
Listing 16.4.
// FlowLayout1.java
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public FlowLayout1()
{
// instantiate components
lblLogin = new JLabel(“Login Frame”, JLabel.CENTER);
btnExit = new JButton(“Exit”);
add(lblLogin);
add(btnExit);
Here you can set mnemonic for button so that button can also be clicked with keyboard keys apart
from mouse clicks. Further, text for toop tip defines a popup text when mouse is hovered on the button.
We will now play with an application shown in Listing 16.5 where let us try different constructors
of flow layout. This program displays series of buttons with different alignments such as left, right and
centre apart from horizontal and vertical gaps between buttons.
// FlowButtons.java
import javax.swing.*;
import java.awt.*;
In this program, apart from alignments of button components, you might observe gaps between
two components in which 10 and 20 indicate horizontal and vertical gaps between buttons. Though
flow layout appears to be very simple, it will not be always suitable when components are arranged
unevenly. Readers are advised to manually resize the frame and appreciate how flow layout changes
the position of components. This is possible only with flow layout, but not with other layout m
anagers.
16.5.2 BorderLayout
BorderLayout manager adds components in five regions: NORTH, SOUTH, EAST, WEST and CEN-
TER. If you do not specify the region to which a component is to be placed, then by default it will be
placed in the centre. Also a component placed in the centre region will occupy neighboring regions
if that region does not contain any component. So it is always necessary that you add component to
centre only after adding components to all other regions. By default, frame uses border layout. Some
examples of creating border layout is shown in Figure 16.3.
BorderLayout()
BorderLayout(10,20) // use this constructor if you initialize
hspace and vspace
We will now place 5 buttons inside all 5 regions of the frame using borderlayout as depicted in
Listing 16.6.
// BorderLayout1.java
import javax.swing.*;
import java.awt.*;
}
public static void main(String[] args)
{
BorderLayout1 f = new BorderLayout1();
// frame properties
f.setTitle(“Buttons using BorderLayout”);
f.setSize(300,200);
f.setLocationRelativeTo(null); // centres to screen
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // closes
frame
f.setVisible(true);
}
}
If you do not have a component to be placed in east or west, do not worry, the centre component
will occupy those regions and the GUI will look cleaner too.
16.5.3 GridLayout
The GridLayout manager adds components to frame in a matrix (grid) format. The components are
added left to right, top to bottom in the order in which they are added using add() method. You need
to specify the values for rows and columns for the grid. Figure 16.4 illustrates the grid layout.
GridLayout(row, col)
GridLayout(col) // rows are determined automatically during
runtime
GridLayout(row) // cols are determined automatically during
runtime
GridLayout(row, col, hspace, vspace)
Now let us add buttons to frame using gridlayout as depicted in Listing 16.7.
// GridLayout1.java
import javax.swing.*;
import java.awt.*;
The above application creates a grid layout of two rows and four columns and eight buttons are
added to frame according to grid layout. GridLayout manager is another interesting layout manager
besides BorderLayout.
// Buttons3.java
import javax.swing.*;
import java.awt.*;
public Buttons3()
{
add(lblLogin, BorderLayout.NORTH);
// add buttons to south
JPanel p = new JPanel(); // by default, flow layout
p.add(btnCancel);
p.add(btnExit);
add(“South”, p);
}
public static void main(String[] args)
{
Buttons3 f = new Buttons3();
// frame properties
f.setTitle(“Buttons inside panel”);
f.setSize(300,200);
f.setLocationRelativeTo(null); // centres to screen
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // closes
frame
f.setVisible(true);
}
}
By default, JPanel uses flow layout and centre alignment. So buttons are added one after another
and the panel is added to the south of the frame. The setLayout() helps us to specify the required lay-
out for the panel. You might also observe how panel preserves the size of the components and sizes
are different according to the text of the buttons. The JPanel is the extensively used container in swing
because it behaves like a frame and you can do all things whatever you do with frames. Suppose you
have a main frame that consists of 20–30 different modules to be integrated. Then all you will have
to do is to create each module as a JPanel and insert them inside frame. If necessary, integrate panel
into another panel, no worry!
In the program depicted in Listing 16.9, we will display three buttons of different sizes horizontally
and vertically using BoxLayout.
// BoxLayout1.java
import java.awt.*;
import javax.swing.*;
jp = new JPanel();
jp.setLayout(new BoxLayout(jp, BoxLayout.Y_AXIS));
jp.add(new JButton(“Button 1”));
jp.add(new JButton(“2”));
jp.add(new JButton(“Button Three”));
add(“South”, jp);
}
In this program, all three buttons are of different sizes and box layout manager preserves the sizes
of the buttons. If you have added these buttons to grid layout, you will see all buttons are placed in
equal sizes.
The BoxLayout is set to JPanel and all swing components are added to JPanel either horizontally
or vertically. Generally, BoxLayout does not use gaps in between components. If you want to control
spacing between components, you should use Box container that uses in turn BoxLayout as its layout
manager.
Box is another lightweight container that uses internally BoxLayout manager to arrange compo-
nents left to right horizontally using static createHorizontalBox() method or top to bottom vertically
using static createVerticalBox() method. The add() method inserts a component to box. Let us now
create three buttons and store them inside horizontal box and vertical box containers as illustrated in
Listing 16.10.
// Box1.java
import java.awt.*;
import javax.swing.*;
If you want to leave some space in between components, then Box provides three types of fillers
namely strut, glue and rigid area. There are couple of methods to create these fillers with which you
can create gaps. Remember these gaps are also identified as components and so you need to add them
to Box as a normal component.
If you need fixed amount of space (in pixels) in between two components, then you should use
either horizontal strut or vertical strut. The createHorizontalStrut() gives gap between two horizontal
components whereas createVerticalStrut() gives gap between two vertical components. Listing 16.11
explains the application of struts.
// Strut1.java
import java.awt.*;
import javax.swing.*;
Suppose you have fixed-sized components that are to be placed either horizontally or vertically
with gaps that can stretch to the edges of the frame. Then, you should use either horizontal glue (with
createHorizontalGlue() method) or vertical glue (with createVerticalGlue() method) which controls
gaps between components evenly as illustrated in Listing 16.12.
// Glue1.java
import java.awt.*;
import javax.swing.*;
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // closes
frame
f.setVisible(true);
}
}
Here in this program, you will see the gaps between B1, B2 and B3 are stretched equally with
respect to the edges of the frame.
Finally if you need gap both horizontally and vertically between two components, then createRigi-
dArea() gives us gaps horizontally as well as vertically. To create gap component, you will have to instan-
tiate Dimension(w,h) object with necessary pixels for width and height. For instance, Example 16.1
creates rigid area of size 10 by 15 between two buttons.
Corresponding
Name of the Event Listener Interface Components Firing this Event
ActionEvent ActionListener JButton, JTextField,
JMenuItem, JMenu, JPopupMenu
DocumentEvent DocumentListener JTextArea, JTextField
ItemEvent ItemListener JCheckBox, JCheckBoxMenuItem,
JComboBox
ListSelectionEvent ListSelectionListener JList
KeyEvent KeyListener Any component
MouseEvent MouseListener Any component
MouseEvent MouseMotionListener Any component
AdjustmentEvent AdjustmentListener JScrollbar
WindowEvent WindowListener Any subclass of window such as
JFrame, JDialog, JFileDialog
FocusEvent FocusListener Any component
ChangeEvent ChangeListener JSlider, JTabbedPane
HyperlinkEvent HyperlinkListener JEditorPane
Here each component supports only few types of events. Further each listener in Figure 16.6 has a
collection of methods that can be overridden. In Figure 16.7, you will learn all methods that are part
of each listener interfaces.
In Figure 16.7, you might see there are some listeners that have more than one interface methods.
Since your listener object will implement these listener interfaces, overridding more than one method
MouseMotionListener mouseDragged(MouseEvent)
mouseMoved(MouseEvent)
WindowListener windowOpened(WindowEvent)
windowClosed(WindowEvent)
windowClosing(WindowEvent)
windowActivated(WindowEvent)
windowDeactivated(WindowEvent)
windowIconified(WindowEvent)
windowDeiconified(WindowEvent)
FocusListener focusGained(FocusEvent)
focusLost(FocusEvent)
ChangeListener stateChanged(ChangeEvent)
HyperlinkListener hyperlinkUpdate(HyperlinkEvent)
is combersome as we are interested to override only one method and not all methods. To solve this
issue, Java provides Adapter classes with which it is enough to override only the method you are
interested in. Figure 16.8 depicts listeners and its adapter equivalent.
So all you have to do is to just extend an Adapter class and override the respective method you
are interested in to override. For example, let us now override windowClosing() method of Window-
Adapter class in BoxFrame application as shown in Figure 16.9.
// BoxFrame2.java
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
In the above code, as usual, three buttons are added to panel according to box layout. The interest-
ing part in the program is how we handle clicking of close button of the window. The windowClos-
ing() method is overridden by extending WindowAdapter class. Inside the method, we simply call
exit() method.
// ColorLabel.java
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
public ColorLabel()
{
// add clock north
add(“North”, clock);
lblHello.setFont(new Font(“Serif”, Font.BOLD, 36));
// add label to north
add(“Center”, lblHello);
{
public void actionPerformed(ActionEvent e)
{
Random ra = new Random();
int r = ra.nextInt(255);
int g = ra.nextInt(255);
int b = ra.nextInt(255);
lblHello.setForeground(new Color(r,g,b));
}
}
Inside actionPerformed(), three random numbers from 0 to 255 are created representing colour
values for red, green and blue and the label is set with this new colour. The ColorLabel object, being
a thread, displays current time continuously.
// ThrowBall.java
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
The setText() and getText() methods are used to store and retrieve text from textfield. In order to pro-
vide password like behaviors you can use its subclass JPasswordField so that the characters entered
will not be visible and will be echoed with *. With an another interesting subclass JFormattedText-
Field, you can specify a valid set of characters that can be typed in a textfield.
When you press ENTER key while typing, JTextField object fires ActionEvent. Further you can
register TextListener to the textfield so that you can handle the associated TextEvent. Since all com-
ponents fire KeyEvent and also JTextField, you can handle KeyEvent too. Here is an example shown
in Listing 16.15 that receives username in textfield and password in passwordfield. When submit
button is clicked, both username and password details are displayed in the command prompt for
verification.
// LoginFrame.java
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public LoginFrame()
{
// add title to north
add(“North”, lblTitle);
In this program, JPasswordField component echoes a * character for each password character we
type. You can also change this echo character with your own echo character using setEchoChar()
method.
The JTextArea component holds multiline text, and its size is determined by its row and column
values. Similar to JTextField, it supports setText() and getText() methods to store and retrieve its con-
tents. The append() method appends a string to the end of the text. The setEditable() method enables
(by default) or disables editing the text. This is especially useful when you want to treat text area only
as a display device. The setLineWrap() enables wrapping of lines if set to true. The setWrapStyle-
Word() supports wrapping of words if set to true. The JTextArea class does not provide scroll bars
in contrast to awt.TextArea. So if you need scrolling behavior, you need to insert JTextArea inside
JScrollPane component. Now let us create a simple text area as shown in Example 16.3.
// FileLister.java
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
public FileLister()
{
// set properties of ta
ta.setEditable(false);
ta.setFont(new Font(“Courier”, Font.ITALIC, 12));
// register listerners
btnShow.addActionListener(new bselectL());
tf.addActionListener(new tfL());
}
{
showFile();
}
}
class bselectL implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
showFile();
}
}
When a user types file name and presses ShowFile button, the text area is inserted with the contents
of the selected file. Another interesting part of this program is that action listener is also registered for
textfield so that users can also press ENTER key once they type file name in the textfield. You might
feel typing file name is boring. So do not worry, you will be introduced to a UI component that will
allow you to choose file name directly from Windows dialogs in section 16.15. The rest of the source
code is self-explanatory.
// NumericTF.java
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.text.*;
import java.awt.*;
import java.awt.event.*;
public NumericTF()
{
// TextCopyCat.java
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.text.*;
import java.awt.*;
import java.awt.event.*;
public class TextCopyCat extends JFrame
{
JTextField tf1 = new JTextField(30);
JTextField tf2 = new JTextField(30);
public TextCopyCat()
{
Box box = Box.createVerticalBox();
box.add(tf1);
box.add(tf2);
add(box);
tf1.getDocument().addDocumentListener(new TF1L());
}
class TF1L implements DocumentListener
{
public void changedUpdate(DocumentEvent e) { }
public void insertUpdate(DocumentEvent e)
{
tf2.setText(tf1.getText());
}
public void removeUpdate(DocumentEvent e)
{
tf2.setText(tf1.getText());
}
}
public static void main(String[] args)
{
TextCopyCat f = new TextCopyCat();
f.setTitle(“Text CopyCat”);
f.setSize(200,100);
f.setLocationRelativeTo(null);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
}
}
In Listing 16.19, we create a panel that will include three checkboxes and a textfield. Whenever a
checkbox is clicked, the name of the checkbox is displayed in the textfield.
// CheckBox1.java
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
{
JCheckBox cbRuby = new JCheckBox(“Ruby”);
JCheckBox cbJava = new JCheckBox(“Java”);
JCheckBox cbPython = new JCheckBox(“Python”);
JTextField status = new JTextField(20);
public CheckBoxPanel()
{
// set grid layout
setLayout(new GridLayout(2,1));
// add cb to box
Box box = Box.createHorizontalBox();
box.add(cbRuby);
box.add(box.createHorizontalGlue());
box.add(cbJava);
box.add(box.createHorizontalGlue());
box.add(cbPython);
// register listeners
cbRuby.addItemListener(new cbRubyL());
cbJava.addItemListener(new cbJavaL());
cbPython.addItemListener(new cbPythonL());
}
}
}
For each checkbox, we need to register ItemListener and override itemStateChanged() method.
Inside this method, we simply extract the name of the checkbox using getText() method and update
the textfield accordingly. We create a public class and add this checkbox panel to this frame.
To illustrate the functioning of radio buttons, let us now develop an application that will add three
radio buttons in a panel and displays its name onto the textfield of CheckBoxPanel class as explained
in Listing 16.20.
// Radiobutton1.java
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public RadioPanel(CheckBoxPanel p)
{
// receive handle to update cbp
cbp = p;
ButtonGroup bg = new ButtonGroup();
bg.add(rbSlow);
bg.add(rbMedium);
bg.add(rbFast);
// add cb to box
Box box = Box.createVerticalBox();
box.add(rbSlow);
box.add(box.createVerticalGlue());
box.add(rbMedium);
box.add(box.createVerticalGlue());
box.add(rbFast);
// add
setLayout(new BorderLayout());
add(“Center”, box);
// register listeners
rbSlow.addItemListener(new rbSlowL());
rbMedium.addItemListener(new rbMediumL());
rbFast.addItemListener(new rbFastL());
}
// inner class
class rbSlowL implements ItemListener
{
public void itemStateChanged(ItemEvent e)
{
cbp.status.setText(“Radio button ” + rbSlow.getText()
+ “ is clicked”);
}
}
// frame properties
f.setTitle(“RadioButton Demo”);
f.setSize(300,100);
f.setLocationRelativeTo(null); // centres to screen
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // closes
frame
f.setVisible(true);
}
}
In this example, we try to combine the user interface of radiobutton panel with CheckBoxPanel.
We instantiate CheckBoxPanel here and add it to the centre of the frame and radio button panel is
added to the east of the frame.
Let us display a combo box containing information about marital status. The textfield should be
updated with the text of the selected item when a user clicks an item in the combo box as shown in
Listing 16.21.
// ComboBox1.java
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public ComboBox1()
{
// make status non editable
status.setEditable(false);
// add cb to box
Box box = Box.createVerticalBox();
box.add(cb);
box.add(status);
// add them to frame
add(box);
// register listeners
cb.addItemListener(new cbL());
}
The getSelectedItem() returns the name of the selected item from the combo box and is displayed
in the textfield. In the previous example, combo box has been populated with item names while it was
instantiated first. No items were added when the program was running or at runtime. It is also possible
to add an item to combo box at runtime. The addItem() appends an item to combobox at runtime as
shown in Listing 16.22.
// DynamicComboBox.java
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public DynamicComboBox()
{
// make status non editable
status.setEditable(false);
// add cb to box
Box box = Box.createVerticalBox();
box.add(cb);
box.add(item);
box.add(status);
// add them to frame
add(box);
// register listeners
cb.addItemListener(new cbL());
item.addActionListener(new itemL());
}
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // closes
frame
f.setVisible(true);
}
}
In this example, a combo box, textfield and uneditable textfield are added to frame using vertical
box. The combo box was initialized with few items when it was created. Users are allowed to type
item names to combo box in the textfield. Whenever a new item name is entered in the textfield, it
gets appended to combobox immediately. The uneditable textfield behaves as a status which displays
every change in the combo box.
16.13.4 Lists
A list can be created with JList and is another interesting JComponent that is very similar to JCombo-
Box. From JList you can select one item, or multiple items. A list can be initialized using an array or
vector of objects and displayed in one or more columns. The items from list can be selected in three
ways: single click, multiple click (by holding Ctrl-key and clicking) and range click (by holding Shift-
key and clicking).
The JList fires ListSelectionEvent when a single item or multiple items are selected. In order
to process list clicks, ListSelectionListener interface should be implemented by overridding val-
ueChanged() method with the handling behavior you want to include for the selection. The getSe-
lectedValuesList() returns a List containing all selected items from JList. The getValueIsAdjusting()
method from ListSelectionEvent helps us to ignore the same item being added to the list of selected
items because of more than one event being fired. Listing 16.23 demonstrates the functioning of JList.
// List1.java
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.event.*;
import javax.swing.border.*;
import java.util.*;
public List1()
{
lst.setBorder(new TitledBorder(“Courses”));
lst.setForeground(Color.red);
lst.setBackground(Color.white);
Border brd = BorderFactory.createMatteBorder(1, 1, 2, 2,
Color.blue);
status.setBorder(brd);
// make status non editable
status.setEditable(false);
// add cb to box
Box box = Box.createHorizontalBox();
box.add(new JScrollPane(lst));
box.add(new JScrollPane(status));
// add them to frame
add(box);
// register listeners
lst.addListSelectionListener(new lstL());
}
status.setText(status.getText() + it.next());
}
}
The JList is instantiated with an array of string items. The horizontal box contains the list and a text
area. The list is surrounded by title border and the text area by matte border. Both list and text area are
added to scrollpane that will allow us to view their contents with automatically added scrollbars if the
contents do not fit into the components. As JList fires ListSelectionEvent, ListSelectedListener is regis-
tered that will handle list operations such as selecting an item from the list. The getValueIsAdjusting()
returns true if the user is still manipulating the selection. Otherwise, getSelectedValuesList() returns
a util.List instance that is iterated with ListIterator interface and text area updates each selected item.
windows are also classified based on modality. While JDialog is nonmodal, then all standard dialog
windows including JOptionPane, JFileChooser and JColorChooser are modal. In sections 16.15 to
16.17, let us explore these dialog windows with illustrative examples.
The setFileFilter() allows us to set FileFilter so that the file chooser will display only files based
on the selected type and restricts unwanted files from appearing in the directory listing. The FileNa-
meExtensionFilter is a subclass of FileFilter that will restrict files based on the list of file extensions
given as arguments. For example, Figure 16.14 explains filtering all files with extension “.java” and
“.class” from the current directory.
The JFileChooser by default displays only files in the current directory. But setFileSelectionMode(int)
method can be used to set file modes to directories as well as files and directories where int value 0, 1
or 2 indicate its file only, directory only or both types. Now in Listing 16.24, we will develop a GUI
that will receive a file name from JFileChooser and display its name and directory in a textfield. The
JFileChooser has been designed for both open and save mode.
Listing 16.24. Selecting File Names for Open and Save Modes
// FileChooser.java
import javax.swing.*;
import javax.swing.filechooser.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
public FileChooser()
{
Box box = Box.createVerticalBox();
box.add(box1);
box.add(box11);
// third row
Box box2 = Box.createHorizontalBox();
box2.add(cbMode);
box2.add(btnOpen);
box2.add(btnSave);
box2.add(btnExit);
box.add(box2);
add(box);
{
// create file chooser
JFileChooser fc = new JFileChooser();
// set filter
fc.setFileFilter(new FileNameExtensionFilter(“Saving
files”, extn));
// show both files and directories
fc.setFileSelectionMode(2);
int val = fc.showSaveDialog(FileChooser.this); //
show it in this class
// check if file name selected and display
if(val == JFileChooser.APPROVE_OPTION)
{
// display selected file
tfFile.setText(fc.getSelectedFile().getName());
// display current directory
tfDir.setText(fc.getCurrentDirectory().
toString());
}
// you can also check for APPROVE_CANCEL option
}
}
This application is yet another classic example of box layout manager. The user interface is divided
into three rows. In the first row and second row, a label and textfield are added. The third row contains
a combo box and three buttons. The combo box has been populated with five file extensions such as
.java, .txt and others.
On clicking Open button, showOpenDialog() of FileChooser displays files and directories for user
selection for open mode. The showOpenDialog() returns a value and you can check whether this value
is same as JFileChooser.APPROVE_OPTION. If it is the same, then a file name is selected by user.
Therefore file name and directory name are displayed in the respective textfields.
Similarly showSaveDialog() displays a dialog box so that users can choose a file name for writing.
Once users select a file name, it will be displayed in the textfield along with its path name in another
textfield.
// ColorChooser.java
import javax.swing.*;
import javax.swing.colorchooser.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.*;
public ColorChooser()
{
lblTitle.setFont(new Font(“Serif”, Font.BOLD, 48));
add(“Center”, lblTitle);
add(“South”, btnPaint);
btnPaint.addActionListener(new PaintL());
}
Here, the showDialog() displays a colour chooser dialog box inside the parent container with a title
and initial colour and returns the selected Color object. The setForeground() sets the selected colour
of the label.
Unusually, you can also display JColorChooser object inside a frame like displaying other swing
components. In this case, you will have to handle the event associated with colour selection. The
J ColorChooser object fires ChangeEvent and so your class can also implement ChangeListener and
override stateChanged() method. As JColorChooser is a type of dialog, it also fires ActionEvent. The
getColor() returns a Color object as the user selects a colour. Here is an example depicted in Listing 16.26
that displays JColorChooser palette.
// ColorChooser2.java
import javax.swing.*;
import javax.swing.colorchooser.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.*;
public ColorChooser2()
{
lblTitle.setFont(new Font(“Serif”, Font.BOLD, 48));
add(“North”, lblTitle);
JPanel p = new JPanel();
p.add(cc);
add(“Center”, p);
cc.getSelectionModel().addChangeListener(new CCL());
}
f.setLocationRelativeTo(null);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
}
}
In this example, the default selection model is obtained via getSelectionModel() method as is
needed to register ChangeListener for JColorChooser.
Syntax:
JOptionPane.showMessageDialog(jframe, mesg, title, icon);
Example:
JOptionPane.showMessageDialog(jframe, “Data Submitted”,
“Submission Info”, JOptionPane.INFORMATION_MESSAGE);
Syntax:
Where
ÁÁ button can be any of YES_NO_OPTION, YES_NO_CANCEL_OPTION,
OK_CANCEL_OPTION and DEFAULT_OPTION
ÁÁ option_mesgs is an array of objects for button titles
ÁÁ intial_option represents the default selection of a button and
ÁÁ icon represents message icons as defined in message dialogs
Example:
Example:
Object[] drinks = {“Red wine”, “White wine”, “Beer”, “Coke”,
“Spring water”};
JOptionPane.showInputDialog(jframe, “Chicken and ham with”,
“Select drinks”, JOptionPane.PLAIN_MESSAGE, null, options,
options[2]);
Example:
JOptionPane.showInputDialog(jframe, “Chicken and ham with”, “Type
drinks”, JOptionPane.PLAIN_MESSAGE, null, null, null);
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.filechooser.*;
import javax.swing.border.*;
import java.io.*;
//define TF and TA
JTextField tfFname = new JTextField(30);
JTextField tfMobile = new JTextField(30);
//define RBs
ButtonGroup bgSex = new ButtonGroup();
JRadioButton rbMale = new JRadioButton(“Male”);
JRadioButton rbFemale = new JRadioButton(“Female”);
//define CB
JComboBox cbMstatus = new JComboBox();
// define CB
JCheckBox cbRegular = new JCheckBox(“Regular”);
JCheckBox cbFasttrack = new JCheckBox(“Fast Track”);
//define BTNs
JButton btnSubmit = new JButton(“submit”);
JButton btnExit = new JButton(“Exit”);
RegistrationForm()
{
//layout
setLayout(new GridLayout(9, 2));
taAddr.setBorder(new LineBorder(Color.black));
// add components
add(lblFname); add(tfFname);
add(lblAddr); add(taAddr);
add(lblMobile); add(tfMobile);
add(lblDOB); add(tfDOB);
add(lblSex);
bgSex.add(rbMale);
bgSex.add(rbFemale);
JPanel p = new JPanel();
p.add(rbMale);
p.add(rbFemale);
add(p);
add(lblMstatus);
cbMstatus.addItem(“Single”);
cbMstatus.addItem(“Married”);
add(cbMstatus);
add(lblCourse);
lmodel.addElement(“HTML”);
lmodel.addElement(“Java”);
lmodel.addElement(“.NET”);
lmodel.addElement(“PHP”);
lmodel.addElement(“Python”);
lmodel.addElement(“Ruby”);
add(spane);
add(lblTrack);
p = new JPanel();
p.add(cbRegular);
p.add(cbFasttrack);
add(p);
add(btnSubmit);
add(btnExit);
// register listeners
rbMale.addItemListener(new MaleL());
rbFemale.addItemListener(new FemaleL());
cbMstatus.addItemListener(new MstatusL());
lstCourse.addListSelectionListener(new CourseL());
cbRegular.addItemListener(new RegularL());
cbFasttrack.addItemListener(new FasttrackL());
btnSubmit.addActionListener(new SubmitL());
btnExit.addActionListener(new ExitL());
}
String sex;
class MaleL implements ItemListener
{
public void itemStateChanged(ItemEvent e)
{
sex = (String)rbMale.getText();
}
}
{
sex = (String)rbFemale.getText();
}
}
String mstatus;
class MstatusL implements ItemListener
{
public void itemStateChanged(ItemEvent e)
{
mstatus = (String)cbMstatus.getSelectedItem();
}
}
String course;
class CourseL implements ListSelectionListener
{
public void valueChanged(ListSelectionEvent e)
{
course = (String)lstCourse.getSelectedValue();
}
}
String track;
class RegularL implements ItemListener
{
public void itemStateChanged(ItemEvent e)
{
track = (String)cbRegular.getText();
}
}
}
}
} catch(IOException e)
{
System.out.println(“File writing error” + e);
}
// show message
JOptionPane.showMessageDialog(RegistrationForm.this,
“Data submitted to file”, “Submission Info”,
JOptionPane.INFORMATION_MESSAGE);
}
This application instantiates all user interface components labels, textfields, text areas, buttons,
radiobuttons, comboboxes, lists and checkboxes. Some components are directly instantiated during
declaration phase itself such as labels, buttons, textfields and text areas. Some components are popu-
lated inside constructor such as lists and combo boxes using addElement() and addItem() methods.
The JList is created with a DefaultListModel and is added inside scroll pane. Event Listeners are
registered for radiobuttons, comboboxes, checkboxes, lists and buttons and appropriate inner classes
define behaviour for these components. When Submit button is clicked, a FileChooser selects a file
name from user and all updated values from these components are stored in a text file using println()
of PrintWriter object. A confirmation message is also given to users by way of information box that
displays a message Data submitted to file with a OK button.
// EditorPane.java
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.filechooser.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
public EditorPane()
{
// editor pane properties
ep.setEditable(false);
ep.setForeground(Color.magenta);
ep.setBackground(Color.yellow);
ep.setBorder(new BevelBorder(BevelBorder.LOWERED));
// add ep to panel
JPanel p = new JPanel();
p.setLayout(new BorderLayout());
p.add(“Center”, ep);
JPanel p2 = new JPanel();
p2.add(btnShow);
p.add(“South”, p2);
// editor pane2 properties
ep2.setEditable(false);
ep2.setForeground(Color.blue);
ep2.setBackground(Color.green);
ep2.setBorder(new BevelBorder(BevelBorder.LOWERED));
// add ep2 to pane
JPanel p1 = new JPanel();
p1.setLayout(new BorderLayout());
p1.add(“Center”, ep2);
p2 = new JPanel();
p2.add(btnShow2);
p1.add(“South”, p2);
// add p and p2 to frame
setLayout(new GridLayout(1,2));
add(p);
add(p1);
btnShow.addActionListener(new ShowL());
btnShow2.addActionListener(new Show2L());
}
if(val == JFileChooser.APPROVE_OPTION)
fileName = fc.getSelectedFile().getName();
// set URL
try
{
ep.read(new FileReader(fileName), null);
}catch(IOException e1) { }
}
}
The JEditorPane has two interesting methods. The read() displays the source file in its display area.
The setPage() sets a URL of a page. If URL of the page is html then the output of the html file will be
rendered in the display area. From the absolute path name, you can construct a file url by appending
file:\\ before the path name.
Though JTextPane extends JEditorPane, it can display images directly using insertIcon() method.
Here is an example depicted in Listing 16.29 that will display an image in its display area.
// ImageTextPane.java
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.filechooser.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
if(val == JFileChooser.APPROVE_OPTION)
{
File file = fc.getSelectedFile();
Icon icon = new ImageIcon(file.
getAbsolutePath());
textPane.insertIcon(icon);
}
}
}
public static void main(String[] args) throws Exception
{
ImageTextPane f = new ImageTextPane();
// frame properties
f.setTitle(“TextPane Image”);
f.setSize(400,400);
f.setLocationRelativeTo(null); // centres to screen
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
}
}
Here initially the absolute path of the image is selected from file chooser and image icon is created
with this path name. The insertIcon() inserts this image icon into the text pane.
// TemperatureSlider.java
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.filechooser.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
public TemperatureSlider()
{
// cs properties
cs.setMajorTickSpacing(5);
cs.setMaximum(60);
cs.setMinorTickSpacing(1);
cs.setOrientation(JSlider.VERTICAL);
cs.setPaintLabels(true);
cs.setPaintTicks(true);
cs.setValue(0);
// fs properties
fs.setMajorTickSpacing(5);
fs.setMaximum(150);
fs.setMinorTickSpacing(1);
fs.setOrientation(JSlider.VERTICAL);
fs.setPaintLabels(true);
fs.setPaintTicks(true);
fs.setValue(0);
// add components
Box box = Box.createHorizontalBox();
box.add(cs);
box.add(box.createHorizontalGlue());
box.add(fs);
add(“Center”, box);
// register listeners
cs.addChangeListener(new CSL());
fs.addChangeListener(new FSL());
}
The centigrade slider represents values from 0 to 60 with major ticks 5 and minor ticks 1. The
paint labels (i.e. 0, 5, 10, etc.) and paint ticks (small and larger hyphens) are made visible and slid-
ers are displayed vertically. Here, to save space, they are rotated (manually) so that they appear
horizontally. The ChangeListeners are registered for each slider. When a slider is adjusted, it fires
ChangeEvent and the associated Listener gets executed. Inside stateChanged() method, the sliders
value representing a temperature gets converted to the other temperature. For example, Centigrade
slider’s value is converted to Fahrenheit value and the Fahrenheit slider is set with this value.
Similarly, Fahrenheit slider’s value gets converted to centigrade value and the centigrade slider is
set with this value. You can adjust any slider and the other slider will move automatically to the
correct value.
// TabbedPane.java
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.event.*;
import java.awt.*;
public TabbedPane()
{
// add buttons as tabs
for(int i = 0; i < tabs.length; i++)
tpane.addTab(tabs[i], new JButton(“Tab ” + i));
add(tpane);
add(“South”, tf);
tpane.addChangeListener(new TPL());
}
Here, initially a string array defines a set of tabs. Inside constructor, addTab() method adds a string
representing a tab and associates a button for this tab. The ChangeListener handles tab selection and
getSelectedIndex() returns the index value of the selected tab.
// TextEditor.java
import javax.swing.*;
import javax.swing.filechooser.*;
import javax.swing.border.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
public TextEditor()
{
// add menu items to menu
mFile.add(miNew);
mFile.add(miOpen);
mFile.add(miSaveas);
mFile.add(miExit);
//add TA and TF
add(lblTitle, “North”);
add(taDisplay, “Center”);
add(tfStatus, “South”);
miSaveas.addActionListener(new SaveasL());
miExit.addActionListener(new ExitL());
}
{
// display selected file
fileName = fc.getSelectedFile().getName();
}
taDisplay.setEditable(true);
// display contents
String s;
try
{
BufferedReader in = new BufferedReader(
new FileReader(fileName));
while ((s = in.readLine()) != null)
taDisplay.setText(taDisplay.getText() + s +
“\n”);
// close stream
in.close();
}catch (IOException e1) { }
// show status
tfStatus.setText(fileName + “ loaded”);
}
}
f.setLocationRelativeTo(null);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
}
}
In this application, there are four menus namely File, Edit, Tools and Help. The File menu contains
four menu items namely New, Open, SaveAs and Exit. There is also a large text area where text files
can be displayed and textfield that acts like a status board. Inside constructor, menu items are first
added to menu using add() method. Then menus are added to menubar using the same overloaded
add() method. The setJMenuBar() adds menubar to frame.
The ActionListeners are added to menu items. Initially text area is made uneditable and when New
is selected, it becomes editable so that text can be entered into the text area. When Open is selected, a
FileChooser allows a user to choose a file name and its contents will be displayed inside the text area.
Similarly when a SaveAs is clicked, the current contents of the text area are saved to a file that has
been selected with file chooser. Finally, Exit menu item closes the frame.
You can add table to scroll pane so that you will be able to scroll it with horizontal and vertical scroll
bars. If you want table to be automatically resized to fit into the frame, then setFillsViewportHeight(true)
method will resize table to the size of the frame. In Listing 16.33, grade details of students are dis-
played in JTable.
// MarksTable.java
import javax.swing.*;
import javax.swing.event.*;
import java.util.*;
import java.io.*;
public MarksTable()
{
// adjust data to entire container
table.setFillsViewportHeight(true);
// put tables to scrollpane
JScrollPane pane = new JScrollPane(table);
// add pane to frame
add(pane);
}
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
}
}
Here, two object arrays cols and data define table header and cell values for the table. With these
object arrays, JTable instance is created and added to frame.
The JTable can also be instantiated with util.Vector of values. As table cell values are 2D, a vector
of vector representing rows is needed. Here is a Listing 16.34 that creates two tables, one populated
with objects and the other populated with vector of vectors.
// StudentInfo.java
import javax.swing.*;
import javax.swing.event.*;
import java.util.*;
import java.io.*;
public StudentInfo()
{
// create table1 with object[][]
table1 = new JTable(data, cols);
In this example, object arrays are created initially. Inside constructor, one table is created with
object arrays as in the previous example. Then loadVector() populates vectors with object array val-
ues. In order to populate cell values, you will use vector containing vectors where each vector will
keep a row of cell values. With these two vectors, the second table is created. Then they are added to
scrollpanes and in turn added to frame.
//ColorButton.java
import javax.swing.*;
import java.awt.*;
import javax.swing.border.*;
You can add this ColorButton class into a package you have already created so that it can be
imported by any required class. Now we will create a testing class that will instantiate ColorButton
just like a normal JButton as depicted in the Listing 16.36.
//ColorButtonTest.java
import javax.swing.*;
import java.awt.*;
public ColorButtonTest()
{
JPanel p = new JPanel();
p.add(bSubmit);
p.add(bCancel);
p.add(bExit);
add(“Center”, lbl);
add(“South”, p);
}
public static void main(String[] args)
{
ColorButtonTest f = new ColorButtonTest();
f.setTitle(“Color Button”);
f.setSize(300,200);
f.setLocationRelativeTo(null);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
}
}
In the same way, you can create any new component as you like by deciding the properties you
want your component to support. Since all swing components extend JComponent, you can also
extend JComponent and override all necessary methods.
16.25 Summary
1.JLabel can be aligned left (by default), centre and right
2.JButton fires ActionEvent when it is clicked
3.Layout manager arranges components into the container such as JFrame and JPanel
4.The setLayout() sets the necessary layout for the container
5.FlowLayout places components left to right in the order they added
6.BorderLayout places components in five regions; north, south, east, west and centre
7.GridLayout places components in a matrix format
8.BoxLayout arranges components either horizontally or vertically, preserving the dimension of
the components
9. Box is another lightweight container that uses internally BoxLayout manager to arrange com-
ponents left to right horizontally or top to bottom vertically
10. Box uses three types of fillers – struts, glue and rigid area – to leave space between components
11. JComponents fire various events. In order to handle these events the respective listeners can be
registered using addXXXListener() methods
12. Adapter classes can be used when all listener methods need not be overridden
13. Inner classes are excellent ways of representing listener interfaces and adapter classes
14. DocumentLister can be used to handle whether a character is pressed or erased from textfield or
text area
15. Checkboxes, comboboxes and radiobuttons fire ItemEvent
16. Some of the standard dialog windows are JOptionPane, JFileChooser and JColorChooser
17. JOptionPane is used to create message dialogs, option dialogs, option dialogs and input dialogs
18. Editor pane and its subclass text pane can display text, html files and images
19. Sliders allow us to select a numeric value from a range of values and fire ChangeEvent
20. GUI components can be arranged in a row using tabbed pane
21. Menus allow us to bundle a collection of components
22. JTable displays a grid of values. Values can be given as object array or a vector of objects
23. New components can be created simply by extending GUI components and overriding neces-
sary methods
Key terms
Review questions
Multiple-choice Questions
1. Which layout manager places GUI components in one of five regions: north, south, east, west,
and centre?
a. BoxLayout b. GridLayout
c. BorderLayout d. FlowLayout
import javax.swing.*;
import java.awt.*;
public class Test16 extends JFrame
{
JButton b = new JButton(“Cancel”);
public Test16()
{
add(b, BorderLayout.SOUTH);
add(“North”, b);
}
public static void main(String[] args)
{
Test16 t = new Test16();
t.setSize(100, 200);
t.setVisible(true);
}
}
a. Cancel button is added to only South b. Cancel button is added to only North
c. Cancel button is added to South and North d. No output
10. Which layout manger arranges components left to right in the order they appear?
a. BoxLayout b. GridLayout
c. BorderLayout d. FlowLayout
import javax.swing.*;
import java.awt.*;
public class Test16 extends JFrame
{
public Test16()
{
add(“Center”, new JButton(“2”));
add(“North”, new JButton(“1”));
add(“South”, new JButton(“3”));
}
public static void main(String[] args)
{
Test16 t = new Test16();
t.setSize(100, 200);
t.setVisible(true);
}
}
setLayout(new GridLayout(2,0));
add(new JButton(“1”));
add(new JButton(“2”));
add(new JButton(“3”));
add(new JButton(“4”));
add(new JButton(“5”));
add(new JButton(“6”));
25. How to stretch gaps vertically in between fixed sized components to the edges of the container?
a. createVerticalStrut() b. createVerticalGlue()
c. createVerticalGap() d. None of the above
26. How to stretch gaps horizontally in between fixed sized components to the edges of the
container?
a. createHorizontalStrut() b. createHorizontalGlue()
c. createHorizontalGap() d. None of the above
27. Which method gives gaps horizontally and vertically between two components?
a. createRigidArea() b. createGlue()
c. createStrut() d. createGap()
e. None of the above
Answers
1. c 2. d 3. c 4. b 5. b 6. b 7. a 8. a 9. d 10. d
11. a, c 12. c 13. b 14. c 15. a, b 16. d 17. c 18. a 19. b 20. b
21. b 22. b 23. d 24. c 25. b 26. b 27. a 28. d 29. a, b 30. a
31. b 32. a 33. d 34. b 35. d 36. a 37. d 38. a 39. d 40. c
41. a 42. b 43. e 44. c 45. c 46. b 47. b 48. c
Short-answer Questions
1. What are the three label alignments?
2. Explain FlowLayout with an example.
3. Explain BorderLayout with an example.
4. Explain GridLayout with an example.
Exercises
16.1. Modify Exercise 14.6 to design a GUI-based Login frame by collecting username and pass-
word through text field and password text field.
16.2. [Simple calculator] Collect two integers and an operator from text fields. Create four buttons
representing +, –, * and / operations. Display the result in another text field.
16.3. [Arithmetic calculator] Design full-featured arithmetic calculator with buttons representing
digits from 0 to 9, operators and text field to collect data and display result.
16.4. [Currency Converter] Create two combo boxes representing source and target currencies
(USD, GDP and INR). Create two text fields representing source and target values. Collect
source currency code and a value to be converted to target currency. On clicking Calculate
button, the converted value should appear in target text field.
16.5. Complete TextEditor application with other menu items: cut, copy, paste, find and replace for
Edit menu.
16.6. [GUI calendar] Display calendar for 2013. Use combo box to select month and non-editable
text field to display numbers representing day. Hint: you may need Calendar and Gregorian-
Calendar classes.
16.7. [Tiny Social Networking Tool] Develop a simple Facebook with which you can add a user,
remove him from the list, insert his image, add friend (if he already exists in the list), small
chat window with JtextArea and just imagine other features.
17
GUI Development
Using JApplet
Objectives
■■ To explain applets, its advantages and restrictions
■■ To introduce applet lifecycle methods
■■ To run applets with web browser, appletviewer and command prompt
■■ To use applets as a top-level container
■■ To design GUI forms using applets
■■ To explain applet input parameters: param tag and getParameter()
■■ To display images inside applets using JPanel
■■ To create Timers for repeated firing of ActionEvent
■■ To play audio clips in applets
■■ To create AudioClip object for repeated playing of appets
■■ To handle mouse events
■■ To handle hyperlink events
■■ To build archives using jar tool
■■ To create digital certificates for signing applets
■■ To design a web browser that will download website pages from www
17.1 Introduction
Swing uses three generally useful top-level containers: JFrame, JDialog and JApplet. In Chapter 16,
the readers were introduced to JFrame and JDialog containers. The readers have learnt how to develop
GUI applications using JFrame and to use JDialog to display messages to users. Now the readers will
learn the other top-level container JApplet, available in swing package.
Similar to JFrame, JApplet can also contain content pane, with which you can add any swing
c omponent such as labels, buttons textfields, etc., onto JApplet. Further, it can also include menubar.
Like JFrame, JApplet by default uses BorderLayout. However, you can select any layout manager
as you like with setLayout(). Since JApplet extends awt.applet.Applet, you can also leverage the
functionality of Applet class and other interfaces available in java.applet package.
Apart from being a top-level container, applets are designed as a client side programming tool. An
applet is a small application that can be embedded into another application such as html page. A static
web page will include applets and so you can run applets inside a web browser. Applets can d ownload
web pages, display documents and images and play audio clips. Also applet can communicate with
other applets. In this chapter, the readers will be introduced to all programming tips and tricks of applets.
// HelloApplet.java
import javax.swing.*;
import java.applet.*;
In the above application, we have just created a JLabel and included into init() method using add().
This step is very similar to adding components to JFrame that we discussed in the previous chapter but
with a difference. When developing application using JFrame, you have added all swing components
to the constructor. But with JApplet, you will add all swing components to init() method. Besides
there is also another difference; JApplet does not contain main() method. Therefore, init() will contain
all components that are to be instantiated and all listeners for all the required components. You will
also call setLayout() inside init() to change default BorderLayout and setJMenuBar() to add menubar
to applet. So, now let us get back to running this applet code.
Applets can be executed in any of the three different ways as shown below:
■■ Running applets inside web browser
■■ Running applets using appletviewer
■■ Running applets inside JFrame
The applet tag has several attributes; currently we focus only three important attributes: code,
width and height. With code attribute, you will assign class name where the applet resides, and width
and height represent the size of the JApplet in pixels. With this understanding, let us now create a
HTML file with <applet> tag as depicted in Listing 17.2.
<html>
<head>
<title> MyApplet </title>
</head>
<body>
<applet code=“HelloApplet.class” width=400 height=300></applet>
</body>
</html>
Now, you can run this applet by simply selecting this HTML file with any java enable web browser
and you will see the string displaying Hello Applet ! Here the basic assumption is that both applet class
file and html file are located in the same directory. In order to make applets accessible at www, you will
have to store html file and the class file inside the web server. So when you type url of the html file in any
web browser, web browser sends a request to web server for this html page and web server returns the
corresponding html page back to browser and in turn the browser displays this html page on its window.
// HelloApplet1.java
// <applet code=“HelloApplet1.class” width=400 height=300> </applet>
import javax.swing.*;
import java.applet.*;
Now it is easy to run this applet inside command prompt as below and you will see a separate win-
dow appearing with the string “Hello Applet !” displayed in the center of the window.
javac HelloApplet.java
appletviewer HelloApplet.java
// HelloAppletFrame.java
import javax.swing.*;
import java.awt.*;
import java.applet.*;
public HelloApplet()
{
add(“Center”, lbl);
}
}
f.setSize(400, 300);
f.setLocationRelativeTo(null);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
}
}
In this code, JApplet behaves as a JPanel where a JLabel is added to applet inside the constructor
itselt. Note that init() is not at all used. This is also possible if you want JApplet to function like any
other top-level container. However, if your applet needs to stop, then start again, then stop its execu-
tion, then you should override applet methods such as start(), stop() as illustrated in Listing 17.5.
// HelloAppletFrame2.java
import javax.swing.*;
import java.awt.*;
import java.applet.*;
public HelloApplet2()
{
add(lbl);
}
f.setSize(400, 300);
f.setLocationRelativeTo(null);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
}
}
// LoginApplet.java
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
add(“Center”, p);
Here is the HTML file containing LoginApplet class as shown in Listing 17.7.
<html>
<head>
<title> User Login </title>
</head>
<body>
<applet code=“LoginApplet.class” height=100 width=300>
</applet>
</body>
</html>
// WelcomeApplet.java
import javax.swing.*;
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
The getHSBColor(hue, saturation, brightness) is a static method that is used to mix our own color
with HSB color model, similar to RGB color model. The argument hue indicates hue value from 0.0
to 1.0. The saturation indicates how deep the color should be. With value 1, you can make color to be
so deep and value 1 will take color out of mixure and make it a shade of gray. The brightness defines
obviously the brightness of the color. The color becomes light when brightness value is 1 and very
dark when it is 0. The setOpaque() forces painting the component immediately. Otherwise you may
not see the color effect immediately (Listing 17.9).
<html>
<head>
<title> Welcome Applet </title>
</head>
<body>
<p align=center>
<applet code=“WelcomeApplet.class” width=400 height=300>
<param name=“mesg” value=“Rajkumar !”/>
</applet>
</p>
</body>
</html>
// ImageApplet.java
import javax.swing.*;
import java.awt.*;
import java.io.*;
import java.net.*;
desc = getParameter(“mesg”);
image = getImage(getCodeBase(), getParameter(“picture”));
//url = this.getClass().getResource(getParameter(“pict
ure”));
//image2 = getImage(url);
// add to panel
add(new ImagePanel());
}
//g.drawImage(image2, 0, 0, getWidth(),
getHeight()-50, this);
g.drawString(desc, 100, 300);
}
}
}
Here, ImageApplet.html (Listing 17.11) file transmits three name-value pairs to ImageApplet
class. The parameters are bg, mesg and picture whose values are AAFF55, Lovely Nature Image and
nature.jpg, respectively. Here AAFF55 represents RGB color values in hex for the background color
of the panel. Inside init(), getParameter() method receives these values for the given names. The
getImage() returns Image object by using either the URL of the applet or the URL of the image file.
Once these values are read into applet inside init(), the JPanel will be painted with this color, mes-
sage and image by overriding paintComponent(). Remember this JPanel is added as an inner class
inside applet.
<HTML>
<BODY>
<APPLET code=“ImageApplet.class” width=300 height=325>
<PARAM name=“bg” value=“AAFF55”>
<PARAM name=“mesg” value=“Lovely Nature Image”>
<PARAM name=“picture” value=”nature.jpg”>
</APPLET>
</BODY>
</HTML>
In order to appreciate the power of timer, here is an example that displays counter value 1, 2, 3,
etc., incremented and displayed every second as depicted in Listing 17.12.
// CounterApplet.java
//
<applet code=“CounterApplet.class” height=100 width=300></
applet>
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
add(box);
ActionListener timerL = new TimerL();
//triger timer every 1000 ms
Timer timer = new Timer(1000, timerL);
timer.start();
}
Here, timer fires actionevent every second and the associated ActionListener is executed, display-
ing the current value of the variable i inside the textfield. Also, background color of the text field is
changed every time its actionevent is fired with a random HSV color.
//AudioPlayerApplet.java
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.util.*;
import java.net.*;
// add to panel
JPanel panel = new JPanel();
panel.setLayout(new BorderLayout());
panel.add(“Center”, lblImage);
add(“Center”, panel);
Here, AudioPlayerApplet does two things. It plays a sound clip that is stored in the current d irectory
where the applet resides. It also displays random images that are stored inside a subdirectory images.
The subdirectory images contains the following images.
Inside init() method, play() method of JApplet class plays the sound clip raj_sound.au that is sent
to applet via <param> tag. The loadImages() method downloads all seven images from images subdi-
rectory and images are instantiated as ImageIcons and kept inside an array icon.
The timer object fires ActionEvent every second and the registered action listener TL is called.
Inside actionPerformed() method, the JLabel is painted with a random ImageIcon from icon array
by calling setIcon() method of JLabel class. Note that you will call this applet using appletviewer as
<applet> tag is inserted as a comment statement inside this java file.
// DragApplet.java
//<applet code=“DragApplet” height=400 width=400></applet>
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public Square()
{
// initial position
x = 10; y = 10;
setBackground(Color.LIGHT_GRAY);
if(x1 >= x && x1 < x+25 && y1 >= y && y1 < y+25)
{
offsetX = x1 - x;
offsetY = y1 - y;
}
// Move
x = x1 - offsetX;
y = y1 - offsetY;
repaint();
}
}
}
{
Square panel = new Square();
public void init()
{
add(panel);
}
}
In this application, a small color-filled square of 25 pixels height and width is drawn on JPanel.
Inside the overridden mousePressed(), the coordinate values of mouse click is collected using
getX() and getY() methods, so that the square will be moved to this new location. Similarly, inside
mouseDragged(), a new coordinate value is calculated so that square is moving when mouse is dragged.
Also, it is necessary to repaint JPanel whenever there is an update, which is done with repaint() method.
// WebBrowser.java
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.border.*;
import java.net.URL;
public WebBrowser()
{
JPanel p = new JPanel();
p.setBackground(Color.BLACK);
p.setLayout(new BorderLayout());
p.setBorder(BorderFactory.createLineBorder(Color.BLACK,1));
pane.setEditable(false);
p.add(“Center”, new JScrollPane(pane));
pane.setPage(e.getURL());
}
catch(Exception e1) { }
}
}
}
try
{
String location = tfURL.getText().trim();
if (location.length() == 0)
throw new Exception();
if(location.contains(“html”) || location.
contains(“htm”))
url = WebBrowser.this.getClass().
getResource(location);
System.out.println(url.toString());
}
catch (Exception e1)
{
JOptionPane.showMessageDialog(
WebBrowser.this, “URL Not Exist”);
return;
}
try
{
// show web page
pane.setPage(url);
}
catch(Exception e1) {
JOptionPane.showMessageDialog(
WebBrowser.this, “Unable to set page”);
return;
}
}
}
<html>
<head>
<title>Web Browser using jar </title>
</head>
<body>
<applet code=“WebBrowser.class”
width=500 height=400>
</applet>
</body>
</html>
When the user types any html file available in the current directory in the text field and presses
Go button, the content of the html file will be displayed inside the editor pane. Remember this web
browser applet recognizes only files with .html and .htm extensions. The setPage() method takes the
url of the html file as input and displays its contents. If there is a hyperlink in the html page, then users
can click on the hyperlink so that the clicked file will be displayed. Listing 17.17 and Listing 17.18
depict the input html files (News.html and Sports.html ) that were used to generate the output.
In News.html file, there is a tag <a>. It is called anchor tag that starts with <a> and closes with
</a>. The href attribute defines a html file that should be available in the current directory. The anchor
tag displays a clickable hypertext Click here when it is rendered. When users click on the hyperlink,
html file defined in href attribute (Sports.html) will be downloaded and displayed in the editor pane.
In Sports.html (Listing 17.18), an unordered list (defined using <ul> and </ul> tag) with two list
items (defined using <li> and </li> tag) is created. The <h1> tag is used to define heading. HTML
supports six levels of headings from <h1> to <h6> where <h1> is the biggest in font size. Also,
comment is included inside <!-- and -- > tags in html. One final note for you! There are many other
features that HTML5 supports. However we do not cover them all in this book because they are out-
side the scope of this book. Therefore, readers are advised to refer to other books to learn all those
necessary features.
Here all class files that exist in this current directory are bundled as a jar file with a name file-
name.jar. Please ensure that the curent directory contains only class files that are part of this applet.
Otherwise your jar file will include class files that may be part of other java applets that are not at all
required and will unnecessarily increase its size.
The jar command has many options. You can study these options by typing jar in the command
prompt. The option c creates new archive and f specifies archive file name. The archive that is created
using jar command should be included inside the html file with archive attribute of <applet> tag. For
instance, Listing 17.19 illustrates our earlier WebBrowser.html with the additional archive attribute.
<html>
<head>
<title>Web Browser using jar </title>
</head>
<body>
<applet code=“WebBrowser.class”
archive=“WebBrowser.jar”
width=500 height=400>
</applet>
</body>
</html>
In step1, you create a private–public key with genkey attribute. Your key will have an alias named
myalias and is stored inside a file named mykeystore. The keystore file mykeystore will be created in
the current directory where you typed keytool command. The keytool command will ask you several
details that will be attached to the key as below and you will have to supply those details.
Then in step2, you will create a digital certificate, again with keytool command but with selfcert
attribute. The certificate will be stored in the same keystore file that has been created in step1.
Finally in step3 you will sign your JAR file containing the applet with jarsigner utility where you
will mention keystore name and alias name along with the JAR file name. This will create a hash for
each file in the JAR and sign them with the private key created in step1. These hashes, the public key
and the certificate are added to the META-INF directory of the JAR file alongside the JAR’s manifest.
Assume FilesApplet.jar is your jar filename and it contains three class files:
■■ FilesApplet$OpenL.class
■■ FilesApplet$SaveL.class
■■ FilesApplet.class
Then you can check them with tf attributes of jar, as shown below:
Once a JAR file is signed, its contents cannot be changed. In other words, if you update the java
source file, then you need to compile and create JAR file again and sign it digitally with jarsigner.
Then the client machine can safely download your applet as it is now digitally signed.
To illustrate applet signing, let us create and sign an applet so that it will access local files as
depicted in Listing 17.20. Listing 17.21 depicts the corresponding html file for FilesApplet.java.
// FilesApplet.java
import javax.swing.*;
import javax.swing.filechooser.*;
import javax.swing.border.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;
taDisplay.setBackground(Color.yellow);
add(“Center”, new JScrollPane(taDisplay));
//add listeners
btnOpen.addActionListener(new OpenL());
btnSave.addActionListener(new SaveL());
}
try
{
if(val == JFileChooser.APPROVE_OPTION)
{
FileWriter fw = new FileWriter(
fc.getSelectedFile());
// write to file
taDisplay.write(fw);
fw.close();
}
}
catch (IOException e1) {
taDisplay.setText(e1.toString());
}
}
}
// display contents
URL url = null;
String s;
try
{
if(val == JFileChooser.APPROVE_OPTION)
{
// display selected file
url = fc.getSelectedFile().toURL();
}
// close stream
in.close();
}catch (IOException e1) {
taDisplay.setText(e1.toString());
}
}
}
}
<html>
<head>
<title>Signed Applet</title>
</head>
<body>
<applet
code=“FilesApplet.class”
archive=“FilesApplet.jar”
width=“400”
height=“580”>
Your browser does not support Applets.
</applet>
</body>
</html>
When users click Open button, the file chooser collects a file name from the user and url object is
constructed and openStream() converts url into InputStream so that BufferedReader instance can be
created and readLine() performs line by line reading of the selected file. The concatenated string is
displayed in the text pane.
When users click Save button, they will be asked to choose a file name. A FileWriter stream is
associated for the selected file and write() stores the contents of the text pane onto the stream. This
kind of reading and writing with local disk is possible once the applet is digitally signed. Otherwise,
all unsigned applets will throw java.security.AccessControlException when an attempt is made to
access local files.
// WebBrowserReal.java
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.border.*;
import java.net.*;
pane.setEditable(false);
try
{
// eg: http://www.yahoo.com
String location = tfURL.getText().trim();
if (location.length() == 0)
throw new Exception();
url = new URL(location)
}
catch (Exception e1)
{
JOptionPane.showMessageDialog(
WebBrowserReal.this, “URL Not Exist”);
return;
}
try
{
pane.setPage(url);
}
catch(Exception e1) {
String s = e1.toString();
JOptionPane.showMessageDialog(
WebBrowserReal.this, s);
return;
}
}
}
}
<html>
<head>
<title>Web Browser Real </title>
<html>
<head>
<title>Web Browser Real </title>
</head>
<body>
<applet code=“WebBrowserReal.class”
archive=“WebBrowserReal.jar”
width=500 height=400>
</applet>
</body>
</html>
In this application, when the user types an url http://www.yahoo.com in the text field and presses
Go button, a web page from yahoo.com is displayed.
17.14 Summary
1. An applet is a small application that can be embedded into another application such as html
page
2. Unsigned Applets cannot read or write local files stored in hard disk
3. Applets will be downloaded every time it is running
Key terms
Review questions
Multiple-choice Questions
11. What method applets use to receive strings from html files?
a. getValue() b. getParameter()
c. get() d. None of the above
13. Which method returns URL of the directory which contains an applet?
a. getDirectory() b. getCodeBase()
c. getURL() d. None of the above
Answers
1. a 2. d 3. e 4. a, c 5. e 6. b 7. c 8. d 9. a 10. b
11. b 12. d 13. b 14. c 15. a,b 16. c 17. d 18. a,b 19. c 20. a
21. a 22. c 23. d 24. d 25. a,b 26. c 27. c 28. d
Short-answer Questions
1. What is an applet?
2. How applets differ from an application?
3. Explain applet life cycle.
4. What are the ways of running an applet?
5. Can applet access local files in hard disk?
6. How will you make applets to access local files?
7. Can applet be used just like other containers such as panel and frame?
8. Can you add applet onto JFrame?
9. Explain passing parameter values from HTML file to applet.
10. How will you display images inside applet?
11. How will you play audio clips inside applet?
12. Explain the process of signing an applet.
13. How will you handle HyperlinkEvent?
Exercises
Java Basics
■■ Define the scope of variables
■■ Define the structure of a Java class
■■ Create executable Java applications with a main method
■■ Import other Java packages to make them accessible in your code
Handling Exceptions
■■ Differentiate among checked exceptions, RuntimeExceptions and Errors
■■ Create a try-catch block and determine how exceptions alter normal program flow
■■ Describe what Exceptions are used for in Java
■■ Invoke a method that throws an exception
■■ Recognize common exception classes and categories
AtomicBoolean, 392
A AtomicInteger, 392
abstract, 138 AtomicIntegerArray, 392, 394
abstract class, 131, 207 AtomicLong, 392
abstract method, 207 AtomicLongArray, 392
Abstract Windowing Toolkit, 490 AudioClip, 643
accept(), 417 available(), 421
AccessControlException, 659 awt.event, 543
accessibility, 178
ActionEvent, 543, 559, 592
ActionListener, 543, 559
actionPerformed(), 543 B
addItem(), 581 BigInteger, 96
addTab(), 610 Binary search, 65
AdjustmentEvent, 559 binarySearch(), 342, 344
AdjustmentListener, 559 Blocked, 389
AffineTransform, 530 block-oriented IO, 470
Aggregation, 130, 174, 206 boolean condition, 29
allocate(), 471 BorderLayout, 545, 549
anchor tag, 652 Box, 545, 554
anonymous inner class, 180 boxing, 10
API documentation, 218 BoxLayout, 545, 553
append(), 456, 464 break statement, 44
applet methods, 631 brightness, 639
applet tag, 632 Buffer, 470, 471
appletviewer, 633 BufferedInputStream, 448
Arc2D, 518 BufferedOutputStream, 456
archive attribute, 654 BufferedReader, 15, 448
Archives, 653 BufferedWriter, 456, 458
ArithmeticException, 226 byte streams, 420
array comparison, 334 ByteArrayInputStream, 420, 422, 448
Array index, 79 ByteArrayOutputStream, 423
arraycopy(), 333 ByteBuffer, 471, 474
ArrayIndexOut ofBoundsException, 226
ArrayList, 267
arrays, 61 C
Arrays class, 332 canRead(), 415
asCharBuffer(), 475 canWrite(), 415
asList(), 333 capacity, 298
Assert statement, 45 ChangeEvent, 559, 592, 608
Q
O QuadCurve2D, 514
ObjectInputStream, 431 quadTo(), 523
object-oriented design, 170 Queue interface, 265
object-oriented programming, 4
object-oriented system, 130
ObjectOutputStream, 431 R
objects as arguments, 143 Random, 497
openStream(), 658 Random strings, 394
operator precedence, 9 RandomAccessFile, 467
outer classes, 179 read(), 421, 448
output streams, 415 Reader, 448
OutputStream, 420, 456 readLine(), 427, 452
overriding, 174 readObject(), 431
readUTF(), 427
Rectangle2D, 517
P Recursion, 96
package, 131, 218 recursive function, 97
package statement, 218 red black tree, 317, 323
paintComponent(), 494, 639 red black tree-based implementation, 308
param tag, 638 ReentrantLock, 397
parameterized constructor, 161 references to objects, 254
PipedInputStream, 420, 448 references, 112
PipedOutputStream, 423, 456 Remote Method Invocation, 431
PipedReader, 448, 460 renameTo(), 415
PipedWriter, 456, 460 Resource sharing, 360, 380
play(), 643 rewind(), 473
Polymorphism, 130, 174 rigid area, 555
prime number, 95 rotate(), 344, 525
Primitive data type, 6 run(), 360
print(), 464 Runnable, 377, 389
println(), 464 Running, 389
PrintStream, 456 Running applets, 632
PrintWriter, 456, 464 runtime errors, 223
PriorityBlockingQueue, 390 runtime overriding, 130
PriorityQueue, 265 runtime stack, 99
private, 136 runtime type identification, 130, 174
private class, 131 RuntimeException, 227
process, 360
Properties class, 306
property file, 306 S
protected, 136, 174 sandbox, 631
protected class, 131 saturation, 639
public, 136 scale(), 525