Class Methods


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.

Design your methods to either change object state or return information, not both.


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]

[1] The utility is not the best-performing one. It is not necessary to create a GregorianCalendar object with each call to createDate. For sporadic use, this is probably just fine. For heavy usesay, creating 10,000 dates upon reading an input fileyou'll want to consider caching the calendar object using a class variable (see the next section).

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 Class


Normally 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.

Static Initialization Blocks

Constructors execute when you create instances of a class. You use constructors for more complex instance initialization.

Occasionally you may need more complex initialization to occur at a class level. You can use a static initialization block to accomplish this goal. Code within a static initialization block executes when the Java VM first loads a class.

 import java.util.Date; public class St {    static {       long now =          System.currentTimeMillis();       then = new Date(now + 86400000);    }    public static Date then; } 

To define a static initialization block, you precede a block of code ({. . . }) with the keyword static. Place it within a class definition but external to any method or constructor. Virtually any code can appear within a static initialization block, but the block should not throw any exceptions (see Lesson 8).




Agile Java. Crafting Code with Test-Driven Development
Agile Javaв„ў: Crafting Code with Test-Driven Development
ISBN: 0131482394
EAN: 2147483647
Year: 2003
Pages: 391
Authors: Jeff Langr

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net