The Artima Developer Community
Sponsored Link

Designing with Static Members
How to Put Static Fields and Methods to Work
by Bill Venners
First Published in JavaWorld, February 1999

<<  Page 2 of 3  >>

Advertisement

So what are class members good for?
In my opinion, the best mindset to cultivate when designing Java programs is to think objects, objects, objects. Focus on designing great objects, and think of classes primarily as blueprints for objects -- the structure in which you define the instance variables and instance methods that make up your well-designed objects. Besides that, you can think of classes as providing a few special services that objects can't provide, or can't provide as elegantly. Think of classes as:

Utility methods
Methods that don't manipulate or use the state of an object or class I call utility methods. Utility methods merely return some value (or values) calculated solely from data passed to the method as parameters. You should make such methods static and place them in the class most closely related to the service the method provides.

An example of a utility method is the String copyValueOf(char[] data) method of class String. This method produces its output, a return value of type String, solely from its input parameter, an array of chars. Because copyValueOf() neither uses nor affects the state of any object or class, it is a utility method. And, like all utility methods should be, copyValueOf() is a class method.

So one of the main ways to use class methods is as utility methods -- methods that return output calculated solely from input parameters. Other uses of class methods involve class variables.

Class variables for data hiding
One of the fundamental precepts in object-oriented programming is data hiding -- restricting access to data to minimize the dependencies between the parts of a program. If a particular piece of data has limited accessibility, that data can change without breaking those portions of the program that can't access the data.

If, for example, an object is needed only by instances of a particular class, a reference to it can be stored in a private class variable. This gives all instances of this class handy access to that object -- the instances just use it directly -- but no other code anywhere else in the program can get at it. In a similar fashion, you can use package access and protected class variables to reduce the visibility of objects that need to be shared by all members of a package and subclasses.

Public class variables are a different story. If a public class variable isn't final, it is a global variable: that nasty construct that is the antithesis of data hiding. There is never any excuse for a public class variable, unless it is final.

Final public class variables, whether primitive type or object reference, serve a useful purpose. Variables of primitive types or of type String are simply constants, which in general help to make programs more flexible (easier to change). Code that uses constants is easier to change because you can change the constant value in one place. Public final class variables of reference types allow you to give global access to objects that are needed globally. For example, System.in, System.out, and System.err are public final class variables that give global access to the standard input output and error streams.

Thus the main way to view class variables is as a mechanism to limit the accessibility of (meaning to hide) variables or objects. When you combine class methods with class variables, you can implement even more complicated access policies.

Using class methods with class variables
Aside from acting as utility methods, class methods can be used to control access to objects stored in class variables -- in particular, to control how the objects are created or managed. Two examples of this kind of class method are the setSecurityManager() and getSecurityManager() methods of class System. The security manager for an application is an object that, like the standard input, output, and error streams, is needed in many different places. Unlike the standard I/O stream objects, however, a reference to the security manager is not stored in a public final class variable. The security manager object is stored in a private class variable, and the set and get methods implement a special access policy for the object.

Java's security model places a special restriction on the security manager. Prior to Java 2 (aka JDK 1.2), an application began its life with no security manager (getSecurityManager() returned null). The first call to setSecurityManager() established the security manager, which thereafter was not allowed to change. Any subsequent calls to setSecurityManager() would yield a security exception. In Java 2, the application always starts out with a security manager, but similar to the previous versions, the setSecurityManager() method will allow you to change the security manager one time, at the most.

The security manager provides a good example of how class methods can be used in conjunction with private class variables to implement a special access policy for objects referenced by the class variables. Aside from utility methods, think of class methods as the means to establish special access policies for object references and data stored in class variables.

<<  Page 2 of 3  >>


Sponsored Links



Google
  Web Artima.com   
Copyright © 1996-2014 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use - Advertise with Us