Saturday, January 30, 2016

Topic 33: Autoboxing in Java

  • Autoboxing is the process by which a primitive type is automatically encapsulated (boxed) into its equivalent type wrapper whenever an object of that type is needed. There is no need to explicitly construct an object. 

  • Auto-unboxing is the process by which the value of a boxed object is automatically extracted (unboxed) from a type wrapper when its value is needed. There is no need to call a method such as intValue( ) or doubleValue( ).

  • With autoboxing it is no longer necessary to manually construct an object in order to wrap a primitive type. We need only assign that value to a type-wrapper reference. Java automatically constructs the object for us. For example, here is the modern way to construct an Integer object that has the value 100:

Integer iOb = 100; // autobox an int

Notice that no object is explicitly created through the use of new as discussed earlier in Type Wrappers. Java handles this for us, automatically.

  • To unbox an object, simply assign that object reference to a primitive-type variable. For example, to unbox iOb, you can use this line:

int i = iOb; // auto-unbox

  • Autoboxing automatically occurs whenever a primitive type must be converted into an object; auto-unboxing takes place whenever an object must be converted into a primitive type. Thus, autoboxing/unboxing might occur when an argument is passed to a method, or when a value is returned by a method. For example, consider this example:

// Take an Integer parameter and return an int value;
static int m(Integer v)
{
return v ; // auto-unbox to int
}


//Inside main() - Pass an int to m() and assign the return value to an Integer. Here, the argument 100 is autoboxed into an Integer. The return value is also autoboxed into an Integer.
Integer iOb = m(100);

  • In general, autoboxing and unboxing take place whenever a conversion into an object or from an object is required. This applies to expressions. Within an expression, a numeric object is automatically unboxed. The outcome of the expression is reboxed, if necessary. For ex:

Integer iOb
int i;

// The following automatically unboxes iOb, performs the increment, and then reboxes the result back into iOb.
++iOb;

// Here, iOb is unboxed, the expression is evaluated, and the result is reboxed and assigned to iOb2.
iOb = iOb + (iOb / 3);

// The same expression is evaluated, but the result is not reboxed.
i = iOb + (iOb / 3);

  • Auto-unboxing also allows you to mix different types of numeric objects in an expression. Once the values are unboxed, the standard type promotions and conversions are applied. For ex:

Integer iOb = 100;
Double dOb = 98.6;

dOb = dOb + iOb; // Results in 198.6

  • Because of auto-unboxing, we can use integer numeric objects to control a switch statement. For example, consider this fragment:

Integer iOb = 2;
switch(iOb)
{
case 1: System.out.println("one");
break;
case 2: System.out.println("two");
break;
default: System.out.println("error");
}

When the switch expression is evaluated, iOb is unboxed and its int value is obtained.

  • Java also supplies wrappers for boolean and char. These are Boolean and Character. Autoboxing/unboxing applies to these wrappers, too. For ex:

Boolean b = true;
// Below, b is auto-unboxed when used in a conditional expression, such as an if.
if(b) System.out.println("b is true");

// Autobox/unbox a char.
Character ch = 'x'; // box a char
char ch2 = ch; // unbox a char

Because of auto-unboxing, the boolean value contained within b is automatically unboxed when the conditional expression is evaluated. Thus, with the advent of autoboxing/unboxing, a Boolean object can be used to control an if statement. Because of auto-unboxing, a Boolean object can now also be used to control any of Java’s loop statements. When a Boolean is used as the conditional expression of a while, for, or do/while, it is automatically unboxed into its boolean equivalent. For example, this is now perfectly valid code:

Boolean b;
while(b) { // ...

  • Autoboxing/Unboxing can help us prevent errors. For ex:

Integer iOb = 1000; // autobox the value 1000
int i = iOb.byteValue(); // manually unbox as byte !!!
System.out.println(i); // does not display 1000 !

This displays not the expected value of 1000, but 24. The reason is that the value inside iOb is manually unboxed by calling byteValue( ), which causes the truncation of the value stored in iOb, which is 1,000. This results in the garbage value of 24 being assigned to i. Auto-unboxing prevents this type of error because the value in iOb will always auto- unbox into a value compatible with int.



Click for NEXT article.

 

Please feel free to correct me by commenting your suggestions and feedback.



 

Friday, January 29, 2016

Topic 32: Type Wrappers in Java


Despite the performance benefit offered by the primitive types, there are times when we will need an object representation. For example, we can’t pass a primitive type by reference to a method. Java provides type wrappers, which are classes that encapsulate a primitive type within an object.

  • The type wrappers are Double, Float, Long, Integer, Short, Byte, Character, and Boolean.

  • Character - Character is a wrapper around a char. The constructor for Character is


Character(char ch)


Here, ch specifies the character that will be wrapped by the Character object being created.


To obtain the char value contained in a Character object, call charValue( ), shown here:

char charValue( ) - It returns the encapsulated character.

  • Boolean - Boolean is a wrapper around boolean values. It defines these constructors:

Boolean(boolean boolValue)

Boolean(String boolString)

In the first version, boolValue must be either true or false. In the second version, if boolString contains the string “true” (in uppercase or lowercase), then the new Boolean object will be true. Otherwise, it will be false.


To obtain a boolean value from a Boolean object, use booleanValue( ), shown here:

boolean booleanValue( ) - It returns the boolean equivalent of the invoking object.

  • The Numeric Type Wrappers - Byte, Short, Integer, Long, Float, and Double. All of the numeric type wrappers inherit the abstract class Number. Number declares methods that return the value of an object in each of the different number formats. These methods are shown here:

byte byteValue( )

double doubleValue( )

float floatValue( )

int intValue( )

long longValue( )

short shortValue( )

doubleValue( ) returns the value of an object as a double, floatValue( ) returns the value as a float, and so on. These methods are implemented by each of the numeric type wrappers. All of the numeric type wrappers define constructors that allow an object to be constructed from a given value, or a string representation of that value. For example, here are the constructors defined for Integer:

Integer(int num)

Integer(String str)

If str does not contain a valid numeric value, then a NumberFormatException is thrown.

  • All of the type wrappers override toString( ). This allows us to output the value by passing a type wrapper object to println( ), for example, without having to convert it into its primitive type.

The following demonstrates how to use a numeric type wrapper to encapsulate a value and then extract that value.

Integer iOb = new Integer(100);
int i = iOb.intValue();

System.out.println(i + " " + iOb); // displays 100 100


The process of encapsulating a value within an object is called boxing. For ex, the following line boxes the value 100 into an Integer:

Integer iOb = new Integer(100);

The process of extracting a value from a type wrapper is called unboxing. For ex, the program unboxes the value in iOb with this statement:

int i = iOb.intValue(); 

 

Click for NEXT article.

 

Please feel free to correct me by commenting your suggestions and feedback.

Topic 31: Enumerations in Java

  • In its simplest form, an enumeration is a list of named constants.

  • In Java, an enumeration defines a class type. That means, an enumeration can have constructors, methods, and instance variables.

  • An enumeration is created using the enum keyword. For example, here is a simple enumeration that lists various apple varieties:

enum Apple
{
Jonathan, GoldenDel, RedDel, Winesap, Cortland
}

The identifiers Jonathan, GoldenDel, and so on, are called enumeration constants. Each is implicitly declared as a public, static final member of Apple. Furthermore, their type is the type of the enumeration in which they are declared, which is Apple in this case. Thus, in the language of Java, these constants are called self-typed, in which “self” refers to the enclosing enumeration.

  • We can create a variable of enumeration type. We declare and use an enumeration variable in much the same way as we do one of the primitive types. For example, this declares ap as a variable of enumeration type Apple: 

    Apple ap;

Because ap is of type Apple, the only values that it can be assigned (or can contain) are those defined by the enumeration. For example, this assigns ap the value RedDel:

ap = Apple.RedDel; //RedDel is preceded by Apple.

  • Two enumeration constants can be compared for equality by using the = = relational operator. For example, this statement compares the value in ap with the GoldenDel constant:

if(ap == Apple.GoldenDel) // ...

  • An enumeration value can also be used to control a switch statement. Of course, all of the case statements must use constants from the same enum as that used by the switch expression. For example, this switch is perfectly valid:

switch(ap) {
case Jonathan:
// ...
case Winesap:
// ...

Notice that in the case statements, the names of the enumeration constants are used without being qualified by their enumeration type name. This is because the type of the enumeration in the switch expression has already implicitly specified the enum type of the case constants. There is no need to qualify the constants in the case statements with their enum type name. In fact, attempting to do so will cause a compilation error.

  • When an enumeration constant is displayed, such as in a println( ) statement, its name is output. For example, given this statement:

System.out.println(Apple.Winesap); //the name Winesap is displayed.

  • All enumerations automatically contain two predefined methods: values( ) and valueOf( ). Their general forms are shown here:

public static enum-type[ ] values( )

public static enum-type valueOf(String str)

The values( ) method returns an array that contains a list of the enumeration constants. The valueOf( ) method returns the enumeration constant whose value corresponds to the string passed in str. In both cases, enum-type is the type of the enumeration. For example:

// use values()
Apple allapples[] = Apple.values();
for(Apple a : allapples)
System.out.println(a);

// use valueOf()
ap = Apple.valueOf("Winesap");
System.out.println("ap contains " + ap);

  • In Java, enumeration is a class type and each enumeration constant is an object of its enumeration type. When we define a constructor for an enum, the constructor is called when each enumeration constant is created. Also, each enumeration constant has its own copy of any instance variables defined by the enumeration. For example, consider the following version of Apple:

// Use an enum constructor, instance variable, and method.
enum Apple {
Jonathan(10), GoldenDel(9), RedDel(12), Winesap(15), Cortland(8);

//Instance variable
private int price; // price of each apple

// Constructor
Apple(int p) { price = p; }

//Instance method
int getPrice() { return price; }
}

Apple ap;

// Display price of Winesap.
System.out.println("Winesap costs " + Apple.Winesap.getPrice() + " cents.\n");
// Display all apples and prices.
for(Apple a : Apple.values())
System.out.println(a + " costs " + a.getPrice() + " cents.");

When the variable ap is declared, the constructor for Apple is called once for each constant that is specified. Notice how the arguments to the constructor are specified, by putting them inside parentheses after each constant, as shown here:

Jonathan(10), GoldenDel(9), RedDel(12), Winesap(15), Cortland(8);

These values are passed to the p parameter of Apple( ), which then assigns this value to price.

Because each enumeration constant has its own copy of price, we can obtain the price of a specified type of apple by calling getPrice( ). For example:

Apple.Winesap.getPrice()

  • An enum can have two or more constructor overloaded forms, just as can any other class. For ex:

// Use an enum constructor.
enum Apple {
Jonathan(10), GoldenDel(9), RedDel, Winesap(15), Cortland(8);
private int price; // price of each apple


// Constructor
Apple(int p) { price = p; }

// Overloaded constructor
Apple() { price = -1; }

}

Notice that in this version, RedDel is not given an argument. This means that the default constructor is called, and RedDel’s price variable is given the value –1.

  • Enumeration can’t inherit another class and also cannot be a superclass. This means that an enum can’t be extended.This come with one exception, i.e. all enumerations automatically inherit one: java.lang.Enum. This class defines several methods that are available for use by all enumerations.

    We can obtain a value that indicates an enumeration constant’s position, called its ordinal value, in the list of constants by calling the ordinal( ) method, shown here:

final int ordinal( )

It returns the ordinal value of the invoking constant. Ordinal values begin at zero. Thus, in the Apple enumeration, Jonathan has an ordinal value of zero, GoldenDel has an ordinal value of 1, RedDel has an ordinal value of 2, and so on.

We can compare the ordinal value of two constants of the same enumeration by using the compareTo() method. It has this general form:

final int compareTo(enum-type e)

Here, enum-type is the type of the enumeration, and e is the constant being compared to the invoking constant. Remember, both the invoking constant and e must be of the same enumeration. If the invoking constant has an ordinal value less than e’s, then compareTo( ) returns a negative value. If the two ordinal values are the same, then zero is returned. If the invoking constant has an ordinal value greater than e’s, then a positive value is returned.

We can compare for equality an enumeration constant with any other object by using equals( ), which overrides the equals( ) method defined by Object. Simply having ordinal values in common will not cause equals() to return true if the two constants are from different enumerations. Remember, we can compare two enumeration references for equality by using = =.

Apple ap, ap2, ap3;
// Obtain ordinal values using ordinal().
for(Apple a : Apple.values())
System.out.println(a + " " + a.ordinal());


ap =  Apple.RedDel;
ap2 = Apple.RedDel;

// Demonstrate compareTo() and equals()
if(ap.compareTo(ap2) < 0)
System.out.println(ap + " comes before " + ap2);

if(ap.equals(ap2))
System.out.println(ap + " equals " + ap2);
if(ap == ap2)
System.out.println(ap + " == " + ap2);


Click for NEXT article.

 

Please feel free to correct me by commenting your suggestions and feedback.

Monday, January 25, 2016

Topic 30: MultiThreading in Java

  • Java provides built-in support for multithreaded programming. A multithreaded program contains two or more parts that can run concurrently. Each part of such a program is called a thread, and each thread defines a separate path of execution. Thus, multithreading is a specialized form of multitasking. 

  • Threads are lightweight. They share the same address space and cooperatively share the same heavyweight process. 

    Interthread communication is inexpensive, and context switching from one thread to the next is low cost.

  • Java uses threads to enable the entire environment to be asynchronous. This helps reduce inefficiency by preventing the wastage of CPU cycles.

  • Threads exist in several states. A thread can be running. It can be ready to run as soon as it gets CPU time. A running thread can be suspended, which temporarily suspends its activity. A suspended thread can then be resumed, allowing it to pick up where it left off. A thread can be blocked when waiting for a resource. At any time, a thread can be terminated, which halts its execution immediately. Once terminated, a thread cannot be resumed.

  • Thread priorities are integers that specify the relative priority of one thread to another. A thread’s priority is used to decide when to switch from one running thread to the next. This is called a context switch. The rules that determine when a context switch takes place are simple:

  • A thread can voluntarily relinquish control. In this scenario, all other threads are examined, and the highest-priority thread that is ready to run is given the CPU.

  • A thread can be preempted by a higher-priority thread. In this case, a lower-priority thread that does not yield the processor is simply preempted—no matter what it is doing— by a higher-priority thread. This is called preemptive multitasking.

For operating systems such as Windows, threads of equal priority are time-sliced automatically in round-robin fashion. For other types of operating systems, threads of equal priority must voluntarily yield control to their peers. If they don’t, the other threads will not run.

  • To synchronize two or more threads that share a resource, Java uses the monitor. We can think of a monitor as a very small box that can hold only one thread. Once a thread enters a monitor, all other threads must wait until that thread exits the monitor. In this way, a monitor can be used to protect a shared asset from being manipulated by more than one thread at a time. There is no class “Monitor”; instead, each object has its own implicit monitor that is automatically entered when one of the object’s synchronized methods is called. Once a thread is inside a synchronized method, no other thread can call any other synchronized method on the same object.

  • After we divide our program into separate threads, we need to define how they will communicate with each other. Java provides a clean, low-cost way for two or more threads to talk to each other, via calls to predefined methods that all objects have. Java’s messaging system allows a thread to enter a synchronized method on an object, and then wait there until some other thread explicitly notifies it to come out.

  • Java’s multithreading system is built upon the Thread class, its methods, and its companion interface, Runnable

    Thread encapsulates a thread of execution.  

    To create a new thread, our program will either extend Thread or implement the Runnable interface. 

  • When a Java program starts up, one thread begins running immediately. This is usually called the main thread. It is the one that is executed when program begins. The main thread is important for two reasons:

  • It is the thread from which other “child” threads will be spawned.

  • Often, it must be the last thread to finish execution because it performs various shutdown actions.

Main thread, like child threads, can be controlled through a Thread object. To do so, we must obtain a reference to it by calling the method currentThread( ), which is a public static member of Thread. Its general form is shown here:

static Thread currentThread( )

This method returns a reference to the thread in which it is called. For example:

// Controlling the main Thread.
class CurrentThreadDemo
{
public static void main(String args[])
{
Thread t = Thread.currentThread();
System.out.println("Current thread: " + t);


// change the name of the thread
t.setName("My Thread"); //setName() changes the internal name of the thread
System.out.println("After name change: " + t);
try
{
for(int n = 5; n > 0; n--)
{
Thread.sleep(1000); //argument is delay period in milliseconds
}
}
//The sleep( ) method in Thread might throw an InterruptedException. This would happen if some other thread wanted to interrupt this sleeping one.
catch (InterruptedException e)
{
System.out.println("Main thread interrupted");
}
}
}

Here is the output generated by this program:

Current thread: Thread[main,5,main]

After name change: Thread[My Thread,5,main]

Notice the output produced when t is used as an argument to println( ). This displays, in order: the name of the thread, its priority, and the name of its group. By default, the name of the main thread is main. Its priority is 5, which is the default value, and main is also the name of the group of threads to which this thread belongs. A thread group is a data structure that controls the state of a collection of threads as a whole. 

  • The sleep( ) method causes the thread from which it is called to suspend execution for the specified period of milliseconds. Its general form is shown here:

static void sleep(long milliseconds) throws InterruptedException

The sleep( ) method has a second form, shown next, which allows to specify the period in terms of milliseconds and nanoseconds:

static void sleep(long milliseconds, int nanoseconds) throws InterruptedException

This second form is useful only in environments that allow timing periods as short as nanoseconds.

  • We can set the name of a thread by using setName( ). We can obtain the name of a thread by calling getName( ) . These methods are members of the Thread class and are declared like this:
    final void setName(String threadName)
    final String getName( )

  • The easiest way to create a thread is to create a class that implements the Runnable interface. To implement Runnable, a class need only implement a single method called run( ), which is declared like this:

public void run( )

Inside run( ), we will define the code that constitutes the new thread. run( ) establishes the entry point for another, concurrent thread of execution within our program. This thread will end when run( ) returns.

After we create a class that implements Runnable, we will instantiate an object of type Thread from within that class. Thread defines several constructors. The one that we will use is shown here:

Thread(Runnable threadOb, String threadName)

In this constructor, threadOb is an instance of a class that implements the Runnable interface. This defines where execution of the thread will begin. The name of the new thread is specified by threadName. After the new thread is created, it will not start running until we call its start( ) method, which is declared within Thread. In essence, start( ) executes a call to run( ). The start( ) method is shown here:

void start( )

Here is an example that creates a new thread and starts it running:

// Create a second thread.
class NewThread implements Runnable
{
Thread t;

NewThread()
{
// Create a new, second thread
t = new Thread(this, "Demo Thread"); //constructor for Thread class

System.out.println("Child thread: " + t);
t.start(); // Start the thread
}

// This is the entry point for the second thread.
public void run()
{
try
{
for(int i = 5; i > 0; i--)
{
System.out.println("Child Thread: " + i);
Thread.sleep(500);
}
}
catch (InterruptedException e)
{
System.out.println("Child interrupted.");
}
System.out.println("Exiting child thread.");
}


}


class ThreadDemo
{
public static void main(String args[])
{
new NewThread(); // create a new thread
try
{
for(int i = 5; i > 0; i--)
{
System.out.println("Main Thread: " + i);
Thread.sleep(1000);
}
}
catch (InterruptedException e)
{
System.out.println("Main thread interrupted.");
}
System.out.println("Main thread exiting.");
}
}

After calling start( ), NewThread’s constructor returns to main( ). Both threads continue running, sharing the CPU, until their loops finish.


As mentioned earlier, in a multithreaded program, often the main thread must be the last thread to finish running. The preceding program ensures that the main thread finishes last, because the main thread sleeps for 1,000 milliseconds between iterations, but the child thread sleeps for only 500 milliseconds.

  • The second way to create a thread is to create a new class that extends Thread, and then to create an instance of that class. The extending class must override the run( ) method, which is the entry point for the new thread. It must also call start( ) to begin execution of the new thread. Here is the preceding program rewritten to extend Thread:

// Create a second thread by extending Thread
class NewThread extends Thread
{
NewThread()
{
// Create a new, second thread
super("Demo Thread");

System.out.println("Child thread: " + this);
start(); // Start the thread
}
// This is the entry point for the second thread.
public void run()
{
try
{
for(int i = 5; i > 0; i--)
{
System.out.println("Child Thread: " + i);
Thread.sleep(500);
}
}
catch (InterruptedException e)
{
System.out.println("Child interrupted.");
}
System.out.println("Exiting child thread.");
}
}
class ExtendThread
{
public static void main(String args[])
{
new NewThread(); // create a new thread
try
{
for(int i = 5; i > 0; i--)
{
System.out.println("Main Thread: " + i);
Thread.sleep(1000);
}
}
catch (InterruptedException e)
{
System.out.println("Main thread interrupted.");
}
System.out.println("Main thread exiting.");
}
}

Notice the call to super( ) inside NewThread. This invokes the following form of the Thread constructor:

public Thread(String threadName)

Here, threadName specifies the name of the thread.

  • Often we will want the main thread to finish last. Two ways exist to determine whether a thread has finished. 

    First, we can call isAlive( ) on the thread. This method is defined by Thread, and its general form is shown here:

final boolean isAlive( )

The isAlive( ) method returns true if the thread upon which it is called is still running. It returns false otherwise.


While isAlive( ) is occasionally useful, we will more commonly use join( ) to wait for a thread to finish, shown here:

final void join( ) throws InterruptedException

This method waits until the thread on which it is called terminates.


Preceding example using Runnable interface and sleep() rewritten using join( ) to ensure that the main thread is the last to stop. It also demonstrates the isAlive( ) method.

NewThread ob1 = new NewThread();
System.out.println("Thread One is alive: " + ob1.t.isAlive());
// wait for threads to finish
try
{
System.out.println("Waiting for threads to finish.");
ob1.t.join();
}
catch (InterruptedException e)
{
System.out.println("Main thread Interrupted");
}

  • To set a thread’s priority, use the setPriority( ) method, which is a member of Thread. This is its general form:

final void setPriority(int level)

Here, level specifies the new priority setting for the calling thread. The value of level must be within the range MIN_PRIORITY and MAX_PRIORITY. Currently, these values are 1 and 10, respectively. To return a thread to default priority, specify NORM_PRIORITY, which is currently 5. These priorities are defined as static final variables within Thread.


We can obtain the current priority setting by calling the getPriority( ) method of Thread, shown here:

final int getPriority( )

The following example demonstrates two threads at different priorities. One thread is set two levels above the normal priority, as defined by Thread.NORM_ PRIORITY, and the other is set to two levels below it.

// Demonstrate thread priorities.
Thread t1 = new Thread(this);
Thread t2 = new Thread(this);

t1.setPriority(Thread.NORM_PRIORITY + 2);
t2.setPriority(Thread.NORM_PRIORITY - 2);

  • When two or more threads need access to a shared resource, they need some way to ensure that the resource will be used by only one thread at a time. The process by which this is achieved is called synchronization. Key to synchronization is the concept of the monitor (also called a semaphore).
    We can synchronize our code in either of two ways:

      Using Synchronized Methods

      Synchronization is easy in Java, because all objects have their own implicit monitor associated with them. To enter an object’s monitor, just call a method that has been modified with the synchronized keyword. While a thread is inside a synchronized method, all other threads that try to call it (or any other synchronized method) on the same instance have to wait. To exit the monitor and relinquish control of the object to the next waiting thread, the owner of the monitor simply returns from the synchronized method. To understand the need for synchronization, let’s begin with a simple example.

    // This program is not synchronized.
    class Callme
    {

    synchronized void call(String msg)
    {
    System.out.print("[" + msg);
    try
    {
    Thread.sleep(1000);
    }
    catch(InterruptedException e)
    {
    System.out.println("Interrupted");
    }
    System.out.println("]");
    }
    }
    class Caller implements Runnable
    {
    String msg;
    Callme target;
    Thread t;
    public Caller(Callme targ, String s)
    {
    target = targ;
    msg = s;
    t = new Thread(this);
    t.start();
    }
    public void run()
    {
    target.call(msg);
    }
    }
    class Synch
    {
    public static void main(String args[])
    {
    Callme target = new Callme();
    Caller ob1 = new Caller(target, "Hello");
    Caller ob2 = new Caller(target, "Synchronized");
    Caller ob3 = new Caller(target, "World");
    // wait for threads to end
    try
    {
    ob1.t.join();
    ob2.t.join();
    ob3.t.join();
    }
    catch(InterruptedException e)
    {
    System.out.println("Interrupted");
    }
    }
    }

    Here is the output produced by this program:

    [Hello] [Synchronized] [World]

    The synchronized Statement

    Suppose class was created by a third party, and we do not have access to the source code. Thus, we can’t add synchronized to the appropriate methods within the class. But we can simply put calls to the methods defined by this class inside a synchronized block. This is the general form of the synchronized statement:

    synchronized(object) {

    // statements to be synchronized

    }

    Here, object is a reference to the object being synchronized. A synchronized block ensures that a call to a method that is a member of object occurs only after the current thread has successfully entered object’s monitor. Here is an alternative version of the preceding example, using a synchronized block within the run( ) method:

    // synchronize calls to call()
    public void run()
    {
    synchronized(target)


    { // synchronized block
    target.call(msg);
    }

    }

    • Interthread communication using final methods in Object wait( ), notify( ), notifyAll( ) methods. All classes have them.

      final void wait( ) throws InterruptedException

      final void notify( )

      final void notifyAll( )

      All three methods can be called only from within a synchronized context.

    wait( ) tells the calling thread to give up the monitor and go to sleep until some other thread enters the same monitor and calls notify( ).

    notify( ) wakes up a thread that called wait( ) on the same object.

    notifyAll( ) wakes up all the threads that called wait( ) on the same object. One of the threads will be granted access.

    Sun recommends that calls to wait( ) should take place within a loop that checks the condition on which the thread is waiting. The following example shows this technique.

    • The following sample program that implements a simple form of the producer/ consumer problem. It consists of four classes: Q representing the queue, Producer, the threaded object that is producing queue entries; Consumer, the threaded object that is consuming queue entries; and PC, the tiny class that creates the single Q, Producer, and Consumer.

    class Q
    {
    int n;
    boolean emptyQ = false;

    synchronized int get()
    {
    while(!emptyQ)
    try
    {
    wait();
    }
    catch(InterruptedException e)
    {
    System.out.println("InterruptedException caught");
    }
    System.out.println("Got: " + n);
    emptyQ = false;
    notify();
    return n;
    }

    synchronized void put(int n)
    {
    while(emptyQ)
    try
    {
    wait();
    }
    catch(InterruptedException e)
    {
    System.out.println("InterruptedException caught");
    }
    this.n = n;
    emptyQ = true;
    System.out.println("Put: " + n);
    notify();
    }
    }

    class Producer implements Runnable
    {
    Q q;
    Producer(Q q)
    {
    this.q = q;
    new Thread(this, "Producer").start();
    }

    public void run()
    {
    int i = 0;
    while(true)
    {
    q.put(i++);
    }
    }
    }

    class Consumer implements Runnable
    {
    Q q;
    Consumer(Q q)
    {
    this.q = q;
    new Thread(this, "Consumer").start();
    }
    public void run()
    {
    while(true)
    {
    q.get();
    }
    }
    }

    class PC
    {
    public static void main(String args[])
    {
    Q q = new Q();
    new Producer(q);
    new Consumer(q);
    System.out.println("Press Control-C to stop.");
    }
    }

    • Deadlock occurs when two threads have a circular dependency on a pair of synchronized objects. For example, suppose one thread enters the monitor on object X and another thread enters the monitor on object Y. If the thread in X tries to call any synchronized method on Y, it will block as expected. However, if the thread in Y, in turn, tries to call any synchronized method on X, the thread waits forever, because to access X, it would have to release its own lock on Y so that the first thread could complete.



    Click for NEXT article.



    Please feel free to correct me by commenting your suggestions and feedback.

    Topic 29: Exception Handling in Java

    • An exception is a run-time error.  

    • A Java exception is an object that describes an exceptional (that is, error) condition that has occurred in a piece of code. When an exceptional condition arises, an object representing that exception is created and thrown in the method that caused the error. That method may choose to handle the exception itself, or pass it on. Either way, at some point, the exception is caught and processed. 

    Exceptions can be generated by the Java run-time system, or they can be manually generated by our code. Exceptions thrown by Java relate to fundamental errors that violate the rules of the Java language or the constraints of the Java execution environment. Manually generated exceptions are typically used to report some error condition to the caller of a method.

    • Java exception handling is managed via five keywords: try, catch, throw, throws, and finally

    Program statements that we want to monitor for exceptions are contained within a try block. If an exception occurs within the try block, it is thrown. Our code can catch this exception (using catch) and handle it in some rational manner. System-generated exceptions are automatically thrown by the Java run-time system. To manually throw an exception, use the keyword throw. Any exception that is thrown out of a method must be specified as such by a throws clause. Any code that absolutely must be executed after a try block completes is put in a finally block.

    This is the general form of an exception-handling block:

    try
    {
    // block of code to monitor for errors
    }
    catch (ExceptionType1 exOb)
    {
    // exception handler for ExceptionType1
    }
    catch (ExceptionType2 exOb)
    {
    // exception handler for ExceptionType2
    }
    // ...
    finally
    {
    // block of code to be executed after try block ends
    }


    Here, ExceptionType is the type of exception that has occurred.

    • All exception types are subclasses of the built-in class Throwable. Thus, Throwable is at the top of the exception class hierarchy. 

    Immediately below Throwable are two subclasses:


    • One branch is headed by Exception. This class is used for exceptional conditions that user programs should catch. This is also the class that we will subclass to create your own custom exception types.

    • The other branch is topped by Error, which defines exceptions that are not expected to be caught under normal circumstances by our program. Exceptions of type Error are used by the Java run-time system to indicate errors having to do with the run-time environment, itself. Stack overflow is an example of such an error.

    It is useful to see what happens when we don’t handle Exceptions. When the Java run-time system detects an exception, it constructs a new exception object and then throws this exception. This causes the execution of program to stop, because once an exception has been thrown, it must be caught by an exception handler and dealt with immediately. Any exception that is not caught by our program will ultimately be processed by the default handler. The default handler displays a string describing the exception, prints a stack trace(The call stack is quite useful for debugging, because it pinpoints the precise sequence of steps that led to the error) from the point at which the exception occurred, and terminates the program.

    • Although the default exception handler provided by the Java run-time system is useful for debugging, we will usually want to handle an exception our self. Doing so provides two benefits. First, it allows us to fix the error. Second, it prevents the program from automatically terminating.

    To guard against and handle a run-time error, simply enclose the code that we want to monitor inside a try block. Immediately following the try block, include a catch clause that specifies the exception type that we wish to catch. Consider the code fragment:

    int d = 0, a;
    try
    {
    a = 42 / d;
    System.out.println("This will not be printed.");
    }
    catch (ArithmeticException e)
    {
    // catch divide-by-zero error
    System.out.println("Division by zero.");
    }

    The println( ) inside the try block is never executed. Reason is once an exception is thrown, program control transfers out of the try block into the catch block. Once the catch statement has executed, program control continues with the next line in the program following the entire try/catch mechanism.

    A try and its catch statement form a unit.


    We cannot use try on a single statement.

    • Throwable overrides the toString( ) method (defined by Object) so that it returns a string containing a description of the exception. We can display this description in a println( ) statement by simply passing the exception as an argument. For example:

    catch (ArithmeticException e)
    {
    System.out.println("Exception: " + e);
    }

    This is useful while debugging.

    • In some cases, more than one exception could be raised by a single piece of code. To handle this type of situation, we can specify two or more catch clauses, each catching a different type of exception. When an exception is thrown, each catch statement is inspected in order, and the first one whose type matches that of the exception is executed. After one catch statement executes, the others are bypassed, and execution continues after the try/catch block.

    When using multiple catch statements, it is important to remember that exception subclasses must come before any of their superclasses. This is because a catch statement that uses a superclass will catch exceptions of that type plus any of its subclasses. Thus, a subclass would never be reached if it came after its superclass and result in unreachable code which is an error.

    • The try statement can be nested. Each time a try statement is entered, the context of that exception is pushed on the stack. If an inner try statement does not have a catch handler for a particular exception, the stack is unwound and the next try statement’s catch handlers are inspected for a match. This continues until one of the catch statements succeeds, or until all of the nested try statements are exhausted. If no catch statement matches, then the Java run-time system will handle the exception.

    We can enclose a call to a method within a try block. Inside that method is another try statement. In this case, the try within the method is still nested inside the outer try block, which calls the method.

    • It is possible for our program to throw an exception explicitly, using the throw statement. The general form of throw is shown here:

    throw ThrowableInstance;

    Here, ThrowableInstance must be an object of type Throwable or a subclass of Throwable.

    There are two ways we can obtain a Throwable object: using a parameter in a catch clause, or creating one with the new operator. The flow of execution stops immediately after the throw statement; any subsequent statements are not executed. The nearest enclosing try block is inspected to see if it has a catch statement that matches the type of exception. If it does find a match, control is transferred to that statement. If not, then the next enclosing try statement is inspected, and so on. If no matching catch is found, then the default exception handler halts the program and prints the stack trace.

    Sample code fragment that creates and throws an exception. The handler that catches the exception rethrows it to the outer handler.

    try
    {
    try
    {
    throw new NullPointerException("Inner try");
    }
    catch(NullPointerException e)
    {
    System.out.println("Inner catch");
    throw e; // rethrow the exception
    }

    }
    catch(NullPointerException e)
    {
    System.out.println("Recaught: " + e);
    }

    • If a method is capable of causing an exception that it does not handle, it must specify this behavior so that callers of the method can guard themselves against that exception. We do this by including a throws clause in the method’s declaration.  

      A throws clause lists the types of exceptions that a method might throw. This is necessary for all exceptions, except those of type Error or RuntimeException, or any of their subclasses.  

      All other exceptions that a method can throw must be declared in the throws clause. If they are not, a compile-time error will result. 

      This is the general form of a method declaration that includes a throws clause:

    type method-name(parameter-list) throws exception-list
    {
    // body of method
    }

    Here, exception-list is a comma-separated list of the exceptions that a method can throw. 

    Sample code:

    static void throwOne() throws IllegalAccessException
    {
    System.out.println("Inside throwOne.");
    throw new IllegalAccessException("demo");
    }
    public static void main(String args[])
    {
    try
    {
    throwOne();
    }
    catch (IllegalAccessException e)
    {
    System.out.println("Caught " + e);
    }
    }

    • finally creates a block of code that will be executed after a try/catch block has completed and before the code following the try/catch block.  

      The finally block will execute whether or not an exception is thrown. If an exception is thrown, the finally block will execute even if no catch statement matches the exception. 

      Any time a method is about to return to the caller from inside a try/catch block, via an uncaught exception or an explicit return statement, the finally clause is also executed just before the method returns. This can be useful for closing file handles and freeing up any other resources that might have been allocated at the beginning of a method with the intent of disposing of them before returning. 

      The finally clause is optional. However, each try statement requires at least one catch or a finally clause. 

      Sample code shows three methods that exit in various ways after executing their finally clauses:

    // Through an exception out of the method.
    static void procA()
    {
    try
    {
    System.out.println("inside procA");
    throw new RuntimeException("demo");
    }
    finally
    {
    System.out.println("procA's finally");
    }
    }


    // Return from within a try block.
    static void procB()
    {
    try
    {
    System.out.println("inside procB");
    return;
    }
    finally
    {
    System.out.println("procB's finally");
    }
    }


    // Execute a try block normally.
    static void procC()
    {
    try
    {
    System.out.println("inside procC");
    }
    finally
    {
    System.out.println("procC's finally");
    }
    }
    public static void main(String args[])
    {
    try
    {
    procA();
    }
    catch (Exception e)
    {
    System.out.println("Exception caught");
    }
    procB();
    procC();
    }

    • Those exceptions defined by java.lang and subclasses of RuntimeException need not be included in any method’s throws list. These are called unchecked exceptions because the compiler does not check to see if a method handles or throws these exceptions. 

      Those exceptions defined by java.lang that must be included in a method’s throws list if that method can generate one of these exceptions and does not handle it itself. These are called checked exceptions.

    • We can create a subclass of Exception. The Exception class does not define any methods of its own but inherit methods provided by its superclass Throwable. We may also wish to override one or more of these methods in exception classes that we create. Exception constructors:

    Exception( )

    Exception(String msg)

    The following example declares a new subclass of Exception and then uses that subclass to signal an error condition in a method. It overrides the toString( ) method, allowing a carefully tailored description of the exception to be displayed.

    // This program creates a custom exception type.
    class MyException extends Exception
    {
    private int detail;
    MyException(int a)
    {
    detail = a;
    }
    public String toString() //Override method in Exception class
    {
    return "MyException[" + detail + "]";
    }

    class ExceptionDemo
    {
    static void compute(int a) throws MyException {
    System.out.println("Called compute(" + a + ")");
    if(a > 10)
    throw new MyException(a); System.out.println("Normal exit");
    }
    public static void main(String args[])

    try {
    compute(1);
    compute(20);
    }
    catch (MyException e) {
    System.out.println("Caught " + e);
    }
    }
    }

    • The chained exception feature allows us to associate another exception with an exception. This second exception describes the cause of the first exception.


    For example, imagine a situation in which a method throws an ArithmeticException because of an attempt to divide by zero. However, the actual cause of the problem was that an I/O error occurred, which caused the divisor to be set improperly. Although the method must certainly throw an ArithmeticException, since that is the error that occurred, we might also want to let the calling code know that the underlying cause was an I/O error. Chained exceptions let us handle this, and any other in which layers of exceptions exist.  
    To allow chained exceptions, two constructors and two methods were added to Throwable. The constructors are shown here:

    Throwable(Throwable causeExc)

    Throwable(String msg, Throwable causeExc)

    In the first form, causeExc is the exception that causes the current exception. The second form allows us to specify a description at the same time that we specify a cause exception. These two constructors have also been added to the Error, Exception, and RuntimeException classes.

    The chained exception methods added to Throwable:  

    Throwable getCause( )  

    Throwable initCause(Throwable causeExc)  

    The getCause( ) method returns the exception that underlies the current exception. If there is no underlying exception, null is returned.

    The initCause( ) method associates causeExc with the invoking exception and returns a reference to the exception. Thus, we can associate a cause with an exception after the exception has been created. However, the cause exception can be set only once. Thus, we can call initCause( ) only once for each exception object. Furthermore, if the cause exception was set by a constructor, then we can’t set it again using initCause( ). In general, initCause( ) is used to set a cause for legacy exception classes that don’t support the two additional constructors described earlier. 
    Here is an example that illustrates the mechanics of handling chained exceptions:

    static void meth()
    {
    // create an exception
    NullPointerException e = new NullPointerException("top layer");
    // add a cause
    e.initCause(new ArithmeticException("cause"));
    throw e;
    }
    //Inside main()
    try
    {
    meth();
    }
    catch(NullPointerException e)
    {
    // display top level exception
    System.out.println("Caught: " + e);
    // display cause exception
    System.out.println("Original cause: " + e.getCause());
    }

    In this example, the top-level exception is NullPointerException. To it is added a cause exception, ArithmeticException. When the exception is thrown out of meth( ), it is caught by main( ). There, the top-level exception is displayed, followed by the underlying exception, which is obtained by calling getCause( ).

    Chained exceptions can be carried on to whatever depth is necessary. Thus, the cause exception can, itself, have a cause. Be aware that overly long chains of exceptions may indicate poor design.

     

    Click for NEXT article.

     

    Please feel free to correct me by commenting your suggestions and feedback.

    Topic 28: Interfaces in Java

    • Interfaces are syntactically similar to classes, but they lack instance variables, and their methods are declared without any body. 

    • Once it is defined, any number of classes can implement an interface

      One class can implement any number of interfaces. 

    • To implement an interface, a class must create the complete set of methods defined by the interface. Each class is free to determine the details of its own implementation. 

    • By providing the interface keyword, Java allows us to fully utilize the “one interface, multiple methods” aspect of polymorphism.

    • Interfaces support dynamic method resolution at run time.

    • An interface is defined much like a class. This is the general form of an interface:

    access-specifier interface name
    {
    return-type method-name1(parameter-list);
    return-type method-name2(parameter-list);
    type final-varname1 = value;
    type final-varname2 = value;
    // ...
    return-type method-nameN(parameter-list);
    type final-varnameN = value;
    }

    • When no access specifier is included, then default access results, and the interface is only available to other members of the package in which it is declared.

    • When it is declared as public, the interface can be used by any other code. In this case, the interface must be the only public interface declared in the file, and the file must have the same name as the interface.

    • name is the name of the interface, and can be any valid identifier.

    • The methods that are declared have no bodies. They end with a semicolon after the parameter list.

    •  Each class that includes an interface must implement all of the methods.

    • Variables can be declared inside of interface declarations. They are implicitly final and static, meaning they cannot be changed by the implementing class. They must also be initialized. All methods and variables are implicitly public.

    • To implement an interface, include the implements clause in a class definition, and then create the methods defined by the interface. The general form of a class that includes the implements clause looks like this:

    class classname [extends superclass] [implements interface [,interface...]]
    {
    // class-body
    }

    If a class implements more than one interface, the interfaces are separated with a comma. 

    If a class implements two interfaces that declare the same method, then the same method will be used by clients of either interface. 

    The methods that implement an interface must be declared public. 

    The type signature of the implementing method must match exactly the type signature specified in the interface definition

    • It is both permissible and common for classes that implement interfaces to define additional members of their own.

    • We can declare interface object reference variable. An instance of any class that implements the declared interface can be referred to by such a variable. When we call a method through one of these references, the correct version will be called based on the actual instance of the interface being referred to.

    An interface reference variable only has knowledge of the methods declared by its interface declaration.

    • We should be careful not to use interfaces casually in performance-critical code.

    • If a class includes an interface but does not fully implement the methods defined by that interface, then that class must be declared as abstract. Further, any class that inherits this abstract class must implement interface completely or be declared abstract itself.

    • An interface can be declared a member of a class or another interface. Such an interface is called a member interface or a nested interface

      A nested interface can be declared as public, private, or protected. This differs from a top-level interface, which must either be declared as public or use the default access level. 

      When a nested interface is used outside of its enclosing scope, it must be qualified by the name of the class or interface of which it is a member.

    Here is an example that demonstrates a nested interface:

    // A nested interface example.
    // This class contains a member interface.
    class A
    {
    // this is a nested interface
    public interface NestedIF
    {
    boolean isNotNegative(int x);
    }

    }

    // B implements the nested interface.
    class B implements A.NestedIF
    {
    public boolean isNotNegative(int x)
    {
    return x < 0 ? false : true;
    }
    }

    class NestedIFDemo
    {
    public static void main(String args[])
    {
    // use a nested interface reference
    A.NestedIF nif = new B();
    if(nif.isNotNegative(10))
    System.out.println("10 is not negative");
    if(nif.isNotNegative(-12))
    System.out.println("this won't be displayed");
    }
    }

    • We can use interfaces to import shared constants into multiple classes by simply declaring an interface that contains variables that are initialized to the desired values. When we implement this interface in a class, all of those variable names will be in scope as constants. If an interface contains no methods, then any class that includes such an interface doesn’t actually implement anything, meaning we are free to either use or not use these variables in implemented class.

    • One interface can inherit another by use of the keyword extends. The syntax is the same as for inheriting classes. 

      When a class implements an interface that inherits another interface, it must provide implementations for all methods defined within the interface inheritance chain. Following is an example:

    // One interface can extend another.
    interface A
    {
    void meth1();
    void meth2();
    }

    // B now includes meth1() and meth2() -- it adds meth3().
    interface B extends A
    {
    void meth3();
    }

    // This class must implement all of A and B
    class MyClass implements B
    {
    //method implementation statements
    }


    Click for NEXT article.

     

    Please feel free to correct me by commenting your suggestions and feedback.