Sunday, August 19, 2007

Calendar class - Better Way to Manipulate Dates.

Java’s Calendar class offers a set of methods for converting and manipulating temporal information. In addition to retrieving the current date and time, the Calendar class also provides an API for date arithmetic. Calendar’s built-in date/time arithmetic API is extremely useful.

This tutorial examines the Calendar class API and presents examples of how you can use Calendar objects to add and subtract time spans to and from dates and times, as well as how to evaluate whether one date precedes or follows another.

Adding time spans

Let’s say you want to add a time span to a starting date and print the result. Consider the following example, which initializes a Calendar to 16 July 2007 and then adds two months and three days to it to obtain a new value:

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.GregorianCalendar;     
public class CalenderDemo{
 public static void main(String[] args) {
  CalenderDemo tdt = new CalenderDemo();
  tdt.calculateDate();
 }   
 private void calculateDate(){
  //Creating a calendar instance with initial date
16 July 2007
  Calendar calendar = new GregorianCalendar
(2007,Calendar.JULY,16);
  System.out.println("Initial date is: ");
  printFormattedDate(calendar);     
  // Adding 2 Months and 3 day here
  calendar.add(Calendar.MONTH,2);
  calendar.add(Calendar.DAY_OF_MONTH,3);
  // printing modified date value
  System.out.println("New date is: ");
  printFormattedDate(calendar);
 }
 /** Method to print Formatted Date
SimpleDateFormat */
 private void printFormattedDate(Calendar calendar){
  // define output format and print
  SimpleDateFormat sdf = new SimpleDateFormat
("d MMM yyyy hh:mm aaa");
  String date = sdf.format(calendar.getTime());
  System.out.println(date);
 }
}

The main workhorse of this class is the doMath() method, which begins by initializing a new GregorianCalendar object to 16 July 2007. Next, the object’s add() method is invoked; this method accepts two arguments: the name of the field to add the value to and the amount of time to be added. In this example, the add() method is called twice — first to add two months to the starting date and then to add a further one day to the result. Once the addition is performed, the printCalendar() utility method is used to print the final result.

The use of the SimpleDateFormat object to turn the output of getTime() into a human-readable string. This class is a part of java.text. package.

When you run the class, this is the output you’ll see:

Initial date is:
 16 July 2007 12:00 AM
New date is:
 19 September 2007 12:00 AM

This kind of addition also works with time values. To illustrate, consider the next example, which adds 14 hours and 55 minutes to a starting time value:

/*
* Creating an Instance of Calendar with Year,
* Month, data, Hours and Minutes **/
Calendar calendar =new GregorianCalendar
(2007,Calendar.JANUARY,1, 1,0);
System.out.println(“Initial Date is :”);
printFormattedDate(calendar);   
//Defined in Above example
 // Add 14h 55min
calendar.add(Calendar.HOUR,14);
calendar.add(Calendar.MINUTE,55);
 
//Print after Adding the hours and minutes        
System.out.println(“Modified Date is :”);
printFormattedDate(calendar);  //Defined in Above example.
       
This is almost identical to the previous class except
that the calls to add() involve the calendar’s hour
and minute fields. Here’s the output:
Initial Date is:

1 Jan 2007 01:00 AM

Modified Date is
1 Jan 2007 03:55 PM

Subtracting time spans

Subtraction is fairly easy as well — you simply use negative values as the second argument to add(). Here’s an example:

// Creating a Date Instance with Year, Month, Day, Hours and Minutes
Calendar calendar = new GregorianCalendar
(2007,Calendar.JANUARY,2, 3,30);
System.out.println("Starting date is: ");
printFormattedDate(calendar);
//Defined in First Example.
// Subtracting 1 Year 1 Day 4 Hours and 5 Minutes
System.out.println("Subtracting 1 Year 1
Day 4 Hours and 5 Minutes");
calendar.add(Calendar.YEAR,-1);
calendar.add(Calendar.DAY_OF_MONTH,-1);
calendar.add(Calendar.HOUR,-4);
calendar.add(Calendar.MINUTE,-5);
// print result
System.out.println("Ending date is ");
printFormattedDate(calendar);

Here’s the output:

Starting date is:
2 Jan 2007 03:30 AM
Subtracting 1y 1d 4h 5min...
Ending date is
31 Dec 2005 11:25 PM

In this example, the Calendar object automatically takes care of adjusting the year and the day when the subtraction results in the date “overflowing” from 1 Jan 2006 to 31 Dec 2005.

Adding vs. rolling

As the previous example illustrates, the add() method automatically takes care of rolling over days, months, and years when a particular calendar field “overflows” as a result of addition or subtraction. However, this behavior is often not what you want. In those situations, the Calendar object also has a roll() method, which avoids incrementing or decrementing larger calendar fields when such overflow occurs. To see how this works, look at the following example:

Calendar calendar = new GregorianCalendar
(2006, Calendar.DECEMBER,1);
System.out.println("Starting date for add()  is: ");
printFormattedDate(calendar);     
System.out.println("After add()ing 1 month, ending date is: ");
calendar.add(Calendar.MONTH, 1);
printFormattedDate(calendar);
// initialize calendar
Calendar calendar2 = new GregorianCalendar

(2006, Calendar.DECEMBER,1);
System.out.println("Starting date for roll() is: ");
printFormattedDate(calendar2);     
System.out.println("After roll()ing 1 month,  ending date is: ");
Calendar2.roll(Calendar.MONTH, 1);
printFormattedDate(calendar2);

Here’s the output:

Starting date for add() is:
 1 Dec 2006 12:00 AM
 After add()ing 1 month, ending date is:
 1 Jan 2007 12:00 AM     
 
 Starting date for roll() is:
 1 Dec 2006 12:00 AM
 After roll()ing 1 month, ending date is:
 1 Jan 2006 12:00 AM

In the first case, when one month is added to the starting date of 1 Dec 2006, the add() method realizes that a year change will occur as a result of the addition, and the year is rolled over to 2007. When using roll(), this behavior is disabled, and only the month field is incremented by 1, with the year change ignored. In many situations, roll() is very useful.

Checking date precedence

The Calendar object also includes the compareTo() method, which lets you compare two dates to find out which one comes earlier. The compareTo() method accepts another Calendar object as an input argument and returns a value less than zero if the following conditions are true:

  • The date and time of the input Calendar object is later than that of the calling Calendar object.
  • A value greater than zero if the reverse is true.
  • A value of 0 if the two Calendar objects represent the same date.

Here’s an example that compares 1 Jan 2007 12:00 AM and 1 Jan 2007 12:01 AM with compareTo():

// initialize two calendars
Calendar calendar1 = new GregorianCalendar
(2007,Calendar.JANUARY,1,0,0,0);
Calendar calendar2 = new GregorianCalendar
(2007,Calendar.JANUARY,1,0,1,0);
// define date format
String date1 = null;
String date2 = null;
SimpleDateFormat sdf = new SimpleDateFormat
("d MMM yyyy hh:mm aaa");
// compare dates
if((calendar1.compareTo(calendar2)) <>
    date1 = sdf.format(calendar1.getTime());
    date2 = sdf.format(calendar2.getTime());
}else{
    date1 = sdf.format(calendar2.getTime());
    date2 = sdf.format(calendar1.getTime());
}
System.out.println(date1 + " occurs before " + date2);
System.out.println(date2 + " occurs after  " + date1);

Here’s the output:

1 Jan 2007 12:00 AM occurs before 1 Jan 2007 12:01 AM
1 Jan 2007 12:01 AM occurs after  1 Jan 2007 12:00 AM


Since Most of the Date/Time classes are deprecated,
Calendar class is very handy to work with.
Alongwith this java.text.DateFormat and
java.text.SimpleDateFormat are very useful to
convert the date to different Locales and
different format.

Thursday, August 09, 2007

Reflection APIs - A way to inspect classes at runtime

Java Reflection is a technology that looks inside a Java object at runtime and sees basically everything about the object that you would know at compile time.

Java Reflection is a technology that looks inside a Java object at runtime and sees what variables it contains, what methods it supports, what interfaces it implements, what classes it extends—basically everything about the object that you would know at compile time.

The Reflection API is located in the java.lang.reflect package and is included in any J2SE installation. Primarily it is intended for very generic programs such as database browsers or visual code editors, but it can be used in any other applications. Reflection is for

Basic techniques

There are two basic techniques involved in Reflection: discovery and use by name. Here are descriptions of both:

  • Discovery involves taking an object or class and discovering the members, superclasses, implemented interfaces, and then possibly using the discovered elements.
  • Use by name involves starting with the symbolic name of an element and using the named element.

Discovery typically starts with an object and then calls the Object.getClass() method to get the object's Class. The Class object has a number of methods for discovering the contents of the class. Here are some of those methods:

  • getMethods(): returns an array of Method objects representing all of the public methods of the class or interface.
  • getConstructors(): returns an array of Constructor objects representing all of the public constructors of the class.
  • getFields(): returns an array of Field objects representing all of the public fields of the class or interface.
  • getClasses(): returns an array of Class objects representing all of the public classes and interfaces that are members (e.g., inner classes) of the class or interface.
  • getSuperclass(): returns the Class object representing the superclass of the class or interface (null is returned for interfaces).
  • getInterfaces(): returns an array of Class objects representing all of the interfaces that are implemented by the class or interface.

You can obtain the Class object either through discovery, by using the class literal (e.g., MyClass.class), or by using the name of the class (e.g., Class.forName("mypackage.MyClass")). With a Class object, member objects Method, Constructor, or Field can be obtained using the symbolic name of the member. These are the most important techniques:

  • getMethod("methodName", Class...): returns the Method object representing the public method with the name "methodName" of the class or interface that accepts the parameters specified by the Class... parameters.
  • getConstructor(Class...): returns the Constructor object representing the public constructor of the class that accepts the parameters specified by the Class... parameters.
  • getField("fieldName"): returns the Field object representing the public field with the name "fieldName" of the class or interface.

You can use Method, Constructor, and Field objects to dynamically access the represented member of the class. For example:

  • Field.get(Object): returns an Object containing the value of the field from the instance of the object passed to get(). (If the Field object represents a static field, the Object parameter is ignored and may be null.)
  • Method.invoke(Object, Object...): returns an Object containing the result of invoking the method for the instance of the first Object parameter passed to invoke(). The remaining Object... parameters are passed to the method. (If the Method object represents a static method, the first Object parameter is ignored and may be null.)
  • Constructor.newInstance(Object...): returns the new Object instance from invoking the constructor. The Object... parameters are passed to the constructor. (Note that the parameterless constructor for a class can also be invoked by calling newInstance().)

Creating arrays and proxy classes

The java.lang.reflect package provides an Array class that contains static methods for creating and manipulating array objects. Since J2SE 1.3, the java.lang.reflect package also provides a Proxy class that supports dynamic creation of proxy classes, which implement specified interfaces.

The implementation of a Proxy class is provided by a supplied object that implements the InvocationHandler interface. The InvocationHandler's method invoke (Object, Method, Object[]) is called for each method invoked on the proxy object—the first parameter is the proxy object, the second parameter is the Method object representing the method from the interface implemented by the proxy, and the third parameter is the array of parameters passed to the interface method. The invoke() method returns an Object result that contains the result returned to the code that called the proxy interface method.

Eaxmple of Reflection is :

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Member;
import static java.lang.System.out;
 
enum ClassMember { CONSTRUCTOR, FIELD, METHOD, CLASS, ALL }
 
public class ClassSpy {
    public static void main(String... args) {
               try {
                   Class c = Class.forName(args[0]);
                   out.format("Class:%n  %s%n%n", c.getCanonicalName());
 
                   Package p = c.getPackage();
                   out.format("Package:%n  %s%n%n",
                                      (p != null ? p.getName() : "-- No Package --"));
 
                   for (int i = 1; i <>
                               switch (ClassMember.valueOf(args[i])) {
                               case CONSTRUCTOR:
                                   printMembers(c.getConstructors(), "Constructor");
                                   break;
                               case FIELD:
                                   printMembers(c.getFields(), "Fields");
                                   break;
                               case METHOD:
                                   printMembers(c.getMethods(), "Methods");
                                   break;
                               case CLASS:
                                   printClasses(c);
                                   break;
                               case ALL:
                                   printMembers(c.getConstructors(), "Constuctors");
                                   printMembers(c.getFields(), "Fields");
                                   printMembers(c.getMethods(), "Methods");
                                   printClasses(c);
                                   break;
                               default:
                                   assert false;
                               }
                   }
 
        // production code should handle these exceptions more gracefully
               } catch (ClassNotFoundException x) {
                   x.printStackTrace();
               }
    }
 
    private static void printMembers(Member[] mbrs, String s) {
               out.format("%s:%n", s);
               for (Member mbr : mbrs) {
                   if (mbr instanceof Field)
                               out.format("  %s%n", ((Field)mbr).toGenericString());
                   else if (mbr instanceof Constructor)
                               out.format("  %s%n", ((Constructor)mbr).toGenericString());
                   else if (mbr instanceof Method)
                               out.format("  %s%n", ((Method)mbr).toGenericString());
               }
               if (mbrs.length == 0)
                   out.format("  -- No %s --%n", s);
               out.format("%n");
    }
 
    private static void printClasses(Class c) {
               out.format("Classes:%n");
               Class[] clss = c.getClasses();
               for (Class cls : clss)
                   out.format("  %s%n", cls.getCanonicalName());
               if (clss.length == 0)
                   out.format("  -- No member interfaces, classes, or enums --%n");
               out.format("%n");
    }
}
 

Further References:

http://java.sun.com/docs/books/tutorial/reflect/index.html