随着这个话题如今变得热门,我不理解某些概念。如果听起来很傻,请原谅我,但当我尝试创建不可变对象时,我发现大多数文章都遵循以下几点:
- 使类为final - 有道理
- 不允许属性的mutators(setters)- 有道理
- 将属性设为private - 有道理
现在我不明白为什么我们需要以下几点:
- 使构造函数为私有并提供与构造函数相同属性的createInstance方法或工厂方法?这有什么帮助?
- 将属性设为final - 文章中的某些作者未能解释这一点,有些地方我读到是为了避免意外修改。当没有mutators且类是final时,你如何意外地进行修改?使一个属性为final有什么帮助吗?
- 除了工厂模式,我可以使用生成器模式吗?
我在此添加我的类和测试案例:
public final class ImmutableUser {
private final UUID id;
private final String firstName;
private final String lastName;
public ImmutableUser(UUID id, String firstName, String lastName) {
super();
this.id = id;
this.firstName = firstName;
this.lastName = lastName;
}
/**
* @return the id
*/
public UUID getId() {
return id;
}
/**
* @return the firstName
*/
public String getFirstName() {
return firstName;
}
/**
* @return the lastName
*/
public String getLastName() {
return lastName;
}
}
测试用例
public class ImmutableUserTest {
@Test(expected = IllegalAccessException.class)
public void reflectionFailure() throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
ImmutableUser user = new ImmutableUser(UUID.randomUUID(), "john", "liu");
Field i =user.getClass().getDeclaredField("firstName");
i.setAccessible(true);
i.set(user, "cassandra");
System.out.println("user " + user.getFirstName()); // prints cassandra
}
}
这个测试用例失败并打印出cassandra。
如果我做错了什么,请让我知道。
new <className>
将分配(为)对象的新实例保留内存。有时这并非必要,甚至是不可取的。以包装类Boolean
为例。它有一个公共构造函数...但只有两个可能的值,它们可以轻松地被缓存并从静态的valueOf(...)
方法返回。Integer
封装类缓存范围[-128
,127
](取决于JVM)...这允许您减少使用的对象数量。 - Clockwork-Muse