Getters and setters in Java

A simple java bean with public setters and getters is arguably the simplest, most familiar and most ingrained pattern in Java. This is one thing many Java students write very early and remember forever:


    private int foo;
    public int getFoo() {
        return foo;
    }
    public void setFoo(int foo) {
        this.foo = foo;
    }

When C# came along, there was a brief discussion in the Java community about the virtues of “properties” as opposed to plain private variables with getters/setters (known scientifically as accessors and mutators). But it did not lead anywhere and by now, the use of the getter/setter pattern has become automatic. Some GUI IDEs offer support for generation of getter/setter methods. But is it a good thing?

Originally, getter/setter pattern was created to promote good object-oriented design by encapsulating the internals of a class from its external interface. This permits changing or refactoring internal details of the class implementation without impacting class users.

But is there any reason we generate getters/setters for value objects? The pattern of private field with public getter/setter is so ingrained in the minds of the Java programmers, we never allow ourselves question it. And we keep on happily producing more classes with usual trivial getter/setter pairs, which add no value, bloat code and make assignments more difficult to understand. In many cases there is no encapsulation, as all consuming classes are meant to change and MUST change whenever value object definition changes. But we have the benefit of 2 useless methods generated per simple field and replace simple assignment with a convoluted nested set/get calls. Ask yourself, which is easier to read:
customerBean.ssn = customerVO.ssn;
or
customerBean.setSsn(customerVO.getSsn());

I think Java community would be well served by cutting down on the getters and setters.

JAXB
Still, in some cases creating getter-setter pair is necessary. One case where I grudgingly agree with using getters/setters is Java classes generated by JAXB compiler, xjc. In most cases, JAXB generated getters and setters are useless: they are of trivial variety (simply assign or return corresponding field value), but they are needed for API consistency. That’s because some of the getters/setters in JAXB are non-trivial. I can point to two such cases: optional attribute with default value and primitive lists.
Optional Attributes
This XSD


    <xsd:attribute name="Pos" type="xsd:int" use="optional" default="1"/>

will result in this non-trivial generated by xjc:


    @XmlAttribute(name = "Pos")
    protected Integer pos;

    /**
     * Gets the value of the pos property.
     * 
     * @return
     *     possible object is
     *     {@link Integer }
     *     
     */
    public int getPos() {
        if (pos == null) {
            return  1;
        } else {
            return pos;
        }
    }

Here, default value (1) is returned by the getter method when underlying Integer value is null (not assigned). You may suggest circumventing the need for the getter by initializing the Integer to the default value at the moment of declaration (protected int pos=1;, this also has side benefit of being able to replace wrapper class with primitive, because we do not use null any more). Then, if value is never assigned, the default will be returned. But this only works if the object is used once. Any reuse of the object breaks this pattern, since there is no means to unset the value of “pos” property in this code. The only way to enable the object to be used more then once without touching the getter is to put equivalent code inside the setter. Conclusion: optional attribute with default value requires non-trivial code in the getter or setter.
Lists of integers
This case is a bit more curious. Suppose you have this schema:


    <xsd:element name="RoutedGreetings">
	<xsd:complexType>
	<xsd:sequence>
		<xsd:element name="GreetingsNumbers" type="NumberListType"/>
	</xsd:sequence>
    </xsd:complexType>
    </xsd:element>

    <xsd:simpleType name="NumberListType">
      <xsd:list itemType="xsd:int"/>
    </xsd:simpleType> 

It shows a list of integers used in another element. Xjc will lazily initialize the list on first access in the getter:


    @XmlList
    @XmlElement(name = "GreetingsNumbers", type = Integer.class)
    protected List greetingsNumbers;

    public List getGreetingsNumbers() {
        if (greetingsNumbers == null) {
            greetingsNumbers = new ArrayList();
        }
        return this.greetingsNumbers;
    }

This is interesting, because I struggle to see why the list should be initialized lazily. If it was initialized eagerly, with the variable declaration ( protected List greetingsNumbers = new ArrayList();), one would be able to do away with getter. I’d be glad to hear thoughts from readers.
Note also that there is no setter: the getter returns a reference to live list, so to set the value you first perform a get and then manipulate the list you obtained.

About these ads

One Response to Getters and setters in Java

  1. Yes, there is a reason to use getters and setters even in simple value objects. The history of the java.awt.Point class is one notorious cautionary tale. The public fields in that class became a bottleneck in Java GUI performance because it prevented points from being reimplemented as flyweights. :-(

    You’re right that most of the time you don’t need to change the implementation of a basic value object, especially without changing the signature and updating all callers. And it’s certainly true that Java’s syntax for getters and setters could be cleaner. Eiffel does a much better job with this, for example. But robust, flexible code does need the freedom to update implementations, even if we don’t take advantage of that power most of the time.

Follow

Get every new post delivered to your Inbox.

Join 71 other followers

%d bloggers like this: