首先,您不应该直接使用public 字段,除非它们是常量 (static final) 字段并且确保它们的状态不会改变。应该使用Encapsulation 公开它们,以避免您的班级的客户修改状态。这是一个通过以防御方式实现 getter/setter 来编写自己的框架的示例,以便不改变 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);
}
}
除此之外,JavaBean specification 声明 Java 类中的字段不应为 public,并且应通过 getter 和 setter 方法访问它们。
7 属性
属性是 Java Bean 的离散的、命名的属性,可以影响其外观或行为。例如,一个 GUI 按钮可能有一个名为“Label”的属性,它表示按钮中显示的文本。
属性以多种方式显示:
- 属性可能会在脚本环境中公开,就好像它们是
对象。因此,在 Javascript 环境中,我可能会执行“b.Label = foo”来设置 a 的值
财产。
- 其他组件可以通过调用其 getter 以编程方式访问属性
和 setter 方法(请参阅下面的第 7.1 节)。
(...)
7.1 访问器方法
属性总是通过对其所属对象的方法调用来访问。对于可读属性,将有一个 getter 方法来读取属性值。对于可写属性,将有一个 setter 方法来允许更新属性值。
有些框架遵循这些规范,以允许通过反射注入/检索类字段的值。例如,Spring 和 JSF。
通过 XML 配置的 Spring 示例:
<bean id="fooBean" class="my.package.Foo">
<property name="stringList">
<list>
<value>Hello</value>
<value>World</value>
</list>
</property>
</bean>
以及相关的 Java 类:
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;
}
}
使用Expression Language进行字段绑定的JSF示例:
<!-- allows JSF to call getter through reflection -->
<h:dataTable value="#{foo.stringList}" var="value">
<h:column>
#{value}
</h:column>
</h:dataTable>
以及相关的 Java 类:
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;
}
}
使用哪个选项:防御性 getter/setter 还是普通 getter/setter?这取决于你在做什么。