First at all, you should not use public
fields directly unless they are constant (static final
) fields and making sure their state won't change. They should be exposed using Encapsulation to avoid a client of your class modifying the state. Here's an example when writing your own framework by implementing getter/setter in defensive way, in order to not alter the current state of your List
:
public class Foo {
private List<String> stringList;
public Foo() {
//always initialized, never null
this.stringList = new ArrayList<>();
}
public List<String> getStringList() {
//defensive implementation
//do not let clients to alter the state of the list
//for example, avoiding clear the list through getStringList().clear()
return new ArrayList(stringList);
}
public void setStringList(List<String> stringList) {
//defensive implementation
//do not let clients to pass a null parameter
this.stringList = (stringList == null) ? new ArrayList<>() : new ArrayList<>(stringList);
}
}
Apart of this, the JavaBean specification states that fields in a Java class should not be public
and their access should be through getter and setter methods.
7 Properties
Properties are discrete, named attributes of a Java Bean that can affect its appearance or its behavior. For example, a GUI button might have a property named “Label” that represents the text displayed in the button.
Properties show up in a number of ways:
- Properties may be exposed in scripting environments as though they were fields of
objects. So in a Javascript environment I might do “b.Label = foo” to set the value of a
property.
- Properties can be accessed programmatically by other components calling their getter
and setter methods (see Section 7.1 below).
(...)
7.1 Accessor methods
Properties are always accessed via method calls on their owning object. For readable properties there will be a getter method to read the property value. For writable properties there will be a setter method to allow the property value to be updated.
There are frameworks that follow these specifications in order to allow injection/retrieval of values for class fields through reflection. For example, Spring and JSF.
Spring example through XML configuration:
<bean id="fooBean" class="my.package.Foo">
<property name="stringList">
<list>
<value>Hello</value>
<value>World</value>
</list>
</property>
</bean>
And the associated Java class:
package my.package;
public class Foo {
private List<String> stringList;
public String getStringList() {
return this.stringList;
}
//allows Spring to set the value of stringList through reflection
public void setStringList(List<String> stringList) {
this.stringList = stringList;
}
}
JSF example for field binding using Expression Language:
<!-- allows JSF to call getter through reflection -->
<h:dataTable value="#{foo.stringList}" var="value">
<h:column>
#{value}
</h:column>
</h:dataTable>
And the associated Java class:
package my.package;
@ManagedBean
@ViewScoped
public class Foo {
private List<String> stringList;
@PostConstruct
public void init() {
stringList = new List<>();
stringList.add("Hello");
stringList.add("world");
}
public String getStringList() {
return this.stringList;
}
public void setStringList(List<String> stringList) {
this.stringList = stringList;
}
}
Which option to use: Defensive getter/setter or common getter/setter? It will depend on what you're doing.