看起来你误读了文本。
现在我同意最后一个观点,但在我看来,在列表中使用JavaBeans比嵌套的Map更有意义
文本从未提到嵌套映射作为替代方案。
...应该调用构造函数,而不是set*方法,并且对象应该是不可变的
这是一种好的实践,特别是在处理线程时非常有用。
但我们也不能说使用setter是很糟糕的,特别是当单个线程正在使用对象时。那是完全安全的。
我不想每次给出新信息时都创建一个新对象,我想将其添加到现有对象中。
只要你控制对象,这样做就没有问题,其他人可能更容易只创建一个新对象。
使用JavaBeans作为数据存储是一种不好的做法,应该避免,还是完全安全的?
不,它并不是一个不好的实践。它也不是完全安全的。这取决于情况。
可变对象的问题(不是JavaBeans本身的问题)是使用不同的线程来访问它们。
您必须同步访问以避免一个线程在其他线程访问它时修改该对象。
不可变对象没有这个问题,因为它们不能改变,因此您不必同步任何内容。
要确保对象是不可变的,必须将其属性声明为final。
class MyBean {
private final int i;
}
如果你想给MyBean.i
赋一个合理的值,你需要在构造函数中指定:
public MyBean( int i ) {
this.i = i;
}
由于变量是final的,您无法使用setter,只能提供getter。
这是完全线程安全的,并且最好的是,您不必同步访问,因为如果两个线程尝试获取 i 的值,它们都将始终看到在实例化时分配的值,您不必同步任何内容。
这既不是坏的实践也不是好的实践。我们大多数人必须使用单个线程,即使是在诸如servlet之类的多线程环境中。
如果将来要处理多线程应用程序,则可以考虑使用不可变的JavaBean ;)
顺便说一下,创建不可变的bean并仍然提供一堆setter的替代方法是使用 Builders
:
Employee e = new EmployeeBuilder()
.setName("Oscar")
.setLastName("Reyes")
.setAge(0x1F)
.setEmployeeId("123forme")
.build();
这与常规 bean 中使用的 setXyz 看起来非常相似,但它具有使用不可变数据的好处。
如果您需要更改一个值,可以使用类方法:
Employee e = Employee.withName( e, "Mr. Oscar")
这个函数会接收一个已有的对象,并将其所有的值复制一份,然后创建一个新的对象……
public static EmployeeWithName( Employee e , String newName ){
return new Employee( newName, e.lastName, e.age, e.employeeId );
}
但是,在单线程模型中,使用Getter/Setter是完全安全的。
顺便说一句,我强烈建议你购买这本书:Effective Java。您将不会后悔,而且您将获得更好地判断类似引用文章的信息。