Identifying, implementing, and accessing fields
Fields, also known as attributes or member attributes, are the data aspects of objects. A field’s visibility defines the level of access to it by Java objects. This week’s discussion, modified from Chapters 7 and 8 of The Object Primer 2nd Edition, focuses on the types of field visibility, how to implement fields, and how to access them.
Table 1 describes the three types of field visibility, indicating the Unified Modeling Language (UML) symbols, the Java keywords, a description of what the visibility means, and my suggested proper usage for that visibility. As you can see, the rules and notations for field visibility are consistent with those for member function visibility, as discussed last week.
Table 1. Visibility of fields in Java programs
|Visibility||UML Symbol||Java keyword||Description||Suggested usage|
|Public||+||public||A public field can be accessed by any other method in any other object or class.||Don’t make fields public.|
|Protected||#||protected||A protected field can be accessed by any method in the class in which it is declared or by any method defined in subclasses of that class.||Don’t make fields protected.|
|Private||–||private||A private field can only be accessed by methods in the class in which it is declared, but not in the subclasses.||All fields should be private and accessed by getter and setter methods (accessors).|
In my experience, all fields should be declared private for purposes of information hiding and encapsulation. When fields are declared protected, there is the possibility that methods in subclasses will directly access them, effectively increasing the coupling within a class hierarchy. This increased coupling makes your classes more difficult to maintain and enhance; therefore, it should be avoided.
To show you how to implement fields with different visibilities, I present the declarations for the fields of the
Address class in Figure 1. It is possible to declare fields that are public or protected, as you can see in the source code example, but that is rarely a good idea.
Fields should never be accessed directly; instead, accessors should be used. Accessor methods come in two flavors: setters and getters (sometimes referred to as mutators and accessors, respectively). A setter modifies the value of a field, whereas a getter obtains its value. The only time that I would consider going against this rule is when the accessor methods are clearly impacting the performance of my application and I have no other alternative for improving the performance to an acceptable level — even then I would attempt to minimize the number of fields that I access directly. By the way, I’ve been working in Java technology since the autumn of 1995 and have yet to break this rule. At the same time, I’ve lost track of the number of developers I’ve met who complain about accessor method performance.
An essential concept that Java programmers must learn is that the only accessor methods that are allowed to work directly with a field are the accessors themselves. Yes, it is possible to directly access a private field within the methods of the class in which the field is defined, but you don’t want to do so because you would increase the coupling within your class. In fact, the use of accessors is a practice that is enforced in Enterprise JavaBean (EJB) 2.0 environments for all persistent fields. The effective use of accessor methods will be covered in future tips.