Thursday, September 4, 2014

Changing behavior of object at runtime.


annonymous innerclass

Inheritance is a very strong feature in java. Among other things it enables us to change behavior of objects at runtime. Lets consider an example.

Consider a class TextFormat having a method displayText(String msg). The method prints the text message that is passed as param without any formating.


package format;
public class TextFormat {
 public void print(String msg){
  System.out.println(msg);
 }
}

package format;
public class Client {
 public static void main(String[] args) {
  TextFormat tf = new TextFormat();
  tf.print("Testing the power of LATE BINDING");
 }
}
Output : Testing the power of LATE BINDING

A client can call the display method through the interface* TextFormat and see the message displayed on the console.

Note* : Interface in the above para is used as a generic term that defines the operations that a client of an api can perform. And it can mean a class or an interface.

Now the client wants the text to be displayed in a formatted manner say in lower case. But it does not want to change the interface and the method call.
That can be achieved through inheritance and the dynamic/late binding concept.
Note that the only change in the client code is at Line 10. And that can also be moved out of code to the configuration ( generally xml ) using IOC (Inversion of control) pattern. So, effectively the Client code remains untouched and the behavior change is also achieved.


package format;
public class LowerCaseTextFormatter extends TextFormat {
 @Override
 public void print(String msg) {
           System.out.println(msg.toLowerCase());
 }
}

package format;
public class Client {
 public static void main(String[] args) {
    TextFormat tf = new LowerCaseTextFormatter(); // LINE 10
    tf.print("Testing the power of LATE BINDING");
 }
}
Output : testing the power of late binding


Can we achieve such a behavior change without writing a new concrete implementation that extends TextFormat class ?

Consider the below case. We are able to change the behavior of print() method on the fly by creating a anonymous inner class. Although it is a local class and cant be reused outside its scope.


package format;

public class Client {
 
 public static void main(String[] args) {
  /* Changing behaviour of print method 
   * using Anonymous Inner Class
   */
  new TextFormat(){  
   @Override
   public void print(String msg) {
    System.out.println(msg.toLowerCase());
   }
  }.print("Testing the power of LATE BINDING");
 }
}
Output : testing the power of late binding

The compiler version of anonymous inner class does extend the TextFormat class.


Monday, September 1, 2014

How does JVM evaluate serialVersionUID if not provided explictly ?

If the programmer does not provide the serialVersionUID explicitly, then the jvm defaults the id to the hash* for that class. The serialVersionUID is a 64-bit (long type) hash of the class name, interface class names, methods, and fields.


private static final long serialVersionUID = 3487495895819393L;

hash* - The hash mentioned here does not refer to the one calculated from hashCode() method. 

Java api provides the utilities to evaluate the serialVersionUID. It may be evaluated 
a) programatically through the api exposed by java
b) through the utility 
serialver provided in the bin folder.


a) Programatically evaluating the serialVersionUID :  Java api provides class ObjectStreamClass, that can be used as below to evaluate the serialVersionUID of a class.
Here we are evaluating the serialVersionUID of the Person class.

We can tweak the class structure by adding/removing new fields,  interfaces, methods, changing access-modifiers etc and we can verify that the serialVersionUID changes.

import java.io.ObjectStreamClass;

public class EvaluateSerialVersionUID {

 public static void main(String[] args) {
  ObjectStreamClass osc = ObjectStreamClass.lookup(Person.class);
  System.out.println(osc.getSerialVersionUID());
 }
}

b) serialver.exe utility in the JDK bin directory : 

We can also use the serialver.exe utility to evaluate the SerialVersionUID in a serializable class.



import java.io.Serializable;
public class Test implements Serializable{
 String name;
 
 public Test(){}
 
 public Test(String name){
  this.name= name;
 }
}

Compile the Test class.
Open command prompt, change the directory to the JAVA_HOME/bin directory.
Run the below command. ( D:\Java_Workspace is path containing Test.class file ).

serialver -classpath D:\Java_Workspace -show





Enter the fully qualified class name and click show.