Download javafundamentals-tutorial-fromhome

Document related concepts
no text concepts found
Transcript
Getting started
1) GETTING STARTED
THE JAVA TECHNOLOGY PHENOMENON
THE JAVA PROGRAMMING LANGUAGE

The Java programming language is a high-level language that can be characterized by all
of the following buzzwords:




Architecture neutral
Portable
High performance
Robust

Secure





Simple
Object oriented
Distributed
Multithreaded
Dynamic

In the Java programming language, all source code is first written in plain text files
ending with the .java extension. Those source files are then compiled into .class files
by the javac compiler. A .class file does not contain code that is native to your
processor; it instead contains bytecodes — the machine language of the Java Virtual
Machine1 (Java VM). The java launcher tool then runs your application with an
instance of the Java Virtual Machine.
ABOUT THE JAVA TECHNOLOGY


The Java platform differs from most other platforms in that it's a software-only platform
that runs on top of other hardware-based platforms.
The Java platform has two components:
o The Java Virtual Machine
o The Java Application Programming Interface (API)
1
Getting started

The API is a large collection of ready-made software components that provide many
useful capabilities. It is grouped into libraries of related classes and interfaces; these
libraries are known as packages.
 As a platform-independent environment, the Java platform can be a bit slower than
native code. However, advances in compiler and virtual machine technologies are
bringing performance close to that of native code without threatening portability.
Interview questions:
THE "HELLO WORLD!" APPLICATION
A CLOSER LOOK AT THE "HELLO WORLD!" APPLICATION

The "Hello World!" application consists of three primary components: source code
comments, the HelloWorldApp class definition, and the main method. The following
explanation will provide you with a basic understanding of the code, but the deeper
implications will only become apparent after you've finished reading the rest of the
tutorial.
SOURCE CODE COMMENTS

Comments are ignored by the compiler but are useful to other programmers. The Java
programming language supports three kinds of comments:
1. /* text */ : The compiler ignores everything from /* to */.
2. /** documentation */
This indicates a documentation comment (doc comment, for short). The compiler ignores
this kind of comment, just like it ignores comments that use /* and */. Thejavadoc tool uses
doc comments when preparing automatically generated documentation. For more
information on javadoc, see the Javadoc™ tool documentation .
3. // text : The compiler ignores everything from // to the end of the line.
CLASS DEFINITION

The most basic form of a class definition is:
2
Getting started
class name {
...
}
The keyword class begins the class definition for a class named name, and the code for each
class appears between the opening and closing curly braces marked in bold above.
MAIN METHOD
public static void main(String[] args)

The main method accepts a single argument: an array of elements of type String.
 This is how the runtime system passes information to an application.
 Each string in the array is called a command-line argument.
 Using these arguments we can affect the operation of the application without
recompiling it. For example, you can specify your current location for a weather program
to determine the weather in your area.
OBJECTS
Bundling code into individual software objects provides a number of benefits, including:




Modularity: The source code for an object can be written and maintained
independently of the source code for other objects. Once created, an object can be
easily passed around inside the system.
Information-hiding: By interacting only with an object's methods, the details of its
internal implementation remain hidden from the outside world.
Code re-use: If an object already exists (perhaps written by another software
developer), you can use that object in your program. This allows specialists to
implement/test/debug complex, task-specific objects, which you can then trust to
run in your own code.
Pluggability and debugging ease: If a particular object turns out to be problematic,
you can simply remove it from your application and plug in a different object as its
replacement. This is analogous to fixing mechanical problems in the real world. If a
bolt breaks, you replace it, not the entire machine.
INTERFACES
Implementing an interface allows a class to become more formal about the behaviour it
promises to provide. Interfaces form a contract between the class and the outside world,
and this contract is enforced at build time by the compiler. If your class claims to implement
3
Learning the Java Language- (25 APR -01 MAY - CODE)
an interface, all methods defined by that interface must appear in its source code before the
class will successfully compile.
2) LEARNING THE JAVA LANGUAGE- (25 APR -01 MAY - CODE)
OBJECT-ORIENTED PROGRAMMING CONCEPTS
OBJECT







An object is a software bundle of related state and behavior. Software objects are often
used to model the real-world objects that you find in everyday life.
Objects have state and behavior.
An object stores its state in fields (variables in some programming languages) and
exposes its behaviour through methods (functions in some programming languages).
Methods are operations on the internal state of an object.
They serve as the primary mechanism for object-to-object communication.
A fundamental principle of object-oriented programming is data encapsulation. We hide
the internal state and require all interaction to be performed through an object's
methods.
Using objects provides a number of benefits, including:
o Modularity: We can write the source code of each object independent of each
other. Once created, an object can be easily used inside the system.
o Information-hiding: An object can interact with other objects and the system
around it through its objects. This hides the implementation details from those
that don’t need to see or know about it.
o Code re-use: A major advantage of using objects is the ability to re-use
functionality that already exists rather than re-inventing the wheel. This allows
developers to work in their area of specialisation. It also means developers can
focus on functionality that really matter. For example: The java API provides
functionality that is tried and tested for handling files on the computer system.
Developers can use this logic rather than write their own.
o Pluggability and debugging ease: If a particular object turns out to be
problematic, you can simply remove it from your application and plug in a
different object as its replacement. This is analogous to fixing mechanical
problems in the real world. If a bolt breaks, you replace it, not the entire
machine.
CLASS

A class is the blueprint from which individual objects are created.
4
Learning the Java Language- (25 APR -01 MAY - CODE)
INTERFACE

A user or business can define a set of functionality they require. This can be represented
programmatically as an interface.
The interface forms a contract between what the class does and the outside world that
expects certain behaviour/functionality. This is enforced at build time by the compiler.
Programmers can write classes that actually deliver that functionality. These classes are
said to implement the interface.
If a class claims to implement an interface, then it must have an implementation of all
the methods the interface defines. If the class doesn’t implement these methods then
java will prevent your application from compiling successfully.
Implementing an interface allows a class to become more formal about the behaviour it
promises to provide.
In its most common form, an interface is a group of related methods with empty bodies.





Example:
syntax
interface Bicycle {
// wheel revolutions per minute
void changeCadence(int newValue);
void changeGear(int newValue);
}
class ACMEBicycle implements Bicycle {
int cadence = 0;
int speed = 0;
int gear = 1;
/* The compiler will now require that methods changeCadence, changeGear, all be
implemented. Compilation will fail if those methods are missing from this class.*/
void changeCadence(int newValue) {
cadence = newValue;
}
void changeGear(int newValue) {
5
Learning the Java Language- (25 APR -01 MAY - CODE)
gear = newValue;
}
PACKAGE

This is a namespace that holds related classes and interfaces similar to a folder on the
computer.
LANGUAGE BASICS
VARIABLES

Instance Variables (Non-Static Fields) Non-static fields are also known as instance
variables because their values are unique to each instance/object of a class. For
example: the current Speed of one bicycle is independent from current Speed of
another.

Class Variables (Static Fields) A class variable is any field declared with
the static modifier; this tells the compiler that there is exactly one copy of this variable
in existence, regardless of how many objects of the class there are. For example the
number of gears for a particular kind of bicycle could be marked as static since
conceptually the same number of gears will apply to all instances. Additionally, the
keyword final could be added to indicate that the number of gears will never change.

Local Variables Similar to how an object stores its state in fields, a method will often
store its temporary state in local variables. Local variables are only visible to the
methods in which they are declared; they are not accessible from the rest of the class.

Parameters: The values that are passed to a method are called actual arguments in the
Java specification. However, it is very common for them to be called
just arguments, actual parameters, or just plain parameters. These terms are so used
interchangeably so often that even the Java specification isn't entirely consistent.
These actual arguments are inside parentheses following the method name. Use
commas to separate arguments if there is more than one.
Before a method is called, the arguments are evaluated left-to-right.
Syntax



public static void main(String[] args) {
}
6
Learning the Java Language- (25 APR -01 MAY - CODE)



If we are talking about "fields in general" (excluding local variables and parameters), we
may simply say "fields". If the discussion applies to "all of the above", we may simply say
"variables".
You may also occasionally see the term "member" used as well. A type's fields, methods,
and nested types are collectively called its members.
Naming:
o Variable names are case-sensitive.
o A variable's name can be any legal identifier — an unlimited-length sequence of
Unicode letters and digits, beginning with a letter, the dollar sign "$", or the
underscore character "_". The convention, however, is to always begin your
variable names with a letter, not "$" or "_".
o Subsequent characters may be letters, digits, dollar signs, or underscore
characters. Conventions (and common sense) apply to this rule as well. When
choosing a name for your variables, use full words instead of cryptic
abbreviations. Doing so will make your code easier to read and understand.
o Keep in mind that the name you choose must not be a keyword or reserved
word.
o If the name you choose consists of only one word, spell that word in all
lowercase letters. If it consists of more than one word, capitalize the first letter
of each subsequent word.
o If your variable stores a constant value, such as static final int NUM_GEARS = 6,
the convention changes slightly, capitalizing every letter and separating
subsequent words with the underscore character.
PRIMITIVE DATA TYPES




The Java programming language is statically-typed, which means that all variables must
first be declared before they can be used. This involves stating the variable's type and
name, as you've already seen: int gear = 1;
Doing so tells your program that a field named "gear" exists, holds numerical data, and
has an initial value of "1".
A primitive type is predefined by the language and is named by a reserved keyword.
The eight primitive data types supported by the Java programming language are:
o byte: The byte data type is an 8-bit signed two's complement integer. It has a
minimum value of -128 and a maximum value of 127 (inclusive). The byte data
type can be useful for saving memory in large arrays, where the memory savings
actually matters.
o short: The short data type is a 16-bit signed two's complement integer. It has a
minimum value of -32,768 and a maximum value of 32,767 (inclusive). As
with byte, the same guidelines apply: you can use a short to save memory in
large arrays, in situations where the memory savings actually matters.
7
Learning the Java Language- (25 APR -01 MAY - CODE)
o int: By default, the int data type is a 32-bit signed two's complement integer,
which has a minimum value of -231 and a maximum value of 231-1. In Java SE 8
and later, you can use theint data type to represent an unsigned 32-bit integer,
which has a minimum value of 0 and a maximum value of 232-1. Use the Integer
class to use int data type as an unsigned integer.
o long: The long data type is a 64-bit two's complement integer. The signed long
has a minimum value of -263 and a maximum value of 263-1. In Java SE 8 and later,
you can use the long data type to represent an unsigned 64-bit long, which has a
minimum value of 0 and a maximum value of 264-1. Use this data type when you
need a range of values wider than those provided by int.
o float: The float data type is a single-precision 32-bit IEEE 754 floating point. Its
range of values is beyond the scope of this discussion, but is specified in
the Floating-Point Types, Formats, and Values section of the Java Language
Specification. As with the recommendations for byte andshort, use
a float (instead of double) if you need to save memory in large arrays of floating
point numbers.
o double: The double data type is a double-precision 64-bit IEEE 754 floating point.
Its range of values is beyond the scope of this discussion, but is specified in
the Floating-Point Types, Formats, and Values section of the Java Language
Specification. For decimal values, this data type is generally the default choice.
o boolean: The boolean data type has only two possible values: true and false. Use
this data type for simple flags that track true/false conditions. This data type
represents one bit of information, but its "size" isn't something that's precisely
defined.
o char: The char data type is a single 16-bit Unicode character. It has a minimum
value of'\u0000' (or 0) and a maximum value of '\uffff' (or 65,535 inclusive).
The Java programming language also provides special support for character strings via
the java.lang.String class. Enclosing your character string within double quotes will
automatically create a new String object; for example, String s = "this is a
string";. String objects are immutable, which means that once created, their values cannot
be changed. The String class is not technically a primitive data type
AUTOBOXING AND UNBOXING
Java compiler automatically converts between the primitive types and their corresponding object
wrapper classes. This is autoboxing. For example, int to an Integer, double to a Double.
Example: Character ch = 'a';
Unboxing is conversion between the object wrapper class to the primitive type. The Java compiler
applies unboxing when an object of a wrapper class is:

Passed as a parameter to a method that expects a value of the corresponding primitive type.
8
Learning the Java Language- (25 APR -01 MAY - CODE)

Assigned to a variable of the corresponding primitive type.
The following table lists the primitive types and their corresponding wrapper classes, which are used
by the Java compiler for autoboxing and unboxing:
Primitive type Wrapper class
boolean
Boolean
byte
Byte
char
Character
float
Float
int
Integer
long
Long
short
Short
double
Double
DEFAULT VALUES
Fields that are declared but not initialized will be set to a reasonable default by the
compiler. Relying on such default values, however, is generally considered bad
programming style.
Data Type
Default Value (for fields)
byte
0
short
0
int
0
long
0L
float
0.0f
double
0.0d
9
Learning the Java Language- (25 APR -01 MAY - CODE)
char
'\u0000'
String (or any object) null
boolean
false
Literals
A literal is the source code representation of a fixed value; literals are represented directly
in your code without requiring computation. As shown below, it's possible to assign a literal
to a variable of a primitive type:
boolean result = true;
char capitalC = 'C';
byte b = 100;
short s = 10000;
int i = 100000;
TO READ: INTEGER LITERALS
TO READ: FLOATING-POINT LITERALS
TO READ: CHARACTER AND STRING LITERALS
TO READ: USING UNDERSCORE CHARACTERS IN NUMERIC LITERALS
ARRAYS
An array is a container object that holds a fixed number of values of a single type. The
length of an array is established when the array is created. After creation, its length is fixed.
10
Learning the Java Language- (25 APR -01 MAY - CODE)
Each item in an array is called an element, and each element is accessed by its
numerical index. As shown in the preceding illustration, numbering begins with 0. The 9th
element, for example, would therefore be accessed at index 8.
Like declarations for variables of other types, an array declaration has two components: the
array's type and the array's name. An array's type is written as type[], where type is the data
type of the contained elements; the brackets are special symbols indicating that this
variable holds an array.
As with variables of other types, the declaration does not actually create an array; it simply
tells the compiler that this variable will hold an array of the specified type.
float[] anArrayOfFloats;
You can also place the brackets after the array's name:
// this form is discouraged
float anArrayOfFloats[];
CREATING, INITIALIZING, AND ACCESSING AN ARRAY




// create an array of integers
anArray = new int[10];
If this statement is missing, then the compiler prints an error like the following, and
compilation fails: Variable anArray may not have been initialized.
assign values to each element of the array:
anArray[0] = 100; // initialize first element
Each array element is accessed by its numerical index:
System.out.println("Element 1 at index 0: " + anArray[0]);
Alternatively, you can use the shortcut syntax to create and initialize an array:
int[] anArray = {
100, 200, 300,
400, 500, 600,
700, 800, 900, 1000
};
11
Learning the Java Language- (25 APR -01 MAY - CODE)
Here the length of the array is determined by the number of values provided between
braces and separated by commas.
You can also declare an array of arrays (also known as a multidimensional array) by using
two or more sets of brackets, such as String[][] names. Each element, therefore, must be
accessed by a corresponding number of index values. In the Java programming language,
a multidimensional array is an array whose components are themselves arrays. Example
in reference: Multi-Dimensional Arrays.
Finally, you can use the built-in length property to determine the size of any array. The
following code prints the array's size to standard output:
System.out.println(anArray.length);


COPYING ARRAYS
The System class has an arraycopy method that you can use to efficiently copy data from
one array into another:
public static void arraycopy(Object src, int srcPos,
Object dest, int destPos, int length)
The two Object arguments specify the array to copy from and the array to copy to. The
three intarguments specify the starting position in the source array, the starting position in
the destination array, and the number of array elements to copy.
The following program, ArrayCopyDemo, declares an array of char elements, spelling the
word "decaffeinated." It uses the System.arraycopy method to copy a subsequence of array
components into a second array:
class ArrayCopyDemo {
public static void main(String[] args) {
char[] copyFrom = { 'd', 'e', 'c', 'a', 'f', 'f', 'e',
'i', 'n', 'a', 't', 'e', 'd' };
char[] copyTo = new char[7];
System.arraycopy(copyFrom, 2, copyTo, 0, 7);
System.out.println(new String(copyTo));
}
12
Learning the Java Language- (25 APR -01 MAY - CODE)
}
The output from this program is:
caffein
ARRAY MANIPULATIONS
For your convenience, Java SE provides several methods for performing array manipulations
(common tasks, such as copying, sorting and searching arrays) in the java.util.Arrays class.
COPYOFRANGE
lass ArrayCopyOfDemo {
public static void main(String[] args) {
char[] copyFrom = {'d', 'e', 'c', 'a', 'f', 'f', 'e',
'i', 'n', 'a', 't', 'e', 'd'};
char[] copyTo = java.util.Arrays.copyOfRange(copyFrom, 2, 9);
System.out.println(new String(copyTo));
}
}
OTHER USEFUL OPERATIONS

Searching an array for a specific value to get the index at which it is placed
(the binarySearchmethod).

Comparing two arrays to determine if they are equal or not (the equals method).

Filling an array to place a specific value at each index (the fill method).

Sorting an array into ascending order. This can be done either sequentially, using
the sortmethod, or concurrently, using the parallelSort method introduced in Java SE
8. Parallel sorting of large arrays on multiprocessor systems is faster than sequential
array sorting.
13
Learning the Java Language- (25 APR -01 MAY - CODE)
OPERATORS
Operator Precedence
Operators
Precedence
postfix
expr++ expr--
unary
++expr --expr +expr -expr ~ !
multiplicative
*/%
additive
+-
shift
<< >> >>>
relational
< > <= >= instanceof
equality
== !=
bitwise AND
&
bitwise exclusive OR ^
bitwise inclusive OR
|
logical AND
&&
logical OR
||
14
Learning the Java Language- (25 APR -01 MAY - CODE)
ternary
?:
assignment
= += -= *= /= %= &= ^= |= <<= >>= >>>=
THE FOUR FUNDAMENTAL OOP CONCEPTS
The four fundamental concepts of object-oriented programming are: encapsulation,
inheritance, abstraction and polymorphism.
ENCAPSULATION






This is also called information hiding.
By this we hide the implementation details of a class (methods and data) from its users
(other applications and classes).
The class acts as a container that encapsulates a set of methods, attribute and
properties to provide its functionalities to other classes.
Encapsulation hides how a class implements functionality while allowing other classes to
make requests of it.
Encapsulation allows a class to change its internal implementation without impacting
the overall functioning of the system.
In java, we make the variables of the class private then expose only the required or
implemented methods through mutators (setter methods) and accessor (getter)
methods. These methods change and provide the state of an object or variable
respectively.
ABSTRACTION



Abstraction enables us to expose or deliver functionality of an application to users
without the details of how we achieved it. In java, we do this by using the abstract class
and an interface.
We define a contract that our application needs to fulfil and expect it to deliver as
expected. The application may use one of various implementation ways and even
change its implementation without the user knowing it.
In java we do this by either extending an abstract class or implementing an interface.
ABSTRACT CLASS
15
Learning the Java Language- (25 APR -01 MAY - CODE)






An abstract class is declared with the abstract keyword and cannot be instantiated. It
can only be used as a super-class for other classes that extend the abstract class. The
implementation gets completed when the subclass extend it.
We use abstract keyword to create an abstract method which doesn’t have body.
A class with abstract methods will only compile if it is made abstract. On the other hand
an abstract class doesn’t need to have an abstract methods.
The subclass of abstract class must implement all the abstract methods, unless the
subclass is also an abstract class.
Abstract classes can implement interfaces without even providing the implementation of
interface methods.
We can run abstract class like any other class if it has main() method.
INTERFACE



An interface is a contract between an application and the outside world. It is a
promise of what functionality an application will deliver. It helps abstract the details
while revealing what users of an application can expect.
An interface is a reference type in java and a collection of abstract methods. An
interface may also contain constants, default methods, static methods, and nested
types. Method bodies exist only for default methods and static methods.
A concrete class will implement an interface and thus inherit the abstract methods of
the interface.
WHEN TO USE AN INTERFACE/ OR AN ABSTRACT CLASS



To determine whether to use an interface or an abstract class or both, look at the
relationship as a IS-A hierarchy or CAN-DO-THIS hierarchy.
An abstract class is suitable where the relationship to be defines is an IS-A hierarchy.
An Interface is suitable where the relationship is a CAN-DO-THIS relationship.
DIFFERENCE BETWEEN ABSTRACT CLASS AND INTERFACE


Interface is of type interface while Abstract class is of type class
Interface methods do not implement the functionality they define (except for the
default methods), instead it is implemented. Abstract class methods can have their
own default implementations which can be run independently and they may also be
extended.
POLYMORPHISM

Polymorphism is the ability of an object to take on many forms. For example we can
use a parent class reference in reference to a child class object. We can refer to a
16
Collections (01-08 MAY - CODE)





person to illustrate a person's behaviour, even when we know that that person is a
teacher.
An object is considered polymorphic if it passes the IS-A test - That is, it is a type of
another object. As such, every object in java is polymorphic because it is of the
object type.
We cannot change the reference variable of an object once we have declared it,
although we can reassign it to another object if it is not declared final.
There are two types of polymorphism in Java:
Compile time polymorphism (static binding) e.g. method overloading.
Runtime polymorphism (dynamic binding) e.g. method overriding.
INHERITANCE



Object-oriented programming allows classes to inherit commonly used state and
behavior from other classes.
o Example: A Bicycle is the superclass of MountainBike, RoadBike, andTandemBike.
In Java each class is allowed to have one direct superclass, and each superclass has the
potential for an unlimited number of subclasses.
At the beginning of your class declaration, use the extends keyword, followed by the
name of the class to inherit from:
class MountainBike extends Bicycle {
// new fields and methods defining
// a mountain bike would go here
}

MountainBike has the same fields and methods as Bicycle, yet allows its code to focus
exclusively on the features that make it unique.
3) COLLECTIONS (01-08 MAY - CODE)
INTRODUCTION
WHAT IS THE COLLECTIONS FRAMEWORK
17
Collections (01-08 MAY - CODE)




A collection — sometimes called a container — is simply an object that groups multiple
elements into a single unit.
Collections are used to store, retrieve, manipulate, and communicate aggregate data.
Typically, they represent data items that form a natural group, such as a poker hand (a
collection of cards), a mail folder (a collection of letters), or a telephone directory (a
mapping of names to phone numbers).
The collections framework is a unified architecture for representing and manipulating
collections. Contains the following:

Interfaces: These are abstract data types that represent collections. Interfaces allow
collections to be manipulated independently of the details of their representation. In
object-oriented languages, interfaces generally form a hierarchy.

Implementations: These are the concrete implementations of the collection interfaces.
In essence, they are reusable data structures.

Algorithms: These are the methods that perform useful computations, such as
searching and sorting, on objects that implement collection interfaces.
o
The algorithms are polymorphic: the same method can be used on many
different implementations of the appropriate collection interface. So the
functionality is reusable.
BENEFITS OF THE JAVA COLLECTIONS FRAMEWORK






Reduces programming effort
Increases program speed and quality
Allows interoperability among unrelated APIs
Reduces effort to learn and to use new APIs
Reduces effort to design new APIs
Fosters software reuse
LESSON: INTERFACES
Core collection interfaces are the foundation of the Java Collections Framework.
18
Collections (01-08 MAY - CODE)



The hierarchy consists of two distinct trees — a Map is not a true Collection.
The core collection interfaces are generic
When you declare a Collection instance you can and should specify the type of object
contained in the collection. Specifying the type allows the compiler to verify (at
compile-time) that the type of object you put into the collection is correct, thus
reducing errors at runtime.
The modification operations in each interface are designatedoptional — a given
implementation may elect not to support all operations. If an unsupported operation is
invoked, a collection throws an UnsupportedOperationException. Implementations are
responsible for documenting which of the optional operations they support. All of the Java
platform's general-purpose implementations support all of the optional operations.
COLLECTION




The Collection interface is the least common denominator that all collections implement
and is used to pass collections around and to manipulate them when maximum
generality is desired.
Some types of collections allow duplicate elements, and others do not.
Some are ordered and others are unordered.
The Java platform doesn't provide any direct implementations of this interface but
provides implementations of more specific subinterfaces, such as Set and List.
SET



A collection that cannot contain duplicate elements.
Models the mathematical set storing a set such as the courses making up a student's
schedule, or the processes running on a machine.
The interface- java.util.Set is a subtype of the java.util.Collection interface. So all
methods in the Collection interface are also available in the Set interface.
LIST



Ordered collection (sometimes called a sequence).
Lists can contain duplicate elements.
The user of a List generally has precise control over where in the list each element is
inserted and can access elements by their integer index (position).
QUEUE


A collection used to hold multiple elements prior to processing.
Besides basic collection operations, a Queue provides additional insertion, extraction,
and inspection operations.
19
Collections (01-08 MAY - CODE)



Queues typically, but do not necessarily, order elements in a FIFO (first-in, first-out)
manner.
Whatever the ordering used, the head of the queue is the element that would be
removed by a call to remove or poll. In a FIFO queue, all new elements are inserted at
the tail of the queue. Other kinds of queues may use different placement rules.
Every Queue implementation must specify its ordering properties.
DEQUE



A collection used to hold multiple elements prior to processing.
Besides basic Collection operations, a Deque provides additional insertion, extraction,
and inspection operations.
In a deque all new elements can be inserted, retrieved and removed at both ends
MAP



An object that maps keys to values.
A Map cannot contain duplicate keys
Each key can map to at most one value.
The following core collection interfaces are merely sorted versions of Set and Map:
SORTEDSET

A set that maintains its elements in ascending order.

Several additional operations are provided to take advantage of the ordering.

Sorted sets are used for naturally ordered sets, such as word lists and membership
rolls.
SORTEDMAP


A Map that maintains its mappings in ascending key order.
Used for naturally ordered collections of key/value pairs, such as dictionaries and
telephone directories.
THE COLLECTION INTER FACE

Contains methods that perform basic operations, such as int size(), boolean
isEmpty(), boolean contains(Object element), boolean add(E element), boolean
remove(Object element), and Iterator<E> iterator().
20
Collections (01-08 MAY - CODE)

Contains methods that operate on entire collections, such as boolean
containsAll(Collection<?> c), boolean addAll(Collection<? extends E> c), boolean
removeAll(Collection<?> c), boolean retainAll(Collection<?> c), and void clear().
Contains methods for array operations (such as Object[] toArray() and <T> T[]
toArray(T[] a) exist as well.
In JDK 8 and later, the Collection interface also exposes methods Stream<E>
stream() and Stream<E> parallelStream(), for obtaining sequential or parallel streams
from the underlying collection.
The add method is defined generally enough so that it makes sense for collections that
allow duplicates as well as those that don't. It guarantees that the Collection will
contain the specified element after the call completes, and returns true if
the Collection changes as a result of the call. Similarly, the remove method is designed
to remove a single instance of the specified element from the Collection, assuming
that it contains the element to start with, and to return true if the Collection was
modified as a result.



TRAVERSING COLLECTIONS
There are three ways to traverse collections: (1) using aggregate operations (2) with
the for-each construct and (3) by using Iterators.
AGGREGATE OPERATIONS
for (Person p : roster) {
if (p.getGender() == Person.Sex.MALE) {
System.out.println(p.getName());
}
}
FOREACH
for (Number number : numbers){
log(number);
}
ITERATOR
Iterator itr = al.iterator();
while(itr.hasNext()) {
Object element = itr.next();
21
Collections (01-08 MAY - CODE)
22
System.out.print(element + " ");
}
LESSON: IMPLEMENTATIONS

General-purpose - are the most commonly used implementations, designed for
everyday use. They are summarized in the table titled General-purposeimplementations.

Special-purpose - designed for use in special situations and display nonstandard
performance characteristics, usage restrictions, or behavior.

Concurrent - designed to support high concurrency, typically at the expense of
single-threaded performance. These implementations are part of the
java.util.concurrent package.

Wrapper - used in combination with other types of implementations, often the
general-purpose ones, to provide added or restricted functionality.

Convenience are mini-implementations, typically made available via static factory
methods, that provide convenient, efficient alternatives to general-purpose
implementations for special collections (for example, singleton sets).

Abstract are skeletal implementations that facilitate the construction of custom
implementations — described later in the Custom Collection
Implementations section. An advanced topic, it's not particularly difficult, but
relatively few people will need to do it.
GENERAL-PURPOSE IMPLEMENTATIONS




Java Collections Framework provides several general-purpose implementations.
You may only need HashSet, ArrayList, and HashMap for most applications.
The General Purpose implementation of the SortedSet and the SortedMap
interfaces are the TreeSet and TreeMap, hence the interfaces are not listed in the
table.
There are two general purpose queue implementations — LinkedList (also a List
implementation) and PriorityQueue (not in the table). LinkedList provides FIFO
functionality while the PriorityQueue order elements according to their value.
Interfaces
Hash table
Resizable array
Implementations Implementations
Tree
Implementations
Set
HashSet
TreeSet
List
ArrayList
Linked list
Implementations
Hash table + Linked
list
Implementations
LinkedHashSet
LinkedList
Collections (01-08 MAY - CODE)
23
Queue
Deque
ArrayDeque
Map
HashMap
LinkedList
TreeMap
LinkedHashMap
Similarities

Each of the general-purpose implementations provides all optional operations
contained in its interface.

All permit null elements, keys, and values.

All have Fail-fast iterators

All are Serializable and clonable.

None are synchronized
o A break with the past - legacy collections Vector and Hashtable are
synchronized.
o Because collections are frequently used when the synchronization is of no
benefit e.g. single-threaded use, read-only use, and as part of a larger data
object that does its own synchronization. Users don’t have to pay for a
feature they don't use. Also, unnecessary synchronization can result in
deadlock under some circumstances.
Collections (01-08 MAY - CODE)
o If you need thread-safe collections, the synchronization wrappers
allow any collection to be transformed into a synchronized collection.
Moreover, the java.util.concurrent package provides concurrent
implementations of the BlockingQueue interface, which extends Queue, and
of the ConcurrentMapinterface, which extends Map. These implementations
offer much higher concurrency than mere synchronized implementations.
SET IMPLEMENTATION



There are three general-purpose Set implementations — HashSet, TreeSet, and
LinkedHashSet.
HashSet is much faster than TreeSet (constant-time versus log-time for most
operations) but offers no ordering guarantees. Hashset is the most commonly used
implementation.
If you need to use the operations in the SortedSet interface, or if value-ordered iteration
is required, use TreeSet.
HASHSET









HashSet doesn’t maintain any order, the elements would be returned in any random
order.
HashSet doesn’t allow duplicates. If you try to add a duplicate element in HashSet, the
old value would be overwritten.
HashSet allows null values however if you insert more than one nulls it would still
return only one null value.
HashSet is non-synchronized. The Collection Framework provides methods to enable us
to synchronise it if it will be used by multiple threads.
The iterator returned by this class is fail-fast which means iterator would throw
ConcurrentModificationException if HashSet has been modified after creation of
iterator, by any means except iterator’s own remove method.
Iteration is linear in the sum of the number of entries and the number of buckets
(the capacity).
Choosing an initial capacity that's too high can waste both space and time. An initial
capacity that's too low wastes time by copying the data structure each time it's forced to
increase its capacity. If you don't specify an initial capacity, the default is 16.
In the past, there was some advantage to choosing a prime number as the initial
capacity. This is no longer true. Internally, the capacity is always rounded up to a power
of two. The initial capacity is specified by using the int constructor.
Set<String> s = new HashSet<String>(64);
If you care a lot about the space consumption of your HashSet, read
the HashSet documentation for more information on the tuning parameter called
24
Collections (01-08 MAY - CODE)
the load factor. Otherwise, just accept the default. If you accept the default load factor
but want to specify an initial capacity, pick a number that's about twice the size to which
you expect the set to grow.
LINKEDHASHSET




Intermediate between HashSet and TreeSet.
Implemented as a hash table with a linked list running through it, it provides insertionordered iteration (least recently inserted to most recently) and runs nearly as fast
as HashSet.
The LinkedHashSet implementation spares its clients from the unspecified, generally
chaotic ordering provided by HashSet without incurring the increased cost associated
with TreeSet.
LinkedHashSet has the same tuning parameters as HashSet, but iteration time is not
affected by capacity. TreeSet has no tuning parameters.
TREESET



TreeSet is similar to the HashSet except that it sorts the elements in the ascending
order unlike the HashSet.
TreeSet allows null element.
Like most of the other collection classes this class is also not synchronized
ENUMSET



A high-performance Set implementation for enum types.
All of the members of an enum set must be of the same enum type.
Internally, it is represented by a bit-vector, typically a single long.
COPYONWRITEARRAYSET




Set implementation backed up by a copy-on-write array.
All mutative operations, such as add, set, and remove, are implemented by making a
new copy of the array; no locking is ever required. Even iteration may safely proceed
concurrently with element insertion and deletion.
Unlike most Set implementations, the add, remove, and contains methods require time
proportional to the size of the set.
This implementation is only appropriate for sets that are rarely modified but frequently
iterated. It is well suited to maintaining event-handler lists that must prevent duplicates.
LIST IMPLEMENTATION
25
Collections (01-08 MAY - CODE)


You can choose between the following List implementations in the Java Collections
API:
o
java.util.ArrayList
o
java.util.LinkedList
o
java.util.Vector
o
java.util.Stack
The order in which the elements are added to the List is stored, so you can access
the elements in the same order. You can do so using either the get(int
index) method, or via the Iterator returned by theiterator() method
ARRAYLIST








Introduced with JDK 1.2.
Most used implementation after the Vector.
The elements added are stored internally as an array.
It permits duplicates and null values as elements.
ArrayList is not synchronised.
Elements can be retrieved with the conventional styles of foreach loop, iterators and
indexes.
Implements the List interface.
It is widely used as a replacement/alternative to the traditional java Array because of
the functionality and flexibility. The issue with arrays:
o They are of fixed length so if it is full we cannot add any more elements to it.
o If elements are removed from it, the memory consumption would be the same
as it doesn’t shrink.
The ArrayList can dynamically grows and shrinks.


ArrayList has one tuning parameter — the initial capacity, which refers to the number
of elements theArrayList can hold before it has to grow.
The performance of an ArrayList decreases as it grows. When an ArrayList grows, a new
array with increased capacity is created, the contents of the old array are copied into the
new array and old array location is garbage collected. Repeating this slows execution.
CONSTRUCTORS


ArayList(): Creates an ArrayList object with an initial capacity to store 10 elements.
ArayList(int capacity): Creates an ArrayList object with an initial capacity provided.
26
Collections (01-08 MAY - CODE)

ArayList(Collection collection): Creates an ArrayList object with the elements of
collection.
KEY METHODS


ensureCapacity(): Consider a scenario when there is a need to add huge number of
elements to an already full ArrayList. The ArrayList has to be resized several times which
would result in a poor performance. For such scenarios ensureCapacity() increases the
size of the ArrayList by a specified capacity.
set(int index, Object o): Used for updating an element. It replaces the element present
at the specified index with the object o.
LINKEDLIST

A linked list is a linear data structure where each element is a separate object.


Each element has two items - the data and a reference to the next node.
The last node has a reference to null.
The entry point into a linked list is called the head of the list. This is the first node. If the
list is empty then the head is a null reference.
A linked list is a dynamic data structure- can grow and shrink on demand. This makes it
useful when the number of objects to be stored is unknown.
The LinkedList does not allow direct access to the individual elements. If you want to
access a particular item then you have to start at the head and follow the references
until you get to that item.
It also uses more memory in comparison to arrays – An extra 4 bytes (on 32-bit CPU) to
store a reference to the next node.




TYPES OF LINKED LISTS
27
Collections (01-08 MAY - CODE)
LINKED LIST OPERATIONS
http://www.cs.cmu.edu/~adamchik/15-121/lectures/Linked%20Lists/linked%20lists.html
MAP IMPLEMENTATION
GENERAL-PURPOSE MAP IMPLEMENTATIONS:





HashMap, TreeMap, LinkedHadMap.
The most commonly used map is the HashMap.
HashMap - If you need a map with fast access and don’t care about the iteration order.
TreeMap - For sorted map operations or key-ordered iteration.
LinkedHashMap - If you need near HashMap performance with insertion-order iteration.
o When you create a LinkedHashMap, you can order it based on key access rather
than insertion.
o In other words, merely looking up the value associated with a key brings that key
to the end of the map.
o LinkedHashMap also provides the removeEldestEntry method that can be
overridden to remove stale records. This makes it easy to implement a custom
cache.
28
Concurrency (23-29 MAY-CODE)
SPECIAL PURPOSE MAP IMPLEMENTATIONS
ENUMMAP



EnumMap is a high-performance Map implementation for use with enum keys.
It is internally implemented as an array
Used to map an enum to a value.
WEAKHASHMAP



WeakHashMap is an implementation that stores only weak references to its keys.
This allows a key-value pair to be garbage-collected when its key is no longer referenced
outside of the WeakHashMap.
It provides the easiest way to harness the power of weak references useful for
implementing "registry-like" data structures, where the utility of an entry vanishes when
its key is no longer reachable by any thread.
IDENTITYHASHMAP






IdentityHashMap is an identity-based Map implementation based on a hash table.
IdentityHashMap is useful for topology-preserving object graph transformations, such as
serialization or deep-copying.
To perform such transformations, you need to maintain an identity-based "node table"
that keeps track of which objects have already been seen.
Identity-based maps are also used to maintain object-to-meta-information mappings in
dynamic debuggers and similar systems.
Finally, identity-based maps are useful in thwarting "spoof attacks" that are a result of
intentionally perverse equals methods because IdentityHashMap never invokes the
equals method on its keys.
An added benefit of this implementation is that it is fast.
CONCURRENT MAP IMPLEMENTATIONS
CONCURRENTHASHMAP


ConcurrentHashMap is a highly concurrent, high-performance implementation backed
up by a hash table.
ConcurrentHashMap never blocks when performing retrievals and allows the client to
select the concurrency level for updates.
4) CONCURRENCY (23-29 MAY-CODE)
29
Concurrency (23-29 MAY-CODE)


The Java platform is designed to support concurrent programming, with basic
concurrency support in the Java programming language and the Java class libraries.
Since version 5.0, the Java platform has also included high-level concurrency APIs. This
tutorial will cover basic concurrency support and some of the high-level APIs in
thejava.util.concurrent packages
INTRODUCTION
PROCESSES


A process has a self-contained execution environment with a complete, private set of
basic run-time resources; in particular, each process has its own memory space.
To facilitate communication between processes, most operating systems support Inter
Process Communication (IPC) resources, such as pipes and sockets. IPC is used for
communication between processes on the same system and on different systems.
THREADS





Threads are sometimes called lightweight processes.
Both processes and threads provide an execution environment, but creating a new
thread requires fewer resources than creating a new process.
Threads share the process's resources, including memory and open files. This can be a
problem and that is why java has the concurrency APIs to help manage these resources
efficiently.
From the application programmer's point of view, you start with just one thread, called
the main thread. This thread has the ability to create additional threads.
Each thread is associated with an instance of the class Thread. There are two basic
strategies for using Thread objects to create a concurrent application.

To directly control thread creation and management, simply instantiate Thread each
time the application needs to initiate an asynchronous task.

To abstract thread management from the rest of your application, pass the
application's tasks to an executor.
DEFINING AND STARTING A THREAD

An application that creates an instance of Thread must provide the code that will run in
that thread. There are two ways to do this:

Provide a Runnable object. The Runnable interface defines a single method, run, meant
to contain the code executed in the thread. The Runnable object is passed to
the Thread constructor. This is more general, because the Runnable object can subclass
30
Concurrency (23-29 MAY-CODE)
a class other than Thread. Not only is this approach more flexible, but it is applicable to
the high-level thread management APIs.

Subclass Thread. The Thread class itself implements Runnable, though its run method
does nothing. An application can subclass Thread, providing its own implementation
of run. This is easier to use in simple applications, but is limited by the fact that your task
class must be a descendant of Thread.

Both invoke Thread.start in order to start the new thread.

The Thread class defines a number of methods useful for thread management:
o
Static methods, which provide information about, or affect the status of, the
thread invoking the method.
o
Methods invoked from other threads involved in managing the thread
and Thread object.
PAUSING EXECUTION WITH SLEEP

Thread.sleep causes the current thread to suspend execution for a specified period. This
is an efficient means of making processor time available to the other threads of an
application or other applications that might be running on a computer system.

Two overloaded versions of sleep are provided:
o one that specifies the sleep time to the millisecond
o one that specifies the sleep time to the nanosecond.

Sleep times are not guaranteed to be precise:
o Limited by the facilities provided by the underlying OS.
o Sleep period can be terminated by interrupts

Sleep throws InterruptedException when another thread interrupts the current thread
while sleep is active.
INTERRUPTS

If any thread is in sleeping or waiting state (i.e. sleep() or wait() is invoked), calling the
interrupt() method on the thread, breaks out the sleeping or waiting state throwing
InterruptedException.
31
Concurrency (23-29 MAY-CODE)

If the thread is not in the sleeping or waiting state, calling the interrupt() method
performs normal behaviour and doesn't interrupt the thread but sets the interrupt flag
to true.

An interrupt is an indication to a thread that it should stop what it is doing and do
something else.

It's up to the programmer to decide exactly how a thread responds to an interrupt, but it
is very common for the thread to terminate.

A thread sends an interrupt by invoking interrupt on the Thread object for the thread to
be interrupted.

For the interrupt mechanism to work correctly, the interrupted thread must support its
own interruption. How?:
o Many methods that throw InterruptedException, such as sleep, are designed to
cancel their current operation and return immediately when an interrupt is
received.
o If a thread goes a long time without invoking a method that
throws InterruptedException, then it must periodically invokeThread.interrupted,
which returns true if an interrupt has been received. For example:
for (int i = 0; i < inputs.length; i++) {
heavyCrunch(inputs[i]);
if (Thread.interrupted()) {
// We've been interrupted: no more crunching.
return;
}
}
o In more complex applications, it might make more sense to throw
an InterruptedException. This allows interrupt handling code to be centralized in
a catch clause.
if (Thread.interrupted()) {
throw new InterruptedException();
}
32
Concurrency (23-29 MAY-CODE)
THE INTERRUPT STATUS FLAG
o The interrupt mechanism is implemented using an internal flag known as
the interrupt status.
o Invoking Thread.interrupt sets this flag. When a thread checks for an interrupt by
invoking the static method Thread.interrupted, interrupt status is cleared.
o The non-static isInterrupted method, which is used by one thread to query the
interrupt status of another, does not change the interrupt status flag.
JOINS

The join method allows one thread to wait for the completion of another. If t is
a Thread object whose thread is currently executing, t.join(); causes the current thread
to pause execution until t's thread terminates.

As with sleep, join is dependent on the OS for timing, so you should not assume
that join will wait exactly as long as you specify.

Like sleep, join responds to an interrupt by exiting with an InterruptedException.
WHEN TO USE JOIN


To make one Thread to wait for another and start execution once that Thread has
completed execution or died.
Join is also a blocking method, which blocks until thread on which join has called die or
specified waiting time is over.
SYNCHRONIZATION
INTRODUCTION

Threads communicate primarily by sharing access to fields and the objects reference
fields refer to.

Synchronization is needed to prevent two kinds of errors possible: thread interference
and memory consistency errors: When two or more threads try to access the same
resource simultaneously this may result in thread contention causing the Java runtime to
execute one or more threads more slowly, or even suspend execution.
THREAD INTERFERENCE
33
Concurrency (23-29 MAY-CODE)


Interference happens when two operations, running in different threads, but acting on
the same data, interleave. This means that the two operations consist of multiple steps,
and the sequences of steps overlap.
Because they are unpredictable, thread interference bugs can be difficult to detect and
fix.
MEMORY CONSISTENCY ERRORS


Happens because of a number of cases in which accesses to program variables may
appear to execute in a different order than was specified by the program. As such
different threads have inconsistent views of what should be the same data.
Understanding the happens-before relationship helps us to avoid these erorrs.
The compiler, for example, is free to reorder instructions to optimize performance. But
also Processors may execute instructions out of order under certain circumstances. They
can move data between registers, memory caches, and main memory in different
order than specified by the program.
EXAMPLE ACTIONS THAT LEAD TO HAPPENS-BEFORE RELATIONSHIPS.




Synchronization
When a statement invokes Thread.start, the effects of the code that led up to the
creation of the new thread are visible to the new thread. Every statement that has a
happens-before relationship with that statement also has a happens-before relationship
with every statement executed by the new thread.
When a thread terminates and causes a Thread.join in another thread to return, the
effects of the code in the thread are now visible to the thread that performed the join.
All the statements executed by the terminated thread have a happens-before
relationship with all the statements following the successful join.
Full list of java concurrency happens-before actions
Java provides two forms of synchronization: Synchronized methods and synchronized
statements.
SYNCHRONIZED METHODS
To make a method synchronized, simply add the synchronized keyword to its declaration.
This has two effects:

It is not possible for two invocations of synchronized methods on the same object to
interleave. When one thread is executing a synchronized method for an object, all other
threads that invoke synchronized methods for the same object block until the first
thread is done with the object.
34
Concurrency (23-29 MAY-CODE)

When a synchronized method exits, it automatically establishes a happens-before
relationship with any subsequent invocation of a synchronized method for the same
object. This guarantees that changes to the state of the object are visible to all threads.
Synchronized methods enable a simple strategy for preventing thread interference and
memory consistency errors but can present problems with liveness.
INTRINSIC LOCKS









Every object has an intrinsic lock aka monitor lock associated with it. The API
specification often refers to this entity simply as a "monitor."
The Intrinsic lock plays a role in both aspects of synchronization: enforcing exclusive
access to an object's state and establishing happens-before relationships that are
essential to visibility.
A thread that needs exclusive and consistent access to an object's fields acquires the
intrinsic lock before accessing them, and then releases it when it's done.
A thread is said to own the intrinsic lock between the time it has acquired the lock and
released the lock.
Threads that attempt to acquire the lock will block as long as the thread owns the lock.
When a thread releases an intrinsic lock, a happens-before relationship is established
between that action and any subsequent acquistion of the same lock.
A lock is a thread synchronization mechanism like synchronized blocks except locks can
be more sophisticated than Java's synchronized blocks.
Locks (and other more advanced synchronization mechanisms) are created using
synchronized blocks.
From Java 5 the package java.util.concurrent.locks contains several lock
implementations, so you may not have to implement your own locks. But you will still
need to know how they work and how to use them.
ATOMIC ACCESS




An atomic action is one that effectively happens all at once. It either happens
completely, or it doesn't happen at all. It cannot stop in the middle.
No side effects of an atomic action are visible until the action is complete.
Even very simple expressions can define complex actions that can decompose into other
actions. Examples of atomic actions:
o Reads and writes are atomic for reference variables and for most primitive
variables (all types except long and double).
o Reads and writes are atomic for all variables
declared volatile (including long and double variables).
Atomic actions cannot be interleaved, so they can be used without fear of thread
interference. However, memory consistency errors are still possible.
35
Concurrency (23-29 MAY-CODE)





Using volatile variables reduces the risk of memory consistency errors:
Any write to a volatile variable establishes a happens-before relationship with
subsequent reads of that same variable. This means that changes to a volatile variable
are always visible to other threads.
It also means that when a thread reads a volatile variable, it sees not just the latest
change to the volatile, but also the side effects of the code that led up the change.
Using simple atomic variable access is more efficient than accessing these variables
through synchronized code, but requires more care by the programmer to avoid
memory consistency errors. Whether the extra effort is worthwhile depends on the size
and complexity of the application.
Some of the classes in the java.util.concurrent package provide atomic methods that do
not rely on synchronization.
LOCKS IN SYNCHRONIZED METHODS


When a thread invokes a synchronized method, it automatically acquires the intrinsic
lock for that method's object and releases it when the method returns even if the
return was caused by an uncaught exception.
For static methods, the thread acquires the intrinsic lock for the Class object associated
with the class. Access to class's static fields is controlled by a lock that's distinct from the
class instance lock.
SYNCHRONIZED STATEMENTS

Unlike synchronized methods, synchronized statements must specify the object that
provides the intrinsic lock:
public void addName(String name) {
synchronized(this) {
lastName = name;
nameCount++;
}
nameList.add(name);
}

In this example, the addName method needs to synchronize changes
to lastName and nameCount, but also needs to avoid synchronizing invocations of other
36
Concurrency (23-29 MAY-CODE)

objects' methods. (Invoking other objects' methods from synchronized code can create
problems that are described in the section on Liveness.)
Synchronized statements are also useful for improving concurrency with fine-grained
synchronization. Instead of using synchronized methods or otherwise using the lock
associated with this, we create two objects solely to provide locks.
public class MsLunch {
private long c1 = 0;
private long c2 = 0;
private Object lock1 = new Object();
private Object lock2 = new Object();
public void inc1() {
synchronized(lock1) {
c1++;
}
}
public void inc2() {
synchronized(lock2) {
c2++;
}
}
}

Use this idiom with extreme care. You must be absolutely sure that it really is safe to
interleave access of the affected fields.
A SIMPLE LOCK
37
Concurrency (23-29 MAY-CODE)
USING SYNCHRONIZED: ESSENTIAL JAVA CLASSES - BASIC I/O
USING BYTE STREAMS
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class CopyBytes {
public static void main(String[] args) throws IOException {
FileInputStream in = null;
FileOutputStream out = null;
try {
in = new FileInputStream("xanadu.txt");
out = new FileOutputStream("outagain.txt");
int c;
while ((c = in.read()) != -1) {
out.write(c);
}
} finally {
if (in != null) {
in.close();
}
if (out != null) {
out.close();
}
}
38
Concurrency (23-29 MAY-CODE)
}
}
USING CHARACTER STREAMS
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class CopyCharacters {
public static void main(String[] args) throws IOException {
FileReader inputStream = null;
FileWriter outputStream = null;
try {
inputStream = new FileReader("xanadu.txt");
outputStream = new FileWriter("characteroutput.txt");
int c;
while ((c = inputStream.read()) != -1) {
outputStream.write(c);
}
} finally {
if (inputStream != null) {
inputStream.close();
}
if (outputStream != null) {
outputStream.close();
}
}
39
Concurrency (23-29 MAY-CODE)
}
}
LINE-ORIENTED I/O
import java.io.FileReader;
import java.io.FileWriter;
import java.io.BufferedReader;
import java.io.PrintWriter;
import java.io.IOException;
public class CopyLines {
public static void main(String[] args) throws IOException {
BufferedReader inputStream = null;
PrintWriter outputStream = null;
try {
inputStream = new BufferedReader(new FileReader("xanadu.txt"));
outputStream = new PrintWriter(new FileWriter("characteroutput.txt"));
String l;
while ((l = inputStream.readLine()) != null) {
outputStream.println(l);
}
} finally {
if (inputStream != null) {
inputStream.close();
}
if (outputStream != null) {
outputStream.close();
40
Concurrency (23-29 MAY-CODE)
}
}
}
}
SCANNING
import java.io.*;
import java.util.Scanner;
public class ScanXan {
public static void main(String[] args) throws IOException {
Scanner s = null;
try {
s = new Scanner(new BufferedReader(new FileReader("xanadu.txt")));
while (s.hasNext()) {
System.out.println(s.next());
}
} finally {
if (s != null) {
s.close();
}
}
}
}
SCANNING JAVA PRIMIT IVE TYPE TOKENS
import java.io.FileReader;
41
Concurrency (23-29 MAY-CODE)
import java.io.BufferedReader;
import java.io.IOException;
import java.util.Scanner;
import java.util.Locale;
public class ScanSum {
public static void main(String[] args) throws IOException {
Scanner s = null;
double sum = 0;
try {
s = new Scanner(new BufferedReader(new FileReader("usnumbers.txt")));
s.useLocale(Locale.US);
while (s.hasNext()) {
if (s.hasNextDouble()) {
sum += s.nextDouble();
} else {
s.next();
}
}
} finally {
s.close();
}
System.out.println(sum);
}
}
42
Concurrency (23-29 MAY-CODE)
And here's the sample input file, usnumbers.txt
8.5
32,767
3.14159
1,000,000.1
CONCURRENCY




Synchronized statement code
Using a simple lock: Simple lock use code
The lock() method locks the Lock instance so that all threads calling lock() are blocked
until unlock() is executed.
Simple Lock implementation: Simple lock implementation code
o Notice the while(isLocked) loop, which is also called a "spin lock". Spin locks and
the methods wait() and notify() are covered in more detail in Thread Signaling.
o While isLocked is true, the thread calling lock() is parked waiting in the wait() call.
o In case the thread should return unexpectedly from the wait() call without having
received a notify() call (AKA a Spurious Wakeup) the thread re-checks the
isLocked condition to see if it is safe to proceed or not, rather than just assume
that being awakened means it is safe to proceed.
o If isLocked is false, the thread exits the while(isLocked) loop, and sets isLocked
back to true, to lock the Lock instance for other threads calling lock().
o When the thread is done with the code in the critical section (the code between
lock() and unlock()), the thread calls unlock(). Executing unlock() sets isLocked
back to false, and notifies (awakens) one of the threads waiting in the wait() call
in the lock() method, if any.
REENTRANT SYNCHRONIZATION



This happens when synchronized code, directly or indirectly, invokes a method that
also contains synchronized code, and both sets of code use the same lock - the monitor
object the block is synchronized on.
A thread can acquire a lock that it already owns. Allowing a thread to acquire the same
lock more than once enables reentrant synchronization.
Without reentrant synchronization, synchronized code would have to take many
additional precautions to avoid having a thread cause itself to block.
43
Concurrency (23-29 MAY-CODE)

Making locks re-entrant: Reentrant lock Implementation
LOCK FAIRNESS


Java's synchronized blocks makes no guarantees about the sequence in which threads
trying to enter them are granted access.
One or more of the threads may never be granted access and access may always be
granted to other threads. This is called starvation.
CALLING UNLOCK() FROM A FINALLY-CLAUSE


Doing so makes sure that the Lock is unlocked in case an exception is thrown from the
code in the critical section.
If unlock() was not called from inside a finally-clause, and an exception was thrown from
the critical section, the Lock would remain locked forever, causing all threads calling
lock() on that Lock instance to halt indefinitely.
DEADLOCKS
THREAD DEADLOCK

A deadlock is when two or more threads are blocked waiting to obtain locks that some
of the other threads in the deadlock are holding. Deadlock can occur when multiple
threads need the same locks, at the same time, but obtain them in different order. See
Deadlock example

Deadlock can also include more than two threads. This makes it harder to detect.
DATABASE DEADLOCKS


A more complicated situation in which deadlocks can occur, is a database transaction. A
database transaction may consist of many SQL update requests. When a record is
updated during a transaction, that record is locked for updates from other transactions,
until the first transaction completes. Each update request within the same transaction
may therefore lock some records in the database.
If multiple transactions are running at the same time that need to update the same
records, there is a risk of them ending up in a deadlock.
DEADLOCK PREVENTION
LOCK ORDERING
44
Concurrency (23-29 MAY-CODE)



Deadlock occurs when multiple threads need the same locks but obtain them in
different order. If you make sure that all locks are always taken in the same order by
any thread, deadlocks cannot occur.
Example:
o Thread 1: lock A, lock B
o Thread 2:wait for A, lock C (when A locked)
o Thread 3: wait for A, wait for B, wait for C
o If a thread, like Thread 3, needs several locks, it must take them in the decided
order. It cannot take a lock later in the sequence until it has obtained the earlier
locks.
o For instance, neither Thread 2 nor Thread 3 can lock C until they have locked A
first. Since Thread 1 holds lock A, Thread 2 and 3 must first wait until lock A is
unlocked. Then they must succeed in locking A, before they can attempt to lock B
or C.
Lock ordering is a simple yet effective deadlock prevention mechanism. However, it can
only be used if you know about all locks needed ahead of taking any of the locks. This
is not always the case.
LOCK TIMEOUT



Put a timeout on lock attempts meaning a thread trying to obtain a lock will only try for
so long before giving up. If a thread does not succeed in taking all necessary locks within
the given timeout, it will backup, free all locks taken, wait for a random amount of time
and then retry. The random amount of time waited serves to give other threads trying to
take the same locks a chance to take all locks, and thus let the application continue
running without locking.
Example:
o Thread 1 locks A, Thread 2 locks B
o Thread 1 attempts to lock B but is blocked, Thread 2 attempts to lock A but is
blocked. Thread 1's lock attempt on B times out, Thread 1 backs up and releases
A as well. Thread 1 waits randomly (e.g. 257 millis) before retrying,
o Thread 2's lock attempt on A times out, Thread 2 backs up and releases B as well,
Thread 2 waits randomly (e.g. 43 millis) before retrying.
o In this example Thread 2 will retry taking the locks about 200 millis before Thread
1 and will therefore likely succeed at taking both locks. Thread 1 will then wait
already trying to take lock A. When Thread 2 finishes, Thread 1 will be able to
take both locks too (unless Thread 2 or another thread takes the locks in
between).
Bear in mind that the timeouts could be because the thread holding the lock (causing
the other thread to time out) takes a long time to complete its task not necessarily a
deadlock.
45
Concurrency (23-29 MAY-CODE)

Additionally, if enough threads compete for the same resources they still risk trying to
take the threads at the same time again and again, even if timing out and backing up.
This may most likely occur with more threads.
A problem with the lock timeout mechanism is that it is not possible to set a timeout for
entering a synchronized block in Java. You will have to create a custom lock class or use
one of the Java 5 concurrency constructs in the java.util.concurrency package.
DEADLOCK DETECTION



Deadlock detection is a heavier deadlock prevention mechanism aimed at cases in which
lock ordering isn't possible, and lock timeout isn't feasible.
Every time a thread takes a lock it is noted in a data structure (map, graph etc.) of
threads and locks. Additionally, whenever a thread requests a lock this is also noted in
this data structure.
When a thread requests a lock but the request is denied, the thread can traverse the
lock graph to check for deadlocks. For instance, if a Thread A requests lock 7, but lock 7
is held by Thread B, then Thread A can check if Thread B has requested any of the locks
Thread A holds (if any). If Thread B has requested so, a deadlock has occurred (Thread A
having taken lock 1, requesting lock 7, Thread B having taken lock 7, requesting lock 1).
Of course a deadlock scenario may be a lot more complicated than two threads holding
each others locks.
One possible action is to release all locks, backup, wait a random amount of time and then
retry. This is similar to the simpler lock timeout mechanism except threads only backup
when a deadlock has actually occurred. Not just because their lock requests timed out.
46
Concurrency (23-29 MAY-CODE)
However, if a lot of threads are competing for the same locks they may repeatedly end up in
a deadlock even if they back up and wait.
A better option is to determine or assign a priority of the threads so that only one (or a few)
thread backs up. The rest of the threads continue taking the locks they need as if no
deadlock had occurred. If the priority assigned to the threads is fixed, the same threads will
always be given higher priority. To avoid this you may assign the priority randomly
whenever a deadlock is detected.
LIVENESS

A concurrent application's ability to execute in a timely manner is known as its liveness.
DEADLOCK

When Deadlock runs, it's extremely likely that both threads will block and the block will
not come to an end, because each thread is waiting for the other to exit bow.
STARVATION


Starvation describes a situation where a thread is unable to gain regular access to
shared resources as they are made unavailable for long periods by "greedy" threads.
For example, suppose an object provides a synchronized method that often takes a long
time to return. If one thread invokes this method frequently, other threads that also
need frequent synchronized access to the same object will often be blocked.
CAUSES
1. Threads with high priority swallow all CPU time from threads with lower priority
The higher the priority the more CPU time the thread is granted. You can set the priority of
threads between 1 and 10. Exactly how this is interpreted depends on the operating system
your application is running on. For most applications you are better off leaving the priority
unchanged.
2. Threads are blocked indefinitely waiting to enter a synchronized block
Java's synchronized code block makes no guarantee about the sequence in which threads
waiting to enter the synchronized block are allowed to enter. This means that there is a
theoretical risk that a thread remains blocked forever trying to enter the block, because
other threads are constantly granted access before it.
3. Threads waiting on an object (called wait() on it) remain waiting indefinitely
47
Concurrency (23-29 MAY-CODE)
The notify() method makes no guarantee about what thread is awakened if multiple
thread have called wait() on the object notify() is called on. It could be any of the threads
waiting. Therefore there is a risk that a thread waiting on a certain object is never
awakened because other waiting threads are always awakened instead of it.
SOLUTION
USING LOCKS INSTEAD OF SYNCHRONIZED BLOCKS
Remember that a thread calling wait() releases the synchronization lock on the Lock
instance, so threads waiting to enter lock() can now do so. The result is that multiple threads
can end up having called wait() inside lock().
Synchronized blocks makes no guarantees about what thread is being granted access if
more than one thread is waiting to enter. Nor does wait() make any guarantees about what
thread is awakened when notify() is called.
If instead each thread calls wait() on a separate object, so that only one thread has called
wait() on each object, the Lock class can decide which of these objects to call notify() on,
thereby effectively selecting exactly what thread to awaken.
FAIR LOCK
every thread calling lock() is now queued, and only the first thread in the queue is allowed
to lock the FairLock instance, if it is unlocked. All other threads are parked waiting until they
reach the top of the queue.
LIVELOCK



A thread often acts in response to the action of another thread. If the other thread's
action is also a response to the action of another thread, then livelock may result.
However, the threads are not blocked — they are simply too busy responding to each
other to resume work.
This is comparable to two people attempting to pass each other in a corridor: Alphonse
moves to his left to let Gaston pass, while Gaston moves to his right to let Alphonse
pass. Seeing that they are still blocking each other, Alphone moves to his right, while
Gaston moves to his left. They're still blocking each other, so...
GUARDED BLOCKS
48
Concurrency (23-29 MAY-CODE)

Such a block begins by polling a condition that must be true before the block can
proceed. There are a number of steps to follow in order to do this correctly.
Suppose, for example guardedJoy is a method that must not proceed until a shared
variable joy has been set by another thread. Such a method could, in theory, simply loop
until the condition is satisfied, but that loop is wasteful, since it executes continuously
while waiting.

public void guardedJoy() {
// Simple loop guard. Wastes
// processor time. Don't do this!
while(!joy) {}
System.out.println("Joy has been achieved!");
}

A more efficient guard invokes Object.wait to suspend the current thread. The
invocation of wait does not return until another thread has issued a notification that
some special event may have occurred — though not necessarily the event this thread is
waiting for:
public synchronized void guardedJoy() {
// This guard only loops once for each special event, which may not
// be the event we're waiting for.
while(!joy) {
try {
wait();
} catch (InterruptedException e) {}
}
System.out.println("Joy and efficiency have been achieved!");
}

Always invoke wait inside a loop that tests for the condition being waited for.
49
Concurrency (23-29 MAY-CODE)






Don't assume that the interrupt was for the particular condition you were waiting for, or
that the condition is still true.
When a thread invokes d.wait, it must own the intrinsic lock for d — otherwise an error
is thrown. Invoking wait inside a synchronized method is a simple way to acquire the
intrinsic lock.
When wait is invoked, the thread releases the lock and suspends execution. At some
future time, another thread will acquire the same lock and invoke Object.notifyAll,
informing all threads waiting on that lock that something important has happened:
Some time after the second thread has released the lock, the first thread reacquires the
lock and resumes by returning from the invocation of wait.
There is a second notification method, notify, which wakes up a single thread.
Because notify doesn't allow you to specify the thread that is woken up, it is useful only
in massively parallel applications — that is, programs with a large number of threads, all
doing similar chores. In such an application, you don't care which thread gets woken up.
IMMUTABLE OBJECTS



An object is considered immutable if its state cannot change after it is constructed.
Using immutable objects is widely accepted as a sound strategy for creating simple,
reliable code.
Immutable objects are particularly useful in concurrent applications. Since they cannot
change state, they cannot be corrupted by thread interference or observed in an
inconsistent state.
The reluctance to using immutable objects is usually attributed to the cost of creating a
new object as opposed to updating an object in place. This can be offset by some of the
efficiencies associated with immutable objects including: decreased overhead due to
garbage collection and the elimination of code needed to protect mutable objects from
corruption.
A STRATEGY FOR DEFINING IMMUTABLE OBJECTS
The following rules define a simple strategy for creating immutable objects. However, such
strategies require sophisticated analysis and are not for beginners.
1. Don't provide "setter" methods — methods that modify fields or objects referred to by
fields.
2. Make all fields final and private.
3. Don't allow subclasses to override methods.
o
The simplest way to do this is to declare the class as final.
50
Concurrency (23-29 MAY-CODE)
o
A more sophisticated approach is to make the constructor private and construct
instances in factory methods.
4. If the instance fields include references to mutable objects, don't allow those objects to
be changed:
o
Don't provide methods that modify the mutable objects.
o
Don't share references to the mutable objects. Never store references to
external, mutable objects passed to the constructor; if necessary, create copies,
and store references to the copies. Similarly, create copies of your internal
mutable objects when necessary to avoid returning the originals in your
methods.
HIGH LEVEL CONCURRENCY OBJECTS




These are higher-level building blocks needed for more advanced tasks for massively
concurrent applications that fully exploit today's multiprocessor and multi-core
systems.
Introduced with version 5.0 of the Java platform.
Most of these features are implemented in the new java.util.concurrent packages.
There are also new concurrent data structures in the Java Collections Framework.
LOCK OBJECTS






Synchronized code relies on a simple kind of reentrant lock. This kind of lock is easy to
use, but has many limitations.
More sophisticated locking idioms are supported by the java.util.concurrent.locks
package.
Lock objects work very much like the implicit locks used by synchronized code. As with
implicit locks, only one thread can own a Lock object at a time. Lock objects also
support a wait/notify mechanism, through their associated Condition objects.
The biggest advantage of Lock objects over implicit locks is their ability to back out of an
attempt to acquire a lock.
The tryLock method backs out if the lock is not available immediately or before a
timeout expires (if specified).
The lockInterruptibly method backs out if another thread sends an interrupt before the
lock is acquired.
EXECUTORS

In all of the previous examples, there's a close connection between the task being done
by a new thread, as defined by its Runnable object, and the thread itself, as defined by a
51
Concurrency (23-29 MAY-CODE)

Thread object. This works well for small applications, but in large-scale applications, it
makes sense to separate thread management and creation from the rest of the
application.
Objects that encapsulate these functions are known as executors.
EXECUTOR INTERFACES
The java.util.concurrent package defines three executor interfaces:



Executor, a simple interface that supports launching new tasks.
ExecutorService, a subinterface of Executor, which adds features that help manage the
lifecycle, both of the individual tasks and of the executor itself.
ScheduledExecutorService, a subinterface of ExecutorService, supports future and/or
periodic execution of tasks.
THE EXECUTOR INTERFACE

The Executor interface provides a single method, execute, designed to be a drop-in
replacement for a common thread-creation idiom. If r is a Runnable object, and e is
an Executor object you can replace
(new Thread(r)).start();
with
e.execute(r);

However, the definition of execute is less specific. The low-level idiom creates a new
thread and launches it immediately.
THE EXECUTORSERVICE INTERFACE




The ExecutorService interface supplements execute with a similar, but more
versatile submit method. Like execute, submit accepts Runnable objects, but also
accepts Callable objects, which allow the task to return a value.
The submit method returns a Future object, which is used to retrieve the Callable return
value and to manage the status of both Callable and Runnable tasks.
ExecutorService also provides methods for submitting large collections
of Callable objects.
Finally, ExecutorService provides a number of methods for managing the shutdown of
the executor. To support immediate shutdown, tasks should handle interrupts correctly.
THE SCHEDULEDEXECUTORSERVICE INTERFACE
52
Concurrency (23-29 MAY-CODE)


The ScheduledExecutorService interface supplements the methods of its parent
ExecutorService with schedule, which executes a Runnable or Callable task after a
specified delay.
In addition, the interface defines scheduleAtFixedRate and scheduleWithFixedDelay,
which executes specified tasks repeatedly, at defined intervals.
THREAD POOLS


Most of the executor implementations in java.util.concurrent use thread pools, which
consist of worker threads. This kind of thread exists separately from the Runnable and
Callable tasks it executes and is often used to execute multiple tasks.
Using worker threads minimizes the overhead due to thread creation. Thread objects
use a significant amount of memory, and in a large-scale application, allocating and
deallocating many thread objects creates a significant memory management overhead.
FIXED THREAD POOL





One common type of thread pool is the fixed thread pool.
This type of pool always has a specified number of threads running; if a thread is
somehow terminated while it is still in use, it is automatically replaced with a new
thread.
Tasks are submitted to the pool via an internal queue, which holds extra tasks whenever
there are more active tasks than threads.
An important advantage of the fixed thread pool is that applications using it degrade
gracefully. To understand this, consider a web server application where each HTTP
request is handled by a separate thread:
o If the application simply creates a new thread for every new HTTP request, and
the system receives more requests than it can handle immediately, the
application will suddenly stop responding toall requests when the overhead of all
those threads exceed the capacity of the system.
o With a limit on the number of the threads that can be created, the application
will not be servicing HTTP requests as quickly as they come in, but it will be
servicing them as quickly as the system can sustain.
A simple way to create an executor that uses a fixed thread pool is to invoke
the newFixedThreadPoolfactory method in java.util.concurrent.Executors This class also
provides the following factory methods:

The newCachedThreadPool method creates an executor with an expandable thread
pool. This executor is suitable for applications that launch many short-lived tasks.

The newSingleThreadExecutor method creates an executor that executes a single
task at a time.
53
Concurrency (23-29 MAY-CODE)

Several factory methods are ScheduledExecutorService versions of the above
executors.
FORK/JOIN





The fork/join framework is an implementation of the ExecutorService interface that
helps you take advantage of multiple processors.
It is designed for work that can be broken into smaller pieces recursively.
The goal is to use all the available processing power to enhance the performance of your
application.
As with any ExecutorService implementation, the fork/join framework distributes tasks
to worker threads in a thread pool. The fork/join framework is distinct because it uses a
work-stealing algorithm. Worker threads that run out of things to do can steal tasks
from other threads that are still busy.
The center of the fork/join framework is the ForkJoinPool class, an extension of the
AbstractExecutorService class. ForkJoinPool implements the core work-stealing
algorithm and can execute ForkJoinTask processes.
Standard Implementations

Besides using the fork/join framework to implement custom algorithms for tasks to be
performed concurrently on a multiprocessor system (such as the ForkBlur.java example
in the previous section), there are some generally useful features in Java SE which are
already implemented using the fork/join framework. One such implementation,
introduced in Java SE 8, is used by thejava.util.Arrays class for its parallelSort() methods.
These methods are similar to sort(), but leverage concurrency via the fork/join
framework. Parallel sorting of large arrays is faster than sequential sorting when run on
multiprocessor systems.
CONCURRENT COLLECTIONS


The java.util.concurrent package includes a number of additions to the Java Collections
Framework. They help avoid Memory Consistency Errors by defining a happens-before
relationship between an operation that adds an object to the collection with subsequent
operations that access or remove that object.
They are most easily categorized by the collection interfaces provided:

BlockingQueue defines a first-in-first-out data structure that blocks or times out
when you attempt to add to a full queue, or retrieve from an empty queue.

ConcurrentMap is a subinterface of java.util.Map that defines useful atomic
operations. These operations remove or replace a key-value pair only if the key is
54
Abstract Classes and Interfaces (09-15 MAY - CODE & STUDY)
present, or add a key-value pair only if the key is absent. Making these operations
atomic helps avoid synchronization. The standard general-purpose implementation
of ConcurrentMap is ConcurrentHashMap, which is a concurrent analog of HashMap.

ConcurrentNavigableMap is a subinterface of ConcurrentMap that supports
approximate matches. The standard general-purpose implementation
of ConcurrentNavigableMap isConcurrentSkipListMap, which is a concurrent analog
of TreeMap.
ATOMIC VARIABLES




The java.util.concurrent.atomic package defines classes that support atomic operations
on single variables.
All classes have get and set methods that work like reads and writes
on volatile variables. That is, a set has a happens-before relationship with any
subsequent get on the same variable.
The atomiccompareAndSet method also has these memory consistency features, as do
the simple atomic arithmetic methods that apply to integer atomic variables.
Replacing an int field with an AtomicInteger allows us to prevent thread interference
without resorting to synchronization and we would avoid the liveness impact of
unnecessary synchronization
CONCURRENT RANDOM NUMBERS



In JDK 7, java.util.concurrent includes a convenience class, ThreadLocalRandom, for
applications that expect to use random numbers from multiple threads or ForkJoinTasks.
For concurrent access, using ThreadLocalRandom instead of Math.random() results in
less contention and, ultimately, better performance.
All you need to do is call ThreadLocalRandom.current(), then call one of its methods to
retrieve a random number. Here is one example:
int r = ThreadLocalRandom.current() .nextInt(4, 77)
5) ABSTRACT CLASSES AND INTERFACES (09-15 MAY - CODE & STUDY)
TBC
6) CONSTRUCTORS (09-15 MAY - CODE & STUDY)
DEFINING A CONSTRUCTOR IN JAVA
Java constructors are special methods that are called to instantiate an object.
55
Constructors (09-15 MAY - CODE & STUDY)
Example: MyClass myObject=new MyClass();
An object is created using a constructor with no arguments: The no-arg constructor.
public class MyClass {
public MyClass() {
}
}




The 1st part of the constructor declaration (public) is an access modifier. See access modifiers section for
the different types of access modifiers.
The 2nd part of the constructor declaration (MyClass) is the name of the class the constructor belongs to.
This tells the Java compiler that we are looking to construct an object of type: MyClass.
The 3rd part is a list of parameters in parenthesis. These are used by the constructor to initialise fields
required by the object or to create a custom object with different states.
Lastly, there's the body of the constructor in curly brackets { }
Constructor Overloading - Multiple Constructors for a Java Class
Constructor overloading occurs when a class has multiple constructors.
A class can have multiple constructors, as long as they have different parameters – the signature.
public class ExampleClass {
private String name;
/* no-arg constructor */
public ExampleClass() {}
public ExampleClass(String _objectName) {this.name= _ objectName;}
}
Default, no-arg Constructor
If you don't define any constructor, the Java compiler will insert a default, no-argument constructor for you. If
you do define a constructor for your class, then the Java compiler will not insert the default no-argument
constructor into your class.
A Java constructor parameter can have the same name as a field. If a constructor parameter has the same
name as a field, the Java compiler has problems knowing which you refer to. By default, if a parameter (or
local variable) has the same name as a field in the same class, the parameter (or local variable) "shadows" for
the field. Look at this constructor example:
public class Employee {
56
Constructors (09-15 MAY - CODE & STUDY)
private String firstName = null;
private String lastName = null;
private int birthYear = 0;
public Employee(String firstName,
String lastName,
int birthYear ) {
firstName = firstName;
lastName = lastName;
birthYear = birthYear;
}
}
Inside the constructor of the Employee class the firstName, lastName and birthYear identifiers now refer to the
constructor parameters, not to the Employee fields with the same names. Thus, the constructor now just sets
the parameters equal to themselves. The Employee fields are never initialized.
To signal to the Java compiler that you mean the fields of the Employee class and not the parameters, put the
this keyword and a dot in front of the field name. Here is how the Java constructor declaration from before
looks with that change:
public class Employee {
private String firstName = null;
private String lastName = null;
private int birthYear = 0;
57
Constructors (09-15 MAY - CODE & STUDY)
public Employee(String firstName,
String lastName,
int birthYear ) {
this.firstName = firstName;
this.lastName = lastName;
this.birthYear = birthYear;
}
}
Now the Employee fields are correctly initialized inside the constructor.
Calling a Constructor
You call a constructor when you create a new instance of the class containing the constructor. Here is a Java
constructor call example:
MyClass myClassVar = new MyClass();
This example invokes (calls) the no-argument constructor for MyClass as defined earlier in this text.
In case you want to pass parameters to the constructor, you include the parameters between the parentheses
after the class name, like this:
MyClass myClassVar = new MyClass(1975);
This example passes one parameter to the MyClass constructor that takes an int as parameter.
Calling a Constructor From a Constructor
58
Constructors (09-15 MAY - CODE & STUDY)
In Java it is possible to call a constructor from inside another constructor. When you call a constructor from
inside another constructor, you use the this keyword to refer to the constructor. Here is an example of calling
one constructor from within another constructor in Java:
public class Employee {
private String firstName = null;
private String lastName = null;
private int birthYear = 0;
public Employee(String first,
String last,
int year ) {
firstName = first;
lastName = last;
birthYear = year;
}
public Employee(String first, String last){
this(first, last, -1);
}
}
Notice the second constructor definition. Inside the body of the constructor you find this Java statement:
this(first, last, -1);
The this keyword followed by parentheses and parameters means that another constructor in the same Java
class is being called. Which other constructor that is being called depends on what parameters you pass to the
59
Constructors (09-15 MAY - CODE & STUDY)
constructor call (inside the parentheses after the this keyword). In this example it is the first constructor in the
class that is being called.
Calling Constructors in Superclasses
In Java a class can extend another class. When a class extends another class it is also said to "inherit" from the
class it extends. The class that extends is called the subclass, and the class being extended is called the
superclass. Inheritance is covered in more detail in my tutorial about inheritance in Java.
A class that extends another class does not inherit its constructors. However, the subclass must call a
constructor in the superclass inside one of the subclass constructors!
Look at the following two Java classes. The class Car extends (inherits from) the class Vehicle.
public class Vehicle {
private String regNo = null;
public Vehicle(String no) {
this.regNo = no;
}
}
public class Car extends Vehicle {
private String brand = null;
public Car(String br, String no) {
super(no);
this.brand = br;
}
}
Notice the constructor in the Car class. It calls the constructor in the superclass using this Java statement:
60
File IO and Serialization (30 MAY – 05 JUN)
super(no);
Using the keyword super refers to the superclass of the class using the super keyword. When super keyword is
followed by parentheses like it is here, it refers to a constructor in the superclass. In this case it refers to the
constructor in the Vehicle class. Because Car extends Vehicle, the Car constructors must all call a constructor in
the Vehicle.
Java Constructor Access Modifiers
The access modifier of a constructor determines what classes in your application that are allowed to call that
constructor. The access modifiers are explained in more detail in the text on Java access modifiers.
For instance, if a constructor is declared protected then only classes in the same package, or subclasses of that
class can call that constructor.
A class can have multiple constructors, and each constructor can have its own access modifier. Thus, some
constructors may be available to all classes in your application, while other constructors are only available to
classes in the same package, subclasses, or even only to the class itself (private constructors).
7) FILE IO AND SERIALIZATION (30 MAY – 05 JUN)
I/O STREAMS



An I/O Stream represents an input source or an output destination. A stream can
represent many different kinds of sources and destinations, including disk files,
devices, other programs, and memory arrays.
Streams support many different kinds of data, including simple bytes, primitive data
types, localized characters, and objects. Some streams simply pass on data; others
manipulate and transform the data in useful ways.
No matter how they work internally, all streams present the same simple model to
programs that use them: A stream is a sequence of data. A program uses an input
stream to read data from a source, one item at a time:
Reading information into a program:
61
File IO and Serialization (30 MAY – 05 JUN)
Writing information from a program:
BYTE STREAMS




Programs use byte streams to perform input and output of 8-bit bytes. All byte stream
classes are descended from InputStream and OutputStream.
Closing a stream when it's no longer needed is very important. This practice helps avoid
serious resource leaks.
Byte streams should only be used for the most primitive I/O. We discuss it here
because all other stream types are built on byte streams.
Code example: Using byte streams
CHARACTER STREAMS





The Java platform stores character values using Unicode conventions. Character
stream I/O automatically translates this internal format to and from the local
character set.
In Western locales, the local character set is usually an 8-bit superset of ASCII.
Input and output done with stream classes automatically translates to and from the
local character set.
A program that uses character streams in place of byte streams automatically adapts to
the local character set and is ready for internationalization.
If internationalization becomes a priority, your program can be adapted without
extensive recoding. See the Internationalization trail for more information.
62
File IO and Serialization (30 MAY – 05 JUN)


All character stream classes are descended from Reader and Writer. As with byte
streams, there are character stream classes that specialize in file
I/O: FileReader and FileWriter.
The character value is held in the last 16 bits compared to the last 8 bits in bytestream.

Code example: Using character streams

Character streams are often "wrappers" for byte streams. The character stream uses
the byte stream to perform the physical I/O, while the character stream handles
translation between characters and bytes. FileReader, for example,
uses FileInputStream, while FileWriter uses FileOutputStream
There are two general-purpose byte-to-character "bridge"
streams: InputStreamReader and OutputStreamWriter. Use them to create character
streams when there are no prepackaged character stream classes that meet your needs.

Line-Oriented I/O



Character I/O usually occurs in bigger units than single characters. One common unit is
the line: a string of characters with a line terminator at the end. A line terminator can
be a carriage-return/line-feed sequence ("\r\n"), a single carriage-return ("\r"), or a
single line-feed ("\n"). Supporting all possible line terminators allows programs to read
text files created on any of the widely used operating systems.
To do this, we have to use two classes we haven't seen before, BufferedReader and
PrintWriter.
Code example: Line-Oriented I/O
BUFFERED STREAMS







Most of the examples we've seen so far use unbuffered I/O.
This means each read or write request is handled directly by the underlying OS.
This can make a program much less efficient, since each such request often triggers disk
access, network activity, or some other operation that is relatively expensive.
To reduce this kind of overhead, the Java platform implements buffered I/O streams.
Buffered input streams read data from a memory area known as a buffer; the native
input API is called only when the buffer is empty. Similarly, buffered output streams
write data to a buffer, and the native output API is called only when the buffer is full.
A program can convert an unbuffered stream into a buffered stream using the wrapping
idiom we've used several times now, where the unbuffered stream object is passed to
the constructor for a buffered stream class.
Example:
o inputStream = new BufferedReader(new FileReader("xanadu.txt"));
o outputStream = new BufferedWriter(new FileWriter("characteroutput.txt"));
There are four buffered stream classes used to wrap unbuffered streams:
63
File IO and Serialization (30 MAY – 05 JUN)
o BufferedInputStream and BufferedOutputStream create buffered byte streams,
o BufferedReader and BufferedWriter create buffered character streams.
Flushing Buffered Streams



It often makes sense to write out a buffer at critical points, without waiting for it to fill.
This is known as flushing the buffer.
Some buffered output classes support autoflush, specified by an optional constructor
argument. When autoflush is enabled, certain key events cause the buffer to be flushed.
For example, an autoflush PrintWriter object flushes the buffer on every invocation
of println or format.
To flush a stream manually, invoke its flush method. The flush method is valid on any
output stream, but has no effect unless the stream is buffered.
SCANNING AND FORMATTING

The scanner and formatting APIs provide capability to deal with translating to and from
neatly formatted data.
o The scanner API breaks input into individual tokens associated with bits of
data.
o The formatting API assembles data into nicely formatted, human-readable
form.
SCANNING

The Scanner
breaks down formatted input into tokens and translates individual tokens
according to their data type.
BREAKING INPUT INTO TOKENS


The scanner uses white space to separate tokens by default.
White space characters include blanks, tabs, and line terminators. For the full list, refer
to the documentation for Character.isWhitespace.)
 To use a different token separator, invoke useDelimiter().
 Specify a regular expression e.g. for a comma, followed by white space, invoke

s.useDelimiter(",\\s*");
Scanning example - a program that reads the individual words inxanadu.txt and prints

them out, one per line.
Close the scanner after use to close underlying stream.
TRANSLATING INDIVIDUAL TOKENS
 The scanning example treats all input tokens as simple String values.
64
File IO and Serialization (30 MAY – 05 JUN)
 The scanner supports tokens for all of the Java language's primitive types (except
for char), as well as BigInteger and BigDecimal.
 Numeric values can use thousands separators. Thus, in a US locale, Scanner correctly
reads the string "32,767" as representing an integer value.
 The ScanSum example reads a list of double values and adds them up.
 Thousands separators and decimal symbols are locale specific.
 The period will be a different character in some locales, because System.out is
a PrintStream object, and that class doesn't provide a way to override the default locale.
We could override the locale for the whole program — or we could just use formatting,
as described next
FORMATTING




Formatting is implemented by instances of the PrintWriter for characters and
PrintStream for bytes.
In addition to the standard set of write methods, both PrintStream
and PrintWriter implement methods for converting internal data into formatted output.
There are two levels of formatting:
o Standard formatting with print and println
o Formatting for almost any number of values based on a format string, with
options for precise formatting using the format method.
Format strings support many features. see format string syntax in the API specification.
It can also contain several additional elements that further customize the formatted
output.
ELEMENTS OF A FORMAT SPECIFIER.

The elements must appear in the order shown. Working from the right, the optional
elements are:
o Precision. For floating point values, this is the mathematical precision of the
formatted value. For s and other general conversions, this is the maximum width
of the formatted value; the value is right-truncated if necessary.
o Width. The minimum width of the formatted value; the value is padded if
necessary. By default the value is left-padded with blanks.
o Flags specify additional formatting options. + flag specifies that the number
should always be formatted with a sign, and the 0 flag specifies that 0 is the
padding character. Other flags include - (pad on the right) and, (format number
65
File IO and Serialization (30 MAY – 05 JUN)
with locale-specific thousands separators). Note that some flags cannot be used
with certain other flags or with certain conversions.
o The Argument Index allows you to explicitly match a designated argument. You
can also specify< to match the same argument as the previous specifier.
I/O FROM THE COMMAND LINE

Java supports command line interaction in two ways: Standard Streams and Console.
STANDARD STREAM






Many Operating Systems have Standard Streams and read input from the keyboard and
write output to the display by default.
They also support I/O on files and between programs through the command line
interpreter.
Java supports three Standard Streams on the command line:
o Standard Input- System.in
o Standard Output-System.out
o Standard Error-System.err.
These objects are defined automatically and do not need to be opened.
Standard Output and Standard Error are both output separately to allow the user to
divert regular output and deal with error messages separately. More details should be
available in the command line interpreter documentation.
These Standard Streams are byte streams historically.
o System.out and System.err are defined as PrintStream objects. However,
PrintStream has an internal character stream object to emulate many of the
features of character streams.
o System.in has no character stream features but you can wrap it
in InputStreamReader.
InputStreamReader characterInputStream = new InputStreamReader(System.in);
CONSOLE





Console Is a more advanced alternative to Standard Streams.
It has more features besides those from the Standard Streams. It is particularly useful for
secure password entry.
It has true character input and output streams through its reader and writer methods.
If the Console object is available, invoking System.console() will return a value,
otherwise it will return NULL. This could be because the OS doesn't support it or because
the program was launched in a non-interactive environment.
The Console object has the readPassword method which supports secure password
entry. It enables secure password entry in two ways:
o Suppresses echoing- password is not visible on the user's screen.
o Returns a character array (not a String) so the password can be overwritten,
removing it from memory as soon as it is no longer needed.
66
File IO and Serialization (30 MAY – 05 JUN)
DATA STREAMS







Data streams support binary I/O of primitive data type values:
boolean, char, byte, short, int,long, float, and double as well as String values.
Data streams implement the DataInput interface or the DataOutput interface.
The most used implementations are DataInputStream and DataOutputStream.
DataStreams detects an end-of-file condition by catching EOFException, instead of
testing for an invalid return value. All implementations of DataInput methods
use EOFException instead of return values.
Each specialized write in DataStreams is exactly matched by the corresponding
specialized read e.g. out.writeDouble(doubleValue), in.readDouble(). Make sure to
match output types and input types.
The input stream is simple binary data and does not indicate the type of individual
values, or where they begin in the stream.
DataStreams use floating point numbers to represent monetary values which is
considered a bad technique. This is because floating point is bad for precise values
especially decimal fractions as they don’t have a binary representation. The correct type
BigDecimal is an object type and won't work with data streams.
OBJECT STREAMS









Object streams support I/O of objects.
Most standard classes implement the interface Serializable and therefore support
serialization of their objects.
The object stream classes are ObjectInputStream and ObjectOutputStream
implementing ObjectInput and ObjectOutput interfaces. These are subinterfaces
of DataInput andDataOutput. Thus ObjectInputStream and ObjectOutputStream
implement all the primitive data I/O methods of Data Streams.
An Object stream can thus contain both primitive and object values.
If readObject() doesn't return the object type expected, attempting to cast it to the
correct type may throw a ClassNotFoundException.
Many objects contain references to other objects. If readObject is to reconstitute an
object from a stream, it has to be able to reconstitute all of the objects the original
object referred to. writeObject traverses the entire web of object references and writes
all objects in that web onto the stream. Thus a single invocation of writeObject can
cause a large number of objects to be written to the stream.
A stream can only contain one copy of an object, though it can contain any number of
references to it. Thus if you explicitly write an object to a stream twice, you're really
writing only the reference twice.
Each writeObject has to be matched by a readObject
If a single object is written to two different streams, it is effectively duplicated — a single
program reading both streams back will see two distinct objects.
FILE I/O (FEATURING NIO.2)

This is the file I/O mechanism introduced in the JDK 7 release
67
File IO and Serialization (30 MAY – 05 JUN)


The Path class is the primary entry point for the package.
The Files class contains methods that deal with file operations.
THE PATH





Most file systems store files in a tree structure with one or more root nodes at the top of
the tree (Microsoft Windows supports multiple root nodes).
Under the root node, there are files and directories (folders in Microsoft Windows). Each
directory can contain almost limitless files and subdirectories.
The root node maps to a volume e.g. C:\ or D:\ for Microsoft and a single root node for
the Solaris OS denoted by /.
o A file is identified by its path through the file system from the root node e.g.
/home/user/text.txt – Solaris (uses the forward slash (/) delimiter)
o C:\home\user\text.txt – Microsoft (uses the backslash (\) delimiter)
These are absolute paths – All the information required to find the file is in the path.
A file location can also be represented relative to another location in the file system. As
such we need to combine the relative path with the absolute path of the
original/primary location to find the file. Relative path is generally used to shorten the
length of the path representation.
A symbolic link is a special file that references/ redirects to another file (target)
transparent to the application or user accessing the file. However, when a symbolic link
is deleted, or renamed it’s the link itself that will be renames or changed, not the target
of the link. The process of substituting the actual location in the file system for the
symbolic link is called resolving the link. If not carefully used, you could encounter a
circular reference. This is when the target of a link points back to the original link. This
could cause a problem when a program is recursively walking a directory structure.
THE PATH CLASS



Java’s representation of a path in the file system which contains the file name and
directory list used to resolve the location of the file.
The path instance is system dependent and will be different for Windows and Solaris.
Operations: Once created, you can append to it, extract pieces of it, compare it to
another path. Used with the Files class, you can create and look for the file represented
by the path, open it, delete it, change its permissions etc.
PATH OPERATIONS
CREATING A PATH



These are the syntactic operations as they operate on the path.
A Path instance specifies the location of a file or directory with a series of one or
more names.
You can easily create a Path object by using one of the get methods from
the Paths(note the plural) helper class. This is a shorthand to getting the path using
FileSystems.getDefault().
68
File IO and Serialization (30 MAY – 05 JUN)

Path path = FileSystems.getDefault().getPath("/users/testUser");
Using the Paths helper class:
o Path path = Paths.get("/tmp ");
o Path path = Paths.get(args[0]);
o Path path = Paths.get(URI.create("file:///Users/testUser/TestFile.java"));
o Path p5 = Paths.get(System.getProperty("user.home"),"testDir", "test.txt");
o Creates the file in the user’s home directory as
/home/testUser/testDir/test.txt for solaris and C:\testUser\testDir\test.txt on
windows.
RETRIEVING INFORMATION ABOUT A PATH
Think of the Path as storing these name elements as a sequence. The highest element in the
directory structure would be located at index 0. The lowest element in the directory
structure would be located at index [n-1]. n is the number of name elements in the Path.
Methods are available for retrieving individual elements or a subsequence of the Path using
these indexes. Example methods available for retrieving information about the path:








Note: Root is / in solaris and C:\ in windows.
path.toString() - Returns the string representation of the Path with minor syntactic
cleanup.
path.getFileName() - Returns the file name or the last element of the sequence of
name elements.
path.getName(0) - Returns the path element corresponding to the specified index.
The 0th element is the path element closest to the root.
path.getNameCount()- Returns the number of elements in the path.
path.subpath(0,2)- Returns the subsequence of the Path (not including a root
element) as specified by the beginning and ending indexes.
path.getParent()- Returns the path of the parent directory.
path.getRoot()- Returns the root of the path. This method will return null if a
relative path is used rather than absolute.
REMOVING REDUNDANCIES FROM A PATH



normalize method removes any redundant elements, which includes any "." or
"directory/.." occurrences. Many file systems use "." notation to denote the current
directory and ".." to denote the parent directory.
normalize doesn't check at the file system when it cleans up a path. It is a purely
syntactic operation.
To clean up a path while ensuring that the result locates the correct file, you can use
thetoRealPath method.
CONVERTING A PATH

toUri -To a string that can be opened from a browser.
69
File IO and Serialization (30 MAY – 05 JUN)



toAbsolutePath - To convert to an absolute path. Returns the same path object if the
path given is absolute. The file does not need to exist for this method to work.
toRealPath method returns the real path of an existing file, performing the following
operations in one:
o If true is passed to this method and the file system supports symbolic links, it
resolves any symbolic links in the path.
o Returns an absolute path if the path is relative.
o Removes any redundant elements if the Path contains any.
This method will throw a NoSuchFileException if the file does not exist or cannot be
accessed.
JOINING PATHS

You can combine paths by using the resolve method. You pass in a partial path ,
which is a path that does not include a root element, and that partial path is
appended to the original path.
CREATING A PATH BETWEEN TWO PATHS

We can construct a path from one location in the file system to another location
using the relativize method. The new path is relative to the original path.
Path p1 = Paths.get("home");
Path p3 = Paths.get("home/tom/email");
Path p1_to_p3 = p1.relativize(p3); // results in tom/email
Path p3_to_p1 = p3.relativize(p1); // Result in ../..

This method required the paths to include a root element. As such it is system
dependent.
COMPARING TWO PATHS





startsWith andendsWith to test if a path begins or ends with a particular string.
isSameFile – To verify that two Path objects locate the same file
equals –to test two paths for equality.
The Path class implements the Iterable interface. The iterator method returns an
object that enables you to iterate over the name elements in the path with the first
element being the one closest to the root in the directory tree.
The Path class also implements the Comparable interface. Use it to
compare Path objects by using compareTo, useful for sorting.
FILE OPERATIONS
70
File IO and Serialization (30 MAY – 05 JUN)



The Files class is the other primary entrypoint of the java.nio.file package.
It offers a rich set of static methods for reading, writing, and manipulating files and
directories.
Files methods work on instances of Path objects.
Releasing System Resources

Most resources for File IO e.g. streams or channels, implement or extend
the java.io.Closeable interface. As such the close method must be invoked to release
the resource when no longer required to avoid impacting the application's
performance. The try-with-resources statement from Java 7 closes resources for you.
Catching Exceptions






With File IO, unexpected conditions such as a file doesn't exist, the program doesn't
have access to the file system, the default file system implementation does not
support a particular function are common.
All methods that access the file system can throw an IOException.
Catch these exceptions in a try-with-resources statement which causes the compiler
to automatically generate code to close the resource(s) when no longer required.
You can use the try catch closing resources in a finally block.
Other specific exceptions extend FileSystemException which has some useful
methods:
o getFile returns the file involved
o getMessage returns the detailed message string
o getReason returns the reason why the file system operation failed
o getOtherFile returns the "other" file involved, if any.
Your code should always handle exceptions.
Varargs




Some Files methods accept an arbitrary number of arguments when flags are
specified e.g. the CopyOption below accepts a variable number of arguments
(varargs)
Path Files.move(Path, Path, CopyOption...)
You can pass it a comma-separated list of values or an array (CopyOption[]) of
values.
For varargs syntax: Arbitrary Number of Arguments.
Atomic Operations


Some Files methods e.g. move can perform operation that cannot be interrupted or
"partially" performed (Either the entire operation is performed or the operation
fails) in some file systems - atomic operations.
This is important when you have multiple processes operating on the same area of
the file system to guarantee that each process accesses a complete file.
71
File IO and Serialization (30 MAY – 05 JUN)
Method Chaining



A technique where you invoke a method that returns an object and immediately
invoke a method on that object that returns yet another object, and so on.
Method chaining produces compact code and avoid declaring temporary variables
Many File IO methods support method chaining.
The Glob







Glob is a pattern using wildcards to specify filenames. For example *.java specifies
all files with extension ‘java’.
Two wildcard characters that are widely used are * and ?. Asterisk * stands for “any
string of characters” and question mark ? stands for “any one character”.
Glob originated from Unix operating system with a “global command” that
abbreviated to glob.
It is similar to regular expression but simpler in representation and limited in
abilities.
Two Files class methods accept a glob argument for pattern-matching behavior. The
glob pattern is matched against other strings, such as directory or file names.
Glob syntax follows these rules:
o An asterisk (*) matches any number of characters (including none).
o Double asterisks (**) like (*) but crosses directory boundaries - used for
matching complete paths.
o A question mark (?) matches exactly one character.
o Braces ({}) specify a collection of sub-patterns. For example:
o {temp,tmp} matches "temp", "tmp".
o {temp*,tmp*} matches all strings beginning with "temp" or "tmp".
o Square brackets ([]) for a set of single characters or with the hyphen (-) - a
range of characters. For example:
 [aeiou] matches any lowercase vowel.
 [0-9] matches any digit.
 [A-Z] matches any uppercase letter.
 [a-z,A-Z] matches any uppercase or lowercase letter.
 Within the square brackets, *, ?, and \ match themselves.
o All other characters match themselves.
o To match *, ?, or the other special characters, you can escape them by using
the backslash character, \. For example: \\ matches a single backslash,
and \? matches the question mark.
Examples of glob syntax:
o *.html – Matches all strings that end in .html
o ??? – Matches all strings with exactly three letters or digits
o *[0-9]* – Matches all strings containing a numeric value
o *.{htm,html,pdf} – Matches any string ending with .htm, .html or .pdf
o a?*.java – Matches any string beginning with a, followed by at least one
letter or digit, and ending with .java
o {foo*,*[0-9]*} – Matches any string beginning with foo or any string
containing a numeric value
72
Access Specifiers (09-15 MAY - CODE & STUDY)



If you are typing the glob pattern at the keyboard and it contains one of the special
characters, you must put the pattern in quotes ("*"), use the backslash (\*), or use
whatever escape mechanism is supported at the command line.
See the getPathMatcher method for more information on the glob syntax.
If glob is not sufficient for your needs, you can use Regular Expressions.
Link Awareness


The Files class is "link aware."
Every Files method either detects what to do when a symbolic link is encountered or
has the option for you to configure what to do when a symbolic link is encountered.
8) ACCESS SPECIFIERS (09-15 MAY - CODE & STUDY)
TBC
9) EXCEPTIONS (06-12 JUN)





The term exception is shorthand for the phrase "exceptional event."
An exception is an event, which occurs during the execution of a program that disrupts
the normal flow of the program's instructions.
When an error occurs within a method, the method creates an object and hands it off to
the runtime system. The object, called an exception object, contains information about
the error, including its type and the state of the program when the error occurred.
Creating an exception object and handing it to the runtime system is called throwing an
exception.
The set of possible "somethings" to handle the exception is the ordered list of methods
that had been called to get to the method where the error occurred. The list of methods
is known as the call stack (see the next figure).
The runtime system searches the call stack for a method that contains a block of code
that can handle the exception. This block of code is called an exception handler.
73
Exceptions (06-12 JUN)





An exception handler is considered appropriate if the type of the exception object
thrown matches the type that can be handled by the handler.
The exception handler chosen is said to catch the exception. If the runtime system
exhaustively searches all the methods on the call stack without finding an appropriate
exception handler, the runtime system (and, consequently, the program) terminates.
Valid Java programming language code must honor the Catch or Specify Requirement
o A try statement that catches the exception: a handler for the exception
o A method that specifies that it can throw the exception. The method must
provide a throws clause that lists the exception
Code that fails to honor the Catch or Specify Requirement will not compile. Only one of
3 exception types is subject to this Requirement.
The Java platform provides numerous exception classes. All the classes are descendants
of the Throwable class
THE THREE KINDS OF EXCEPTIONS
1. Checked exception
 A well-written application should anticipate and recover from
 All exceptions are checked exceptions, except for those indicated
by Error, RuntimeException, and their subclasses.
 Example: java.io.FileNotFoundException
2. Error
 External to the application, and that the application usually cannot anticipate or
recover from.
 Example: java.io.IOError
 An application might choose to catch this exception, in order to notify the user of
the problem — but it also might make sense for the program to print a stack trace
and exit.
 Errors are not subject to the Catch or Specify Requirement. Errors are those
exceptions indicated by Error and its subclasses.
3. Runtime exception.
 These are exceptional conditions that are internal to the application, and that the
application usually cannot anticipate or recover from.
 These usually indicate programming bugs, such as logic errors or improper use of
an API.
 Example: NullPointerException
 Not subject to the Catch or Specify Requirement.
 Runtime exceptions are those indicated by RuntimeException and its subclasses.
Errors and runtime exceptions are collectively known as unchecked exceptions.
74
Exceptions (06-12 JUN)
CATCHING AND HANDLING EXCEPTIONS




You can put each line of code that might throw an exception within its own try block and
provide separate exception handlers for each or within a single try block and associate
multiple handlers with it.
You associate exception handlers with a try block by providing one or more catch blocks
directly after the try block. No code can be between the end of the try block and the
beginning of the first catch block.
Exception handlers can do more than just print error messages or halt the program.
They can do error recovery, prompt the user to make a decision, or propagate the error
up to a higher-level handler using chained exceptions, as described in the Chained
Exceptions section.
From Java SE 7 and later, a single catch block can handle more than one type of
exception. specify the types of exceptions that block can handle, and separate each
exception type with a vertical bar (|):
catch (IOException|SQLException ex) {
logger.log(ex);
throw ex;
}





The finally block always executes when the try block exits. Putting cleanup code in
a finally block is always a good practice, even when no exceptions are anticipated.
Finally may not execute if:
The JVM exits while the try or catch code is being executed.
The thread executing the try or catch code is interrupted or killed, even though the
application as a whole continues.
If you are using Java SE 7 or later, consider using the try-with-resources statement in
these situations, which automatically releases system resources when no longer needed.
THE TRY-WITH-RESOURCES STATEMENT:

A resource is an object that must be closed after the program is finished with it. Any
object that implements java.lang.AutoCloseable, which includes all objects which
implement java.io.Closeable, can be used as a resource.
Example:
static String readFirstLineFromFile(String path) throws IOException {
75
Exceptions (06-12 JUN)
try (BufferedReader br =
new BufferedReader(new FileReader(path))) {
return br.readLine();
}
}

A try-with-resources statement can have catch and finally blocks just like an
ordinary try statement. In a try-with-resources statement, any catch or finally block is
run after the resources declared have been closed.
SUPPRESSED EXCEPTIONS


If an exception is thrown from the try block and one or more exceptions are thrown
from the try-with-resources statement, then those exceptions thrown from the try-withresources statement are suppressed, and the exception thrown by the block is the one
that is thrown from the try logic. You can retrieve these suppressed exceptions by calling
the Throwable.getSuppressedmethod from the exception thrown by the try block.
The Closeable interface extends the AutoCloseable interface. The close method of
the Closeable interface throws exceptions of type IOException while the close method
of the AutoCloseable interface throws exceptions of type Exception. Consequently,
subclasses of the AutoCloseable interface can override this behavior of
the close method to throw specialized exceptions, such as IOException, or no exception
at all.
HOW TO THROW EXCEPTIONS





The Java platform provides numerous exception classes. All the classes are descendants
of the Throwable class, and all allow programs to differentiate among the various types
of exceptions that can occur during the execution of a program.
All methods use the throw statement to throw an exception. The throw statement
requires a single argument: a throwable object. Throwable objects are instances of any
subclass of the Throwable class.
The objects that inherit from the Throwable class include direct descendants (objects
that inherit directly from the Throwable class) and indirect descendants (objects that
inherit from children or grandchildren of the Throwable class).
The figure below illustrates the class hierarchy of the Throwable class and its most
significant subclasses.
As you can see, Throwable has two direct descendants: Error and Exception.
76
Exceptions (06-12 JUN)
Error Class

When a dynamic linking failure or other hard failure in the Java virtual machine occurs,
the virtual machine throws an Error. Simple programs typically do not catch or throw
Errors.
Exception Class


Indicates that a problem occurred, but it is not a serious system problem. Most
programs you write will throw and catch Exceptions.
One Exception subclass, RuntimeException, is reserved for exceptions that indicate
incorrect use of an API. An example of a runtime exception is NullPointerException.
CHAINED EXCEPTIONS




An application often responds to an exception by throwing another exception. In effect,
the first exception causes the second exception. It can be very helpful to know when one
exception causes another. Chained Exceptions help the programmer do this.
The following are the methods and constructors in Throwable that support chained
exceptions.
o Throwable getCause()
o Throwable initCause(Throwable)
o Throwable(String, Throwable)
o Throwable(Throwable)
The Throwable argument to initCause and the Throwable constructors is the exception
that caused the current exception. getCause returns the exception that caused the
current exception, and initCause sets the current exception's cause.
The following example shows how to use a chained exception.
try {
77
Exceptions (06-12 JUN)
} catch (IOException e) {
throw new SampleException("Other IOException", e);
}

In this example, when an IOException is caught, a new SampleException exception is
created with the original cause attached and the chain of exceptions is thrown up to the
next higher level exception handler.
CREATING EXCEPTION CLASSES

Do you need an exception type that isn't represented by those in the Java platform?

Would it help users if they could differentiate your exceptions from those thrown by
classes written by other vendors?

Does your code throw more than one related exception?

If you use someone else's exceptions, will users have access to those exceptions? A
similar question is, should your package be independent and self-contained?

For readable code, it's good practice to append the string Exception to the names of all
classes that inherit (directly or indirectly) from the Exception class.
UNCHECKED EXCEPTIONS — THE CONTROVERSY



One case where it is common practice to throw a RuntimeException is when the user
calls a method incorrectly. For example, a method can check if one of its arguments is
incorrectly null. If an argument is null, the method might throw a NullPointerException,
which is an unchecked exception.
Generally speaking, do not throw a RuntimeException or create a subclass of
RuntimeException simply because you don't want to be bothered with specifying the
exceptions your methods can throw.
Here's the bottom line guideline: If a client can reasonably be expected to recover from
an exception, make it a checked exception. If a client cannot do anything to recover
from the exception, make it an unchecked exception.
ADVANTAGES OF EXCEPTIONS
1. Separating Error-Handling Code from "Regular" Code
Exceptions enable you to write the main flow of your code and to deal with the
exceptional cases elsewhere.
2. Propagating Errors Up the Call Stack
78
Generics (16-22 MAY - CODE)
A method can duck any exceptions thrown within it, thereby allowing a method farther
up the call stack to catch it. Hence, only the methods that care about errors have to
worry about detecting errors.
3. Grouping and Differentiating Error Types
You can create groups of exceptions and handle exceptions in a general fashion, or you
can use the specific exception type to differentiate exceptions and handle exceptions in
an exact fashion.
10) GENERICS (16-22 MAY - CODE)
INTRODUCTION








Help us to detect bugs at compile time rather than runtime.
With generics we use types as parameters in defining types and methods. The input to type
parameters are types.
Compile time type checks: The java compiler throws errors at compile time for code that fails
type checks.
Generics enable us to implement algorithms that flexibly work on objects of different types.
Generics remove the need for casting to choose the right type.
Example:
List list=new ArrayList();
list.add(“John”);
The way the list has been instantiated makes it unclear as to what data type it will store. This is
potentially unsafe as we may also try to add an Integer.
To get the stored value, we would need to cast to a String.
String name=(String)list.get(0);
Generics enable us to make it type safe without casting.
TYPE PARAMETER NAMING CONVENTIONS

Java convention uses single uppercase letters for the type parameter name. This is different
from the ordinary class or interface name so there’s no confusion.
COMMON PARAMETERS






T – Type
S,U,V etc. – 2nd, 3rd, 4th types
E – Element (used extensively by the Java Collections Framework)
K – Key
V – Value
N – Number
GENERIC TYPES
79
Generics (16-22 MAY - CODE)
DEFINING A GENERIC CLASS
The format for defining a Generic class:
Public class PersonAnalyser<T>{
Public int getAge(){
Return
}
Public setAge(T t){
}
}

The type variable can be any non-primitive: class, interface, array, another type variable.
INSTANTIANTING A GENERIC TYPE
Person<Teacher> teachingPerson;
teachingPerson= new Person<Teacher();

Type Parameter and Type Argument Terminology:
PersonAnalyser<T> - Type parameter
Person<Teacher> - Type argument
JAVA 7 TYPE INFERENCE


From Java 7 the Java compiler can infer the type from the variable the instance is assigned to:
Person <Teacher>teachingPerson = new Person<>();
This is also referred to as the diamond operator because of the empty <>.
TYPE INFERENCE AND GENERIC METHODS

Generally, a Java compiler can infer the type parameters of a generic method call. Consequently,
in most cases, you do not have to specify them.
TYPE INFERENCE AND INSTANTIATION OF GENERIC CLASSES


You can replace the type arguments required to invoke the constructor of a generic class with an
empty set of type parameters (<>) as long as the compiler can infer the type arguments from the
context.
To take advantage of type inference during generic class instantiation, you must use the
diamond.
80
Generics (16-22 MAY - CODE)

Compilers from releases prior to Java SE 7 are able to infer the actual type parameters of generic
constructors, similar to generic methods. However, compilers in Java SE 7 and later can infer the
actual type parameters of the generic class being instantiated if you use the diamond (<>).
TARGET TYPES

The Java compiler takes advantage of target typing to infer the type parameters of a generic
method invocation. The target type of an expression is the data type that the Java compiler
expects depending on where the expression appears.
MULTIPLE TYPE PARAMETERS

A generic class can have multiple type parameters. Example:
public interface Pair<K, V> {
public K getKey();
public V getValue();
}
RAW TYPES


This is similar to using a generic type without the parameter type.
Raw Types are used in legacy code because lots of API classes (such as the Collections classes)
were not generic prior to JDK 5.0. When using raw types, you essentially get pre-generics
behaviour.
GENERIC METHODS


These are methods with their own type parameters limited to the method where it is declared
Static and non-static generic methods are allowed, as well as generic class constructors.
Example:
interface Collection<E> {
public <T> boolean containsAll(Collection<T> c);
}
Static method
public class MyComparator {
public static <K, V> boolean compare(Pair<K, V> p1, Pair<K, V> p2) {
return p1.getKey().equals(p2.getKey()) &&
81
Generics (16-22 MAY - CODE)
p1.getValue().equals(p2.getValue());
}
}
Class constructor
public class Pair<K, V> {
private K key;
private V value;
public Pair(K key, V value) {
this.key = key;
this.value = value;
}
}

Type inference allows you to invoke a generic method without specifying a type between angle
brackets. Further reading: Type Inference.
BOUNDED TYPE PARAMETERS

Bounded Type Parameters restrict the types that can be used as type arguments in a
parameterized type.
A method that operates on numbers should only accept instances of Number or its subclasses.
To declare a bounded type parameter, list the type parameter's name, followed by
the extends keyword, followed by its upper bound, which in this example is Number. Note that,
in this context,extends is used in a general sense to mean either "extends" (as in classes) or
"implements" (as in interfaces).


public <U extends Number> void validate (U u){
System.out.println("T: " + t.getClass().getName());
System.out.println("U: " + u.getClass().getName());
}

In addition to limiting the types you can use to instantiate a generic type, bounded type
parameters allow you to invoke methods defined in the bounds:
MULTIPLE BOUNDS
82
Java Keywords - Static , Final , volatile, synchronized , transient, this super etc. (06-12 JUN)
A type variable with multiple bounds is a subtype of all the types listed in the bound. If one of the
bounds is a class, it must be specified first.
GENERICS, INHERITANCE, AND SUBTYPES
Given two concrete types A and B (for example, Number and Integer), MyClass<A> has no
relationship to MyClass<B>, regardless of whether or not A and B are related. The common parent
of MyClass<A> and MyClass<B> is Object.
Generic Classes and Subtyping
You can subtype a generic class or interface by extending or implementing it. The relationship
between the type parameters of one class or interface and the type parameters of another are
determined by theextends and implements clauses.
Using the Collections classes as an example, ArrayList<E> implements List<E>, and List<E> extends
Collection<E>. SoArrayList<String> is a subtype of List<String>, which is a subtype
of Collection<String>. So long as you do not vary the type argument, the subtyping relationship is
preserved between the types.
11) JAVA KEYWORDS - STATIC , FINAL , VOLATILE, SYNCHRONIZED , TRANSIENT, THIS
SUPER ETC. (06-12 JUN)
TBC
Here is a list of keywords in the Java programming language. You cannot use any of the following as
identifiers in your programs. The keywords const and goto are reserved, even though they are not
currently used. true, false, and null might seem like keywords, but they are actually literals; you
cannot use them as identifiers in your programs.
abstract
continue
for
new
switch
assert***
default
goto*
package
synchronized
boolean
do
if
private
this
83
Annotations (06-12 JUN)
break
double
implements
protected
throw
byte
else
import
public
throws
case
enum****
instanceof
return
transient
catch
extends
int
short
try
char
final
interface
static
void
class
finally
long
strictfp**
volatile
const*
float
native
super
while
*
not used
**
added in 1.2
***
added in 1.4
****
added in 5.0
12) ANNOTATIONS (06-12 JUN)
Annotation type can be one of the types that are defined in the java.lang or
java.lang.annotation or you can define your own annotation.
Annotations are used to provide meta data for your Java code. Being meta data, Java
annotations do not directly affect the execution of your code,
Annotations have a number of uses, among them:

Information for the compiler —Can be used by the compiler to detect errors or
suppress warnings.

Compile-time and deployment-time processing — Build tools may scan your Java code
for specific annotations and generate source code or other files based on these
annotations.
84
Annotations (06-12 JUN)

Runtime processing —Normally, Java annotations are not present in your Java code
after compilation. It is possible, however, to define your own annotations that are
available at runtime.
Format
In its simplest form, an annotation looks like @Entity. The at sign character (@) indicates to
the compiler that what follows is an annotation.
The annotation can include elements, which can be named or unnamed, and there are
values for those elements: @Author(name = "Benjamin Franklin", date = "3/27/2003" ) or
@SuppressWarnings(value = "unchecked"). If there is just one element named value, then
the name can be omitted, as in: @SuppressWarnings("unchecked"). If the annotation has no
elements, then the parentheses can be omitted.
It is also possible to use multiple annotations on the same declaration: @Author(name =
"Jane Doe") @EBook
If the annotations have the same type, then this is called a repeating annotation:
@Author(name = "Jane Doe") @Author(name = "John Smith"). Repeating annotations are
supported as of the Java SE 8 release
Where to use annotations


Annotations can be applied to declarations of classes, fields, methods, and other
program elements. Used on a declaration, an annotation appears on its own line by
convention.
Annotations can also be applied to the use of types from Java 8. This is called Type
annotation. Examples:

Class instance creation expression: new @Interned MyObject();

Type cast: myString = (@NonNull String) str;

Implements clause:
class UnmodifiableList<T> implements
@Readonly List<@Readonly T> { ... }

Thrown exception declaration:
void monitorTemperature() throws
@Critical TemperatureException { ... }
85
Annotations (06-12 JUN)
Declaring an Annotation Type
@interface ClassPreamble {
String author();
String date();
int currentRevision() default 1;
String lastModified() default "N/A";
String lastModifiedBy() default "N/A";
// Note use of array
String[] reviewers();
}
After the annotation type is defined, you can use annotations of that type, with the values
filled in, like this:
@ClassPreamble (
author = "John Doe",
date = "3/17/2002",
currentRevision = 6,
lastModified = "4/12/2004",
lastModifiedBy = "Jane Doe",
// Note array notation
reviewers = {"Alice", "Bob", "Cindy"}
)
To make the information in @ClassPreamble appear in Javadoc-generated documentation,
you must annotate the @ClassPreamble definition with the @Documentedannotation:
// import this to use @Documented
import java.lang.annotation.*;
@Documented
86
JVM and Memory Management (06-12 JUN)
@interface ClassPreamble {
// Annotation element definitions
}
Predefined Annotation Types
Annotation Types Used by the Java Language
The predefined annotation types defined in java.lang are @Deprecated, @Override,
and@SuppressWarnings.
13) JVM AND MEMORY MANAGEMENT (06-12 JUN)



Java Virtual Machine refers to any of the following: An abstract specification, a concrete
implementation of the JVM or a runtime instance of the JVM.
o The abstract specification is a concept
o Concrete implementations-exist on many platforms and from many vendors.
They are either all software or a combination of hardware and software.
o A runtime instance is used by a single running Java application.
Each Java application runs inside a runtime instance of some concrete implementation
of the abstract specification of the Java virtual machine.
Java bytecode runs in a JRE (Java Runtime Environment). The JVM is the a part of the JRE
which loads and executes Java byte code.
THE LIFE OF A JVM



A runtime instance of the JVM is started when a java application starts and will only run
for one Java application.
If you start many Java applications at the same time, on the same computer, you’ll have
as many JVM instances running on the same concrete implementation of a given JVM
concrete implementation.
The JVM instance starts running the java application by invoking the main() method of
the initial class.
o This method must be public, static, return void, and accept one parameter of a
String array.
87
JVM and Memory Management (06-12 JUN)

o The main() method of an application's initial class serves as the starting point for
that application's initial thread. The initial thread can in turn fire off other
threads.
A Java application continues to execute only during the life of non-daemon and
terminates when all non-daemon threads terminate. At that point the virtual machine
instance will exit.
THE ARCHITECTURE OF THE JVM





The architecture of the JVM defines a specification that any JVM implementation
adopts.
The architecture consists of the following:
o A class loader subsystem: A mechanism for loading types (classes and interfaces)
given fully qualified names.
o An execution engine: A mechanism to execute the methods of loaded classes.
o The JVM needs memory to store classes and all other information loaded by the
class loader, parameters passed in, objects created, local variables, work in
progress of computations being performed, return values.
The memory that the JVM needs to execute a program is organized into a number of
runtime data areas. The actual structure details vary according to the JVM
implementation.
The Java virtual machine has one method area and one heap area shared by all threads.
o Method area: The class loader parses all the type information from the binary
data into the memory area.
o The heap: Objects created by the JVM are stored in the heap.
Each thread gets its own Java stack and pc register also called the program counter.
88
JVM and Memory Management (06-12 JUN)






The pc register: indicates the next instruction to execute when the thread is executing a
Java method.
The java stack: stores the state of Java method invoked for the thread. This includes the
parameters, local variables, its return values and intermediate calculations. The java
stack is made up of stack frames. A stack frame contains the state of an invoked Java
method. The JVM pushes a new frame onto the stack when a method is invoked and
pops and discards the frame when the method completes execution.
The native method stack: stores the state of native method invocation in a way that
varies by implementation. Information about the invocation may also be stored in
registers.
The execution engine: consists of the interpreter and the Just In Time(JIT) compiler.
The Interpreter: converts byte code instruction into machine level instruction
JIT Compiler:
o When JIT is enabled, the JVM will analyze the Java application method calls and
compile the bytecode (after some internal thresholds are reached) into native,
more efficient, machine code. The JIT process is normally prioritized by the
busiest method calls first.
o Once such method call is compiled into machine code, the JVM executes
it directly instead of “interpreting” it.
o The above process leads to improved run time performance over time.
CLASS LOADER
 Java loads and links the class when it refers to a class for the first time at runtime.
o Hierarchy: Class loaders in Java are organized into a hierarchy with a parent-child
relationship. The Bootstrap Class Loader is the parent of all class loaders.
o Delegation: When a class is required, the parent class loader is checked to
determine whether or not the class is in the parent class loader. If the upper class
loader has the class, the class is used. If not, the class loader requests the parent
to load the class.
o Class visibility: A child class loader can find the class in the parent class loader
and not the other way round.
 Each class loader has its namespace that stores the loaded classes. To load a class, the
class loader checks the namespace, using the FQCN (Fully Qualified Class Name) to see if
the class has already been loaded. Even if the class has an identical FQCN but a different
namespace it means that the class has been loaded by another class loader and so the
class loader will need to load its own.
Loading a class
The class loader checks if a class has been loaded in the class loader cache. If not, it checks
the parent class loader.
If the class is not found in the bootstrap class loader, the requested class loader searches for
the class in the file system.
89
JVM and Memory Management (06-12 JUN)
BOOTSTRAP CLASS LOADER
o
Loads Java APIs, including object classes: the runtime classes in rt.jar,
internationalization classes in i18n.jar, and others.
o
Unlike other class loaders, it is implemented in native code instead of Java. It
is created when running the JVM.
EXTENSION CLASS LOADER
o
Loads the extension classes and various security extension functions: classes
in JAR files in the lib/ext directory of the JRE, and in the system-wide,
platform-specific extension directory (such as /usr/jdk/packages/lib/ext on
the Solaris™ Operating System, but note that use of this directory applies
only to Java™ 6 and later).
SYSTEM CLASS LOADER

Loads the application classes. It loads the class in the $CLASSPATH specified by the
user.

User-defined class loader: Written for an application by a user.
RUNTIME DATA AREAS
90
JVM and Memory Management (06-12 JUN)


These are the memory areas assigned when the JVM program runs on the OS.
The runtime data areas are divided into 6 areas as in the diagram below.
o The PC Register, JVM Stack, and Native Method Stack are created for one
thread.
o The Heap, Method Area, and Runtime Constant Pool are shared by all
threads.
PC REGISTER


The PC (Program Counter) Register is created when the thread starts.
The PC register has the address of the currently executing JVM instruction.
JVM STACK



The JVM stack is created at the same time as the thread and stores frames.
A new frame is created each time a method is invoked. The frame is destroyed when
the method exits normal or with an exception.
The JVM pushes or pops the stack frame to the JVM stack.
NATIVE METHOD STACK

If supplied, native method stacks are typically allocated per thread when each thread
is created.
91
JVM and Memory Management (06-12 JUN)


The JVM has a Native Method Stack: colloquially called "C stacks”.
It supports native methods (methods written in a language other than the Java
programming language).
THE METHOD AREA






It is created when the JVM starts.
The class loader locates the appropriate class file to load a type. It reads in the class
file (a linear stream of binary data).
The virtual machine extracts information about the type from the binary data and
stores it in the method area.
Memory for class (static) variables declared in the class is also taken from the
method area.
How the JVM represents type information internally is a decision of the
implementation designer.
All threads share the same method area, so access to the method area's data
structures must be designed to be thread-safe
THE HEAP











Java objects reside in an area called the heap.
The heap is created when the JVM starts up and may increase or decrease in size
while the application runs.
When the heap becomes full, garbage is collected.
During the garbage collection objects that are no longer used are cleared, thus
making space for new objects.
The heap is sometimes divided into two areas (or generations) called
the nursery (or young space) and the old space.
The nursery is a part of the heap reserved for allocation of new objects.
When the nursery becomes full, garbage is collected by running a special young
collection, where all objects that have lived long enough in the nursery are
promoted (moved) to the old space, thus freeing up the nursery for more object
allocation.
When the old space becomes full garbage is collected there, a process called an old
collection.
The reasoning behind a nursery is that most objects are temporary and short lived.
A young collection is designed to be swift at finding newly allocated objects that are
still alive and moving them away from the nursery.
Typically, a young collection frees a given amount of memory much faster than an
old collection or a garbage collection of a single-generational heap (a heap without a
nursery).
92
JVM and Memory Management (06-12 JUN)
RUNTIME CONSTANT POOL








This area is included in the method area. However as it plays a core role in JVM
operation, the JVM specification separately describes it.
It contains the constant of each class and interface and all references for methods
and fields.
In short, when a method or field is referred to, the JVM searches the actual address
of the method or field on the memory by using the runtime constant pool.
The diagram below will help explain the role of the constant pool further.
The frame is where the operands (operation instructions) reside and that is where
the dynamic linking occurs. It is a shorthand way, so to speak, using the constant
pool to keep track of the class and its members.
Each frame contains a reference to the runtime constant pool. This reference points
to the constant pool for the class of the method being executed for that frame. This
reference helps to support dynamic linking.
C/C++ code is typically compiled to an object file then multiple object files are linked
together to product a usable artifact such as an executable or dll. During the linking
phase symbolic references in each object file are replaced with an actual memory
address relative to the final executable. In Java this linking phase is done dynamically
at runtime.
When a Java file is compiled, all references to variables and methods are stored in
the class's constant pool as a symbolic reference.
93
Design Patterns (16-19 JUN)

A symbolic reference is a logical reference not a reference that actually points to a
physical memory location
Source: stackflow question response by James Drinkard
EXECUTION ENGINE







The bytecode that the class loader puts in the runtime data area is executed by the
execution engine which reads the Java Bytecode in units of instruction.
Java Bytecode is written in human-readable form. The execution engine changes the
bytecode to machine code in the JVM. This is done in one of two ways:
o Interpreter: Reading, interpreting and executing the bytecode instructions
one by one. As it interprets and executes instructions one by one, it can
quickly interpret one bytecode, but slowly executes the interpreted result.
o JIT (Just-In-Time) compiler: The JIT compiler compensates for the
disadvantage of the slow execution of the interpreter.
The execution engine runs as an interpreter first, and at the appropriate time, the JIT
compiler compiles the entire bytecode to change it to native code. After that, the
execution engine no longer interprets the method, but directly executes using native
code.
The compiled code can be executed quickly since the native code is stored in the
cache.
However, it takes more time for JIT compiler to compile the code than for the
interpreter to interpret the code one by one.
Therefore, if the code is to be executed just once, it is better to interpret it instead of
compiling.
The JVM implementations that use the JIT compiler internally check how frequently
the method is executed and compile the method only when the frequency is higher
than a certain level.
Further reading and reference:
https://dzone.com/articles/understanding-jvm-internals
http://blog.jamesdbloom.com/JVMInternals.html
https://www.artima.com/insidejvm/ed2/jvmP.html
http://www.cubrid.org/blog/dev-platform/understanding-jvm-internals/
14) DESIGN PATTERNS (16-19 JUN)
TBC
94
TBD-Other topics to study
TBD-OTHER TOPICS TO STUDY
Classes and objects including nested classes
Java Memory Management
REFERENCE
MULTI-DIMENSIONAL ARRAYS
The arrays you have been using so far have only held one column of data. But you can set up
an array to hold more than one column. These are called multi-dimensional arrays. As an
example, think of a spreadsheet with rows and columns. If you have 6 rows and 5 columns
then your spreadsheet can hold 30 numbers. It might look like this:
A multi dimensional array is one that can hold all the values above. You set them up like
this:
int[ ][ ] aryNumbers = new int[6][5];
They are set up in the same way as a normal array, except you have two sets of square
brackets. The first set of square brackets is for the rows and the second set of square
brackets is for the columns. In the above line of code, we're telling Java to set up an array
with 6 rows and 5 columns. To hold values in a multi-dimensional array you have to take
care to track the rows and columns. Here's some code to fill the first rows of numbers from
our spreadsheet image:
aryNumbers[0][0] = 10;
aryNumbers[0][1] = 12;
aryNumbers[0][2] = 43;
aryNumbers[0][3] = 11;
aryNumbers[0][4] = 22;
So the first row is row 0. The columns then go from 0 to 4, which is 5 items. To fill the
second row, it would be this:
aryNumbers[1][0] = 20;
aryNumbers[1][1] = 45;
95
Reference
aryNumbers[1][2] = 56;
aryNumbers[1][3] = 1;
aryNumbers[1][4] = 33;
The column numbers are the same, but the row numbers are now all 1.
To access all the items in a multi-dimensional array the technique is to use one loop inside
of another. Here's some code to access all our number from above. It uses a double for
loop:
The first for loop is used for the rows; the second for loop is for the columns. The first time
round the first loop, the value of the variable i will be 0. The code inside of the for loop is
another loop. The whole of this second loop will be executed while the value of the variable
i is 0. The second for loop use a variable called j. The i and the j variables can then be used
to access the array.
aryNumbers[ i ][ j ]
So the two loop system is used to go through all the values in a multi-dimensional array, row
by row.
Source: http://www.homeandlearn.co.uk/java/multi-dimensional_arrays.html
FAIL-FAST

Detect illegal concurrent modification during iteration and fail quickly and cleanly by
throwing ConcurrentModificationException rather than risking arbitrary,
nondeterministic behaviour at an undetermined time in the future. This can happen in
the following situations:
 Single Threaded Environment - After the creation of the iterator , structure is
modified at any time by any method other than iterator's own remove method.
96
Reference

Multiple Threaded Environment: If one thread is modifying the structure of the
collection while other thread is iterating over it .
Fail-fast behaviour of an iterator cannot be guaranteed rather on a best-effort basis. It is,
generally speaking, impossible to make any hard guarantees in the presence of
unsynchronized concurrent modification. The fail-fast behavior of iterators should be used
only to detect bugs.
HOW IT WORKS
Iterator read internal data structure (object array) directly . The internal data structure
should not be modified while iterating through the collection. To ensure this it maintains an
internal flag "mods" .Iterator checks the "mods" flag whenever it gets the next value
(using hasNext() method and next() method). Value of mods flag changes whenever there
is an structural modification. Thus the iterator would throw
ConcurrentModificationException.
Source: java hungry
FAIL SAFE
HOW IT WORKS




Fail Safe Iterator makes a copy of the internal data structure (object array) and iterates
over the copied data structure. Any structural modification done to the iterator affects
the copied data structure. The original data structure remains structurally unchanged
and no ConcurrentModificationException is thrown by the fail safe iterator.
The "snapshot" style iterator method uses a reference to the state of the array at the
point that the iterator was created. This array never changes during the lifetime of the
iterator, so interference is impossible and the iterator is guaranteed not to throw
ConcurrentModificationException.
The iterator will not reflect additions, removals, or changes to the list since the iterator
was created.
Element-changing operations on iterators themselves (remove(), set(), and add()) are
not supported. These methods throw UnsupportedOperationException.
THE LIMITATIONS:


The overhead of maintaining the copied data structure i.e memory.
The fail safe iterator does not guarantee that the data being read is the data currently in
the original data structure.
97
Code
Thus fail safe iterator is ordinarily too costly, but may be useful when you cannot or don’t
want to synchronize traversals, yet need to preclude interference among concurrent
threads.
Example Fail Safe Iterator: Iterator with ConcurrentHashMap
Source: java hungry
HASHTABLE


Was part of the original java.util and is a concrete implementation of a Dictionary.
Java 2 re-engineered Hashtable so that it also implements the Map interface. Thus,
Hashtable is now integrated into the collections framework. It is similar to HashMap, but
is synchronized.
HOW IT WORKS
Like HashMap, Hashtable stores key/value pairs in a hash table. When using a Hashtable,
you specify an object that is used as a key, and the value that you want linked to that key.
The key is then hashed, and the resulting hash code is used as the index at which the value
is stored within the table.
INNER CLASS





In Java you are allowed to define a class (say, B) inside of another class (say, A). The class
A is called the outer class, and the class B is called the inner class.
The purpose of inner classes is purely to be used internally as helper classes.
An inner class is a member of its enclosing class and has access to other members
(including private) and vice versa.
An inner class can be declared private, public, protected, or package private.
There are two kind of inner classes: static and non-static. A static inner class cannot refer
directly to instance variables or methods defined in its outer class: it can use them only
through an object reference.
CODE
ESSENTIAL JAVA CLASSES - BASIC I/O
USING BYTE STREAMS
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
98
Code
public class CopyBytes {
public static void main(String[] args) throws IOException {
FileInputStream in = null;
FileOutputStream out = null;
try {
in = new FileInputStream("xanadu.txt");
out = new FileOutputStream("outagain.txt");
int c;
while ((c = in.read()) != -1) {
out.write(c);
}
} finally {
if (in != null) {
in.close();
}
if (out != null) {
out.close();
}
}
}
}
USING CHARACTER STREAMS
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
99
Code
public class CopyCharacters {
public static void main(String[] args) throws IOException {
FileReader inputStream = null;
FileWriter outputStream = null;
try {
inputStream = new FileReader("xanadu.txt");
outputStream = new FileWriter("characteroutput.txt");
int c;
while ((c = inputStream.read()) != -1) {
outputStream.write(c);
}
} finally {
if (inputStream != null) {
inputStream.close();
}
if (outputStream != null) {
outputStream.close();
}
}
}
}
LINE-ORIENTED I/O
import java.io.FileReader;
import java.io.FileWriter;
import java.io.BufferedReader;
100
Code
import java.io.PrintWriter;
import java.io.IOException;
public class CopyLines {
public static void main(String[] args) throws IOException {
BufferedReader inputStream = null;
PrintWriter outputStream = null;
try {
inputStream = new BufferedReader(new FileReader("xanadu.txt"));
outputStream = new PrintWriter(new FileWriter("characteroutput.txt"));
String l;
while ((l = inputStream.readLine()) != null) {
outputStream.println(l);
}
} finally {
if (inputStream != null) {
inputStream.close();
}
if (outputStream != null) {
outputStream.close();
}
}
}
}
SCANNING
import java.io.*;
101
Code
import java.util.Scanner;
public class ScanXan {
public static void main(String[] args) throws IOException {
Scanner s = null;
try {
s = new Scanner(new BufferedReader(new FileReader("xanadu.txt")));
while (s.hasNext()) {
System.out.println(s.next());
}
} finally {
if (s != null) {
s.close();
}
}
}
}
SCANNING JAVA PRIMIT IVE TYPE TOKENS
import java.io.FileReader;
import java.io.BufferedReader;
import java.io.IOException;
import java.util.Scanner;
import java.util.Locale;
public class ScanSum {
public static void main(String[] args) throws IOException {
102
Code
Scanner s = null;
double sum = 0;
try {
s = new Scanner(new BufferedReader(new FileReader("usnumbers.txt")));
s.useLocale(Locale.US);
while (s.hasNext()) {
if (s.hasNextDouble()) {
sum += s.nextDouble();
} else {
s.next();
}
}
} finally {
s.close();
}
System.out.println(sum);
}
}
And here's the sample input file, usnumbers.txt
8.5
32,767
3.14159
1,000,000.1
CONCURRENCY
103
Code
SYNCHRONIZED STATEMENT CODE
public class Counter{
private int count = 0;
public int inc(){
synchronized(this){
return ++count;
}
}
}
SIMPLE LOCK USE CODE
public class Counter{
private Lock lock = new Lock();
private int count = 0;
public int inc(){
lock.lock();
int newCount = ++count;
lock.unlock();
return newCount;
}
}
SIMPLE LOCK IMPLEMENTATION CODE
public class Lock{
104
Code
private boolean isLocked = false;
public synchronized void lock()
throws InterruptedException{
while(isLocked){
wait();
}
isLocked = true;
}
public synchronized void unlock(){
isLocked = false;
notify();
}
}
REENTRANT LOCK IMPLEMENTATION
public class Lock{
boolean isLocked = false;
Thread lockedBy = null;
int
lockedCount = 0;
public synchronized void lock()
throws InterruptedException{
Thread callingThread = Thread.currentThread();
105
Code
while(isLocked && lockedBy != callingThread){
wait();
}
isLocked = true;
lockedCount++;
lockedBy = callingThread;
}
public synchronized void unlock(){
if(Thread.curentThread() == this.lockedBy){
lockedCount--;
if(lockedCount == 0){
isLocked = false;
notify();
}
}
}
...
}
DEADLOCK EXAMPLE
public class TreeNode {
106
Code
TreeNode parent = null;
List
children = new ArrayList();
public synchronized void addChild(TreeNode child){
if(!this.children.contains(child)) {
this.children.add(child);
child.setParentOnly(this);
}
}
public synchronized void addChildOnly(TreeNode child){
if(!this.children.contains(child){
this.children.add(child);
}
}
public synchronized void setParent(TreeNode parent){
this.parent = parent;
parent.addChildOnly(this);
}
public synchronized void setParentOnly(TreeNode parent){
this.parent = parent;
}
}
107
Code
If a thread (1) calls the parent.addChild(child) method at the same time as another thread
(2) calls the child.setParent(parent) method, on the same parent and child instances, a
deadlock can occur. Here is some pseudo code that illustrates this:
Thread 1: parent.addChild(child); //locks parent
--> child.setParentOnly(parent);
Thread 2: child.setParent(parent); //locks child
--> parent.addChildOnly()
First thread 1 calls parent.addChild(child). Since addChild() is synchronized thread 1
effectively locks the parent object for access from other treads.
Then thread 2 calls child.setParent(parent). Since setParent() is synchronized thread 2
effectively locks the child object for acces from other threads.
Now both child and parent objects are locked by two different threads. Next thread 1 tries
to call child.setParentOnly() method, but the child object is locked by thread 2, so the
method call just blocks. Thread 2 also tries to call parent.addChildOnly() but the parent
object is locked by thread 1, causing thread 2 to block on that method call. Now both
threads are blocked waiting to obtain locks the other thread holds.
Note: The two threads must call parent.addChild(child) and child.setParent(parent) at the
same time as described above, and on the same two parent and child instances for a
deadlock to occur. The code above may execute fine for a long time until all of a sudden it
deadlocks.
The threads really need to take the locks *at the same time*. For instance, if thread 1 is a bit
ahead of thread2, and thus locks both A and B, then thread 2 will be blocked already when
trying to lock B. Then no deadlock occurs. Since thread scheduling often is unpredictable
there is no way to predict *when* a deadlock occurs. Only that it *can* occur.
108