Topic 37: Additional Keywords in Java
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. 
Variable
 modified by volatile can be changed unexpectedly by other parts of the program. Specifying the variable as volatile 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). Used mostly in multithreaded programming.
 
Sometimes,
 knowing the type of an object during run time is useful. For example, we 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. The instanceof operator has this general form: 
objref instanceof type 
 
Here,
 objref is a reference to an instance of a class, and type is a class 
type. If objref 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. 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 InstanceOf 
{ 
                public static void main(String args[]) 
                { 
                                A a = new A(); 
                                B b = new B(); 
                                C c = new C(); 
                                
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"); 
System.out.println(); 
// compare types of derived types 
A ob = c; // A reference to c 
System.out.println("ob now refers to c"); 
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"); 
} 
}   
 
By modifying a class or a method with strictfp, we  ensure that floating-point calculations (and thus all truncations) 
take place precisely as they did in earlier versions of Java. 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. 
Keyword assert is used 
during program development to create an assertion, which is a condition 
that should be true during the execution of the program. For example,we  might have a method that should always return a positive integer 
value. We might test this by asserting that the return value is greater
 than zero using an assert statement. At run time, if the condition 
actually is true, no other action takes place. However, if the condition
 is false, then an AssertionError is thrown. Assertions are often used 
during testing to verify that some expected condition is actually met. 
They are not usually used for released code. 
 
The assert keyword has two forms. The first is shown here: 
assert condition; 
Here,
 condition is an expression that must evaluate to a Boolean result. If 
the result is true, then the assertion is true and no other action takes
 place. If the condition is false, then the assertion fails and a 
default AssertionError object is thrown. 
The second form of assert is 
shown here: 
assert condition : expr; 
In
 this version, expr is a value that is passed to the AssertionError 
constructor. This value is converted to its string format and displayed 
if an assertion fails. Typically, we will specify a string for expr, 
but any non-void expression is allowed as long as it defines a 
reasonable string conversion. 
Here is an example that uses assert. It 
verifies that the return value of getnum( ) is positive. 
// Demonstrate assert. 
class AssertDemo 
{ 
                static int val = 3; 
                // Return an integer. 
                static int getnum() 
                { 
                                return val--; 
                } 
public static void main(String args[]) 
{ 
int n; 
for(int i=0; i < 10; i++) 
{ 
n = getnum(); 
assert n > 0; // will fail when n is 0 
System.out.println("n is " + n); 
} 
} 
}   
 
 
To
 enable assertion checking at run time, we must specify the -ea option.
 For example, to enable assertions for AssertDemo, execute it using this
 line: 
java -ea AssertDemo 
As
 explained, we can specify the message displayed when an assertion 
fails. For example, we can specify:
 assert n > 0 : "n is 
negative!"; 
One
 important point to understand about assertions is that we must not 
rely on them to perform any action actually required by the program. The
 reason is that normally, released code will be run with assertions 
disabled. For ex:
 
                                                assert (n = getnum()) > 0; // This is not a good idea!
This works fine if assertions are enabled, it
 will cause a malfunction when assertions are disabled, because the call
 to getnum( ) will never be executed! In fact, n must now be 
initialized, because the compiler will recognize that it might not be 
assigned a value by the assert statement. 
Assertions
 are a good addition to Java because they streamline the type of error 
checking that is common during development. For example, prior to 
assert, if we wanted to verify that n was positive in the preceding 
program, we had to use a sequence of code similar to this: 
if(n < 0){System.out.println("n is negative!"); return; // or throw an exception} 
With
 assert, you need only one line of code. Furthermore, we don’t have to 
remove the assert statements from our released code. 
When
 executing code, we can disable assertions by using the -da option. We can enable or disable a specific package by specifying its name after 
the -ea or -da option. For example, to enable assertions in a package 
called MyPack:
 -ea:MyPack 
To disable assertions in MyPack:
 -da:MyPack 
To enable or disable all subpackages of a package, follow the package name with three dots: 
-ea:MyPack... 
We can also specify a class with the -ea or -da option. For example, this enables AssertDemo individually: 
-ea:AssertDemo 
A new feature to Java called static import that expands the 
capabilities of the import keyword. By following import with the keyword
 static, an import statement can be used to import the static members of
 a class or interface. When using static import, it is possible to 
refer to static members directly by their names, without having to 
qualify them with the name of their class.
To
 understand the usefulness of static import, let’s begin with an example
 that does not use it. The following code fragment computes the hypotenuse of a
 right triangle. It uses two static methods from Java’s built-in math 
class Math, which is part of java.lang. The first is Math.pow( ), which 
returns a value raised to a specified power. The second is Math.sqrt( ),
 which returns the square root of its argument. 
 
                                // Notice how sqrt() and pow() must be qualified by their class name, which is Math. 
                                hypot = Math.sqrt(Math.pow(side1, 2) + Math.pow(side2, 2)); 
Because
 pow( ) and sqrt( ) are static methods, they must be called through the 
use of their class’ name, Math. As
 this simple example illustrates, having to specify the class name each 
time pow( ) or sqrt( ) is used can grow tedious. We can use static 
import in such cases: 
import static java.lang.Math.sqrt; 
import static java.lang.Math.pow; 
class Hypot {//...
                                hypot = sqrt(pow(side1, 2) + pow(side2, 2));
There are two general forms of the import static statement:
The
 first, brings into view a 
single name. Its general form is shown here:
 
import static 
pkg.type-name.static-member-name; 
Here,
 type-name is the name of a class or interface that contains the desired
 static member. Its full package name is specified by pkg. The name of 
the member is specified by static-member-name. 
The
 second form, imports all static members of a given class or interface. 
Its general form is shown here: 
 
import static pkg.type-name.*; 
One
 other point: in addition to importing the static members of classes and
 interfaces defined by the Java API, we can also use static import to 
import the static members of classes and interfaces that we create. If using a static member once or twice 
in the program, it’s best not to import it. Static import is designed for those situations in which we are using a static member repeatedly, such as when performing a series 
of mathematical computations. 
When
 working with overloaded constructors, it is sometimes useful for one 
constructor to invoke another. In Java, this is accomplished by using 
another form of the this keyword. The general form is shown here: 
this(arg-list) 
 
When
 this( ) is executed, the overloaded constructor that matches the 
parameter list specified by arg-list is executed first. The call to this( ) must be the first statement within the constructor. To
 understand how this( ) can be used, let’s work through a short example.
 First, consider the following class that does not use this( ): 
class MyClass 
{ 
                int a, b; 
                // initialize a and b individually 
                MyClass(int i, int j) { a = i;      b = j;        } 
                // initialize a and b to the same value 
                MyClass(int i) { a = b = i; } 
                // give a and b default values of 0 
                MyClass( ) { a = b = 0; } 
}   
By using this( ), it is 
possible to rewrite MyClass as shown here: 
// initialize a and b individually 
                
MyClass(int i, int j) { a = i;      b = j;        } 
// initialize a and b to the same value 
                MyClass(int i) 
                { 
                                this(i, i); // invokes MyClass(i, i) 
                } 
                // give a and b default values of 0 
                MyClass( ) 
                { 
                                this(0); // invokes MyClass(0) 
                }
In
 this version of MyClass, the only constructor that actually assigns 
values to the a and b fields is MyClass(int, int). The other two 
constructors simply invoke that constructor (either directly or 
indirectly) through this( ). For example, consider what happens when 
this statement executes: 
MyClass mc = new MyClass(8); 
The
 call to MyClass(8) causes this(8, 8) to be executed, which translates 
into a call to MyClass(8, 8), because this is the version of the MyClass
 constructor whose parameter list matches the arguments passed via this(
 ). Now, consider the following statement, which uses the default 
constructor: 
MyClass mc2 = new MyClass(); 
In
 this case, this(0) is called. This causes MyClass(0) to be invoked 
because it is the constructor with the matching parameter list. Of 
course, MyClass(0) then calls MyClass(0, 0) as just described. 
One 
reason why invoking overloaded constructors through this( ) can be 
useful is that it can prevent the unnecessary duplication of code. 
Constructors that call this( ) will execute a bit slower
 than those that contain all of their initialization code inline. This 
is because the call and return mechanism used when the second 
constructor is invoked adds overhead. 
There are two restrictions when using this( ). 
First, we cannot use any instance variable of the constructor’s class in a call to this( ).
 
Second, we cannot use super( ) and this( ) in the same 
constructor because each must be the first statement in the constructor.
 
 
Click for NEXT article. 
 
Please feel free to correct me by commenting your suggestions and feedback.
 
 
 
 
          
      
 
  
 
 
 
 
 
 
 
 
 
 
 
No comments:
Post a Comment