One part of reviewing and refactoring code is finding and removing code smells. An example, which I encounter quite often is the outmoded manner of coding Enumeration-like behaviour using int-constants. Or worse: String constants. The java.util.Calendar-class serves as a great example for this former best practice, before the Enumeration-Type was introduced with Java release 1.5.
Imagine you want to get a java.util.Date object pointing to the 1st of January 2009, midnight. This is one way of doing it:
cal.set(Calendar.YEAR, 2009);
cal.set(Calendar.MONTH, Calendar.JANUARY);
cal.set(Calendar.DAY_OF_MONTH, 1);
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
Date myDate = cal.getTime();
This has been a clean way of implementing and “imitating” enum-like behaviour in pre 1.5 times and of course in projects that require a lower java version.
Since we’re passing ints to the set method, it is possible to do something like this, without having the compiler complain about it (seen it done before):
And due to the fact that the number of the months in the Calendar class starts with 0 this would create a Date object pointing to the 1st of February. Ouch. An even more evil way of misusing the Calendar class could be this:
I’ve never seen this done before, but looking at it, I must say it really hurts.
Since the release of Java 1.5 there is a much better way of programming that kind of behaviour using the Enumeration type. This is how a simple Month enumeration could look like:
JANUARY, FEBURARY, MARCH, APRIL, MAY, JUNE, JULY, AUGUST, SEPTEMBER,OCTOBER, NOVEMBER, DECEMBER;
}
But we can add a little more brain to the implementation:
We’ll add member variables for the name, index and number of days, a constructor with arguments for each of these values and we’ll provide getters for retrieving them. Additionally we’ll add a method for calculating the correct number of days depending on a given year, considering leap years.
public enum MonthEnum {
// define the items of the enumeration
JANUARY("January", 1, 31),
FEBRUARY("February", 2, 28),
MARCH("March", 3, 31),
[…]
NOVEMBER("November", 11, 30),
DECEMBER("December", 12, 31);
// member variables
private String name;
private int index;
private int numberOfDays;
// constructor
private MonthEnum(String name, int index, int numberOfDays) {
this.name = name;
this.index = index;
this.numberOfDays = numberOfDays;
}
public String getName() {
return name;
}
public int getNumber() {
return index;
}
public int getNumberOfDays() {
return numberOfDays;
}
public int calcNumberOfDays(int year) {
// check for leap years:
// year modulo 4 is 0
// if year modulo 100 equals 0
// and year modulo 400 is not 0, it’s not a leap year
if (this.equals(MonthEnum.FEBRUARY) && year%4 == 0
&& !(year%100 == 0 && year%400 != 0)) {
return this.numberOfDays +1;
}
return this.numberOfDays;
}
}
And here’s an example of how the enumeration can be used:
private static void printMonthDetails(MonthEnum monthEnum) {
System.out.println(monthEnum.getName());
System.out.println(monthEnum.getNumber());
System.out.println(monthEnum.getNumberOfDays() );
}
public static void main(String[] args) {
System.out.println(MonthEnum.FEBRUARY.calcNumberOfDays(2008));
System.out.println(MonthEnum.FEBRUARY.calcNumberOfDays(2009));
System.out.println(MonthEnum.FEBRUARY.calcNumberOfDays(1700));
System.out.println(MonthEnum.FEBRUARY.calcNumberOfDays(1600));
printMonthDetails(MonthEnum.DECEMBER);
}
}
I warmly recommend the use of this great feature of the Java language. It definitely adds more type safety, ease of use and security to your application. But unfortunately it seems to me, that it still hasn’t reached the popularity that it really deserves, yet.





February 27th, 2009 at 2:12 pm
[...] seems to me, that it still hasn’t reached the popularity that it really deserves, yet. Source: Core-Dump [...]
February 27th, 2009 at 2:33 pm
Hey buddy gud note …I just paste ur content and referred ur link…that’s ok wid u…
http://dhootankur.wordpress.com
February 27th, 2009 at 3:17 pm
Prior to Java 5, the better approach was to simply use ordinary classes as enums as advised in the original Effective Java. For most purposes, rolling your own is trivial. Also, there are several freely available implementations on the web.
The sad part is that so many Java APIs still use only ints and strings.
March 5th, 2009 at 12:14 pm
Hi Curt,
thank you for the comment - I totally agree with your points…
And sorry for publishing the comment so late. I’ll have to look at the configuration of this wordpress installation again.
Cheers!
Alex