Sorry

One of the defining characteristics of the brave new world of Java is the increasing prevalence of the builder pattern in the Java space. Groovy, which appears to be the most popular alternative language (to Java) on the JVM, is well-known for its heavy use of the Builder in both the core libraries and in Groovy-supported libraries and frameworks. Josh Bloch brought the pattern to the forefront of Java developer community mindset with coverage of the pattern in Item #2 of the second edition of his highly influential Effective Java. There have been several builders added to the JDK including the addition of Locale.Builder in J2SE 1.7. In this post, I briefly introduce Calendar.Builder coming to JDK 8.

Today, a Java developer typically populates an instance of the Calendar class by either calling one of the "set" methods that accepts a lengthy list of content for the instance or by calling individual "set" methods on the instance one after another. These two typical approaches for populating a Calendar instance are demonstrated in the next two code listings.

The two "traditional" approaches shown above show different ways to populate the Calendar instance. One extreme is to set each individual field separately while the other is to set all the significant fields with a single "set" method. There are advantages to each approach. The single "set" method has fewer states of an "unfinished" object than the multiple-set approach, but the multiple-set approach is more readable because the name of the value being set is clear based on the first parameter to each "set" method. The single-set approach is a little unwieldy because it takes six integers that can be easily mixed up in order passed because there is no obvious way to differentiate which integer is which other than the implicit order.

Calendar.Builder leverages on the advertised benefits of the Builder as described by Bloch: removes the existence of "inconsistent states partway through [an object's] construction." This is demonstrated in the next code listing.

In the above code listing, the Calendar instance is created AND populated in one statement, removing the need to risk an object being in an inconsistent state across multiple statements. This example retains the readability of the traditional individual "set" methods approach [set(int, int)] with the added safety of having the object populated fully immediately at instantiation.

There are fewer characters and lines to type with this approach, but it partially reintroduces the disadvantage of being more likely to have an integer parameter inadvertently switched as each of the two methods takes three integers (or an overloaded version of setTimeOfDay() will take a fourth integer representing milliseconds).

For developers wanting the ultimate flexibility in specifying Calendar parameters during its instantiation, Calendar.Builder provides the method setFields(int ...) that takes an arbitrary length of pairs of integers with the first integer of the pair representing the field to be set and the second integer of the pair representing the value for that field. This method is used in the next code listing.

This setFields(int ...) method brings greater risk of mangling the order of integers used for instantiation of the new instance of Calendar, but using the statically imported Calendar constants does improve readability and reduces the likelihood of mixing the integers incorrectly. If an odd number of integers is provided (meaning that there is an incomplete pair), an IllegalArgumentException is thrown.

Although Calendar.Builder provides some convenience in instantiating and populating an instance of Calendar, anyone fortunate enough to adopt JDK 8 will have access to the new date/time API and so the question might be asked, "Why use Calendar.Builder?" Perhaps the best answer is that there are millions of lines of existing code, libraries, and frameworks out there using and expecting Calendar instances, so it will probably be a long time before the need for Calendar is completely gone (if ever). Fortunately, Calandar.Builder makes it easy to covert an instance of Instant (part of the new Java data/time API) into a Calendar via CalendarBulder.setInstant(long). This is demonstrated in the next code listing.

Note that an overloaded version of the setInstant method accepts a Date for instantiating a Calendar. In both cases, whether instantiated with setInstant(long) or setInstant(Date), no other "set" method on Calender.Builder should be called to avoid an IllegalStateException.

Like many Java developers, I'm looking forward to an improved Java data/time API that is built into the standard Java Development Kit. However, I also realize that, especially in large code bases and when using libraries and frameworks expecting Calendar or Date, that I won't be free of Calendar and Date for some time. The introduction of Calendar.Builder in JDK 8 eases that burden a bit.

Dustin Marx is a principal software engineer and architect at Raytheon Company. His previous published work for JavaWorld includes Java and Flex articles and "More JSP best practices" (July 2003) and "JSP Best Practices" (November 2001).