Saturday, June 21, 2008

Compiling and Executing Java program

There are three basic steps in development of a simple java program which are Coding, Compiling, and Executing the java program. Coding is to write different set of classes and interfaces using any text editor like notepad etc. There are three cases which a java program can have. Those are:

Case A: Classes in default package (no package) and does not use classes which are bundled in jar.
Case B: Classes which are grouped in different packages but does not use classes which are bundled in jar.
Case C: Classes which are group in different packages and also uses classes bundled in jar.

Now i discuss compilation and execution of java program in each case one by one.

Lets discuss Case A. It is most simplest case which does not have any dependency on classes of others which are bundled in jar. Morever, classes are not grouped in different packages. Classes which are not grouped in packages, are said to be contained in default package. Suppose you have created a folder named as "TestProject" and has placed all java files there, then you can do following in windows to compile and exeuctge java program:
Just go to directory "TestProject" through command prompt and write following command:
C:\TestProject>javac *
above command will compile all java files. Now In order to run the java program, write following command:
C:\TestProject>java MainClass
where MainClass is any class which contains "public static void main(String[] args)" method.

Now we discuss Case B in which classes are grouped under packages. Packages provide better management of code, easy maintenance, and good access control on classes. Morever, packages provide safety from class name collissions. This case has further two possibilities. One is that you have logical grouped java classes in packages but placed them together like in case A i.e. all classes in folder TestProject. Now you will use following command to compile the code:
C:\TestProject>javac * -d .
"d" switch is used to provide destination for compiled classes. When destination is ".", it means root directory (TestProject in this case) will be default directory. javac command will first create folder heirarchy similar to packages and will place compiled class files in respective folder e.g. if a class is in package "org.engineers.project", then javac will first create folder named as "org" at root directory, then will create "engineers" folder under "org" and "project" folder under "engineers" folder. and will place class in "project" folder. In order to execute java program, you have to write following command at root directory:
C:\TestProject>java fully_qualified_class_name
fully_qualified_class_name means name of class with package e.g. if a class "Main" is contained under package org.engineers.project, then fully_qualified_class_name will be "org.engineers.project.Main"

Now we talk about second possibility in Case B which is that you have placed java source files in same folder hierarchy, as of packages i.e. if a class "Main.java" is in package "org.engineers.project", you have placed Main.java in folder org/engineers/project folder. You can use same command to compile and execute java program as in first possibility but it will mix your compiled code with source code so in order to keep them separate create a directory named as "src" under root directory (TestProject in this case) and then place all folder hierarchy containing source files there. Now create another folder named as "classes" at root level and use following command to compile the code:
C:\TestProject>javac * -d classes
"classes" folder be treated as root folder for class files.
In order to run java program, you have to change java command slightly. New command will be:
C:\TestProject>java -cp classes org.engineers.project.Main
Difference with this command and with previous command is of addition switch named as "cp". it represents classpath and tells java command where to find compiled classes. Since compiled classes are in "classes" folder, so i added that folder in classpath.

Now its time to discuss Case C, which is more realistic case. In this case, java source files uses classes which are placed in "jar" file. Jar file is just a zip file but with extensino java archive ("jar") . Now you will have to include all jar files in classpath using same switch which we used in preceding case to run the program. but this time we will have to use switch in both javac and java command.
C:\TestProject> javac -cp test.jar * -d classes
where test.jar is jar file which contains other classes which my classes use.
To execute the java program use following command:
C:\TestProject> java -cp test.jar;classes org.enigneers.project.Main
Note that i have added both "test.jar" and "classes folder in classpath.

Saturday, June 14, 2008

Cloning of Java objects

Parent class of all objects in java is "Object" which contains several important methos. One of them is "clone" which is used to make a copy of object. There are certain things which you should keep in mind while using clone method of Object.
- implement "Cloneable" interface to each class which you want to clone. If a class does not implement "Cloneable" interface, clone method will throw "CloneableNotSupportedException". This interface does not contain any methods. It is just a marker interface. Suppose you have a Class "Book" of which you want to make a clone, then structure of that class will be:

public class Book implements Cloneable
{
//attributes
//methods
@Override protected Object clone() throws CloneableNotSupportedException
{
//Clone logic
}
}

- Obtain cloned object through super.clone
- if your class only contains primitive attributes or wrappers of primitive attributes or immutable object like String, then you don't need to do anything special inside clone method because clone method automatically makes a copy of primitive data types and immutable objects. Suppose above "Book" class contains following two attributes with accessor methdos for attributes:

private String name;
private Float price;
public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public Float getPrice() {
return price;
}

public void setPrice(Float price) {
this.price = price;
}

Now to clone Book class you just need to write following implementation in overriding of clone method:

protected Object clone() CloneNotSupportedException
{
return super.clone();
}

- by default clone method makes shallow copy and does not make a Deep copy of object. Deep copy means if your object contains references of other objects or collections, it will not make a copy of those referenced objects and will use same references as was in origianl objects. Suppose above mentioned "Book" class contains an attribute of class "Publisher". Structure of Publisher class is given below:


public class Publisher{
private String pubName;

public String getPubName() {
return pubName;
}

public void setPubName(String pubName) {
this.pubName = pubName;
}
}

Now try out the following code:

Publisher pub = new Publisher();
pub.setPubName("Java Publisher");
orig.setPub(pub);
Logger.getLogger(CloneTest.class.getName()).log(Level.INFO,orig.getPub().getPubName());
Book clone2 = (Book) orig.clone();
Logger.getLogger(CloneTest.class.getName()).log(Level.INFO,clone2.getPub().getPubName());
orig.getPub().setPubName("java Publisher Changed");
Logger.getLogger(CloneTest.class.getName()).log(Level.INFO,clone2.getPub().getPubName());

Output of above code will be:
15-Jun-2008 1:39:47 AM javasolutionsblog.clonetest.CloneTest main
INFO: Java Publisher
15-Jun-2008 1:39:47 AM javasolutionsblog.clonetest.CloneTest main
INFO: Java Publisher
15-Jun-2008 1:39:47 AM javasolutionsblog.clonetest.CloneTest main
INFO: Java Publisher Changed


Although expected output of third log was "Java Publisher" but since clone didn't make copy of refernce object publisher, it used same object in clone as in origignal object, when i make a change in the publisher name in original object, it also reflected in cloned object.

- In order to do deep copy of Book class, we will aso have to implement "Cloneable" interface in "Publisher" class + override clone method in Publisher class too. If Publisher class contains references of other objects, then you will have to implement Cloneable interface + override clone method in each sub class too.
In our case, structure of Publisher class will be:

public class Publisher implements Cloneable{
private String pubName;

public String getPubName() {
return pubName;
}

public void setPubName(String pubName) {
this.pubName = pubName;
}

@Override
protected Object clone() throws CloneNotSupportedException
{
return super.clone();
}

}

Now change the definition of clone method of Book class as follows:

protected Object clone() throws CloneNotSupportedException {
Book clonedBook = (Book) super.clone();
if (this.getPub() != null) {
clonedBook.setPub((Publisher) this.getPub().clone());
}

return clonedBook;
}

Thursday, June 12, 2008

Implementing Equals and HashCode

In my last blog i described how we can compare two java objects of same class by overriding equals method. In this blog i will explain best practices regarding implementing of equals method.
Whenever, we go for overriding of equals method, one question comes to our mind is, on which basis we will have to say that two objects are same. First answer comes to mind is that we should compare objects on the basis of primary key which is also used to distinguish the records in the database. Primary keys are good candidate to compare objects if we assign primary keys ourself not by database. When primary key is assigned by database like auto number, objects don't have primary key until they are persisted in the database so before persistent of objects, how we should compare the objects. Good practice is always compare objects on the basis of business key which uniquely describes objects. Suppose we have a class of Person with attributes (id, name, ssn,address) . In this class we have two unique attributes one is id and second one is ssn. id is used to distinguish the objects in the database and is assigned when objects are persisted, then only choice is SSN which we can use to compare different person because each person has his own SSN (Social Security Number). So best practice is always compare objects on business keys rather than on database keys.
Second best practice is whenever you go for overriding of equals method. also override "int hashCode()" method. This method returns hash of objects. Implementing hasCode facilitates us when we use objects as keys in HashTable. If we don't override hashCode method, each object created with new operator will always has different hash values irrespective of fact whether they are same or not. Suppose I have a class of Customer with attributes (id, name, ssn, address) and i create two objects with new operation having the same dataset. Although logically they are same but physically they are two different objects that's y they have differnt hashCode. So best practice is that if two objects are equals, then those two objects should always have same hashCode. Overriding of hashCode will also facilitate us when we save objects in sets. Sets store only one instance of an object at a time, so if we have two customer objects with same attributes, then only one instance of customer must be saved in sets. It is only possible by overriding of hashcode method.
Now question is how to generate hashCode for an object. Answer is same as for equals method. Always generate hashCode from business keys. In above example of Customer objects, we should generate hashCode of Customer from SSN. java has provided methods which generate hashCode for all primitive data types and for String. hashCode for primitive data types are generated by using wrappers of primitive data types e.g. for int we can generate hashCode by following code:

Integer i = new Integer(5);
int code = i.hashCode();

Similary we can get hashCode of other primitive datatypes by using respective wrapper classes.

So in this blog we have come to Two Best Practices regarding comparison of objects:
- One is always compare objects in equal method on the basis of business keys.
- Second is whenever override equals method, also override hashCode method and generate hash for objects on the basis of same business key as used in equals method.