Friday, December 12, 2008

The transient and volatile Modifiers

The transient and volatile Modifiers:

 

Java defines two interesting type modifiers: transient and volatile. These modifiers are used to handle somewhat specialized situations. When an instance variable is declared as transient, then its value need not persist when an object is stored.

 

For example:

 

class T {

transient int a; // will not persist

int b; // will persist

}

 

Here, if an object of type T is written to a persistent storage area, the contents of a would not be saved, but the contents of b would. The volatile modifier tells the compiler that the variable modified by volatile can be changed unexpectedly by other parts of your program. One of these situations involves multithreaded programs. (You saw an example of this in Post 11.) In a multithreaded program, sometimes, two or more threads share the same instance variable. For efficiency considerations, each thread can keep its own, private copy of such a shared variable. The real (or master) copy of the variable is updated at various times, such as when a synchronized method is entered. While this approach works fine, it may be inefficient at times. In some cases, all that really matters is that the master copy of a variable always reflects its current state. To ensure this, simply specify the variable as volatile, which tells the compiler that it must always use the master copy of a volatile variable (or, at least, always keep any private copies up to date with the master copy, and vice versa). Also, accesses to the master variable must be executed in the precise order in which they are executed on any private copy.

 

volatile in Java has, more or less, the same meaning that it has in C/C++/C#.  Using instanceof Sometimes, knowing the type of an object during run time is useful. For example, you might have one thread of execution that generates various types of objects, and another thread that processes these objects. In this situation, it might be useful for the processing thread to know the type of each object when it receives it. Another situation in which knowledge of an object's type at run time is important involves casting. In Java, an invalid cast causes a run-time error. Many invalid casts can be caught at compile time.

 

However, casts involving class hierarchies can produce invalid casts that can be detected only at run time. For example, a superclass called A can produce two subclasses, called B and C. Thus, casting a B object into type A or casting a C object into type A is legal, but casting a B object into type C (or vice versa) isn't legal. Because an object of type A can refer to objects of either B or C, how can you know, at run time, what type of object is actually being referred to before attempting the cast to type C? It could be an object of type A, B, or C. If it is an object of type B, a run-time exception will be thrown. Java provides the run-time operator instanceof to answer this question.

The instanceof operator has this general form:

 

object instanceof type

 

Here, object is an instance of a class, and type is a class type. If object is of the specified type or can be cast into the specified type, then the instanceof operator evaluates to true. Otherwise, its result is false. Thus, instanceof is the means by which your program can obtain run-time type information about an object.

 

The following program demonstrates instanceof:

// Demonstrate instanceof operator.

class A {

int i, j;

}

class B {

int i, j;

}

class C extends A {

int k;

}

class D extends A {

int k;

}

class InstanceOf {

public static void main(String args[]) {

A a = new A();

B b = new B();

C c = new C();

D d = new D();

if(a instanceof A)

System.out.println("a is instance of A");

if(b instanceof B)

System.out.println("b is instance of B");

if(c instanceof C)

System.out.println("c is instance of C");

if(c instanceof A)

System.out.println("c can be cast to A");

if(a instanceof C)

System.out.println("a can be cast to C");

334 

System.out.println();

// compare types of derived types

A ob;

ob = d; // A reference to d

System.out.println("ob now refers to d");

if(ob instanceof D)

System.out.println("ob is instance of D");

System.out.println();

ob = c; // A reference to c

System.out.println("ob now refers to c");

if(ob instanceof D)

System.out.println("ob can be cast to D");

else

System.out.println("ob cannot be cast to D");

if(ob instanceof A)

System.out.println("ob can be cast to A");

System.out.println();

// all objects can be cast to Object

if(a instanceof Object)

System.out.println("a may be cast to Object");

if(b instanceof Object)

System.out.println("b may be cast to Object");

if(c instanceof Object)

System.out.println("c may be cast to Object");

if(d instanceof Object)

System.out.println("d may be cast to Object");

}

}

 

The output from this program is shown here:

a is instance of A

b is instance of B

c is instance of C

c can be cast to A

ob now refers to d

ob is instance of D

ob now refers to c

ob cannot be cast to D

ob can be cast to A

a may be cast to Object

b may be cast to Object

c may be cast to Object

d may be cast to Object

 

The instanceof operator isn't needed by most programs, because, generally, you know the type of object with which you are working. However, it can be very useful when you're writing generalized routines that operate on objects of a complex class hierarchy.

 

strictfp

Java 2 added a new keyword to the Java language, called strictfp. With the creation of Java 2, the floating point computation model was relaxed slightly to make certain floating point computations faster for certain processors, such as the Pentium. Specifically, the new model does not require the truncation of certain intermediate values that occur during a computation. By modifying a class or a method with strictfp, you ensure that floating point calculations (and thus all truncations) take place precisely as they did in earlier versions of Java. The truncation affects only the exponent of certain operations. When a class is modified by strictfp, all the methods in the class are also modified by strictfp automatically.

 

For example, the following fragment tells Java to use the original floating point model for calculations in all methods defined within MyClass:

 

strictfp class MyClass { //...

 

Frankly, most programmers never need to use strictfp, because it affects only a very small class of problems.

No comments: