Objects are a combination of behavior (implemented in Java in terms of methods) and attributes (implemented in Java in terms of fields). Attributes for an object stick around as long as the object sticks around. At any given point in time, an object has a certain state, which is the combined snapshot of all its instance variables. For this reason, instance variables are sometimes called state variables. Action methods in the object may operate on and change attributes of the object. In other words, action methods can alter the object state. Query methods return pieces of the object state.
Occasionally you will find the need for a method that can take parameters, operate on only those parameters, and return a value. The method has no need to operate on object state. This is known as a utility method. Utility methods in other languages are sometimes called functions. They are global: any client code can access them. Sometimes, having to create an object in order to use a utility method makes little sense. For example, the DateUtil method createDate you coded in Lesson 3 is a simple function that takes month, day, and year integer arguments and returns a Date object. The createDate method changes no other data. Removing the need to construct DateUtil objects will also simplify your code a bit. Finally, since createDate is the only method in DateUtil, there is no other need to construct instances of it. For these reasons, createDate is a good candidate for being a class method. In this exercise, you will refactor createDate to be a class method in this exercise. Start by changing the test to make a class method call: package sis.studentinfo; import java.util.*; import junit.framework.*; public class DateUtilTest extends TestCase { public void testCreateDate() { Date date = DateUtil.createDate(2000, 1, 1); Calendar calendar = new GregorianCalendar(); calendar.setTime(date); assertEquals(2000, calendar.get(Calendar.YEAR)); assertEquals(Calendar.JANUARY, calendar.get(Calendar.MONTH)); assertEquals(1, calendar.get(Calendar.DAY_OF_MONTH)); } } You no longer create an instance of DateUtil with the new operator. Instead, to call a class method, you specify the class on which the class method is defined (DateUtil), followed by the dot operator (.), followed by the method name and any arguments (createDate(2000, 1, 1)). Changes to the DateUtil class itself are similarly minor: package sis.studentinfo; import java.util.*; public class DateUtil { private DateUtil() {} public static Date createDate(int year, int month, int date) { GregorianCalendar calendar = new GregorianCalendar(); calendar.clear(); calendar.set(Calendar.YEAR, year); calendar.set(Calendar.MONTH, month - 1); calendar.set(Calendar.DAY_OF_MONTH, date); return calendar.getTime(); } } You declare a class method just like a "regular," or instance, method, except that you prefix its declaration with the keyword static. In addition to making the createDate method static, it's a good idea to make the constructor of DateUtil private. By declaring the constructor as private, only code in the DateUtil class can construct new DateUtil instances. No other code will be able to do so. While it wouldn't be harmful to allow creation of DateUtil objects, keeping clients from doing something nonsensical and useless is a good idea. Adding the private constructor will also make it simpler for you to pinpoint the nonstatic references to createDate. When you compile your code, methods that create a new DateUtil object will generate compilation errors. For example, the setUp method in CourseSessionTest will fail compilation: public void setUp() { startDate = new DateUtil().createDate(2003, 1, 6); session = new CourseSession("ENGL", "101", startDate); } Update it to call createDate statically: public void setUp() { startDate = DateUtil.createDate(2003, 1, 6); session = new CourseSession("ENGL", "101", startDate); } Fix the remainder of the failing compilation problems and rerun your tests. You now have a general-purpose utility that may find frequent use in your system.[1]
The class java.lang.Math in the J2SE 5.0 class library supplies many many mathematical functions. For example, Math.sin returns the sine of a double and Math.toRadians converts a double value from degrees to radians. The Math class also provides two standard mathematical constants, Math.PI and Math.E. Since each of the methods in java.lang.Math is a utility class method, it is known as a utility class. In UML (Figure 4.1), you indicate a utility class using the stereotype <<utility>>. Stereotypes in UML define semantics beyond the limitations of what UML supplies. A utility stereotype specifies that all class behaviors and attributes may be globally accessed. Figure 4.1. The Math Utility ClassNormally you underline class behaviors and class attributes in UML. Since the <<utility>> stereotype declares that all methods and attributes in a class are global, you need not underline them.
|