由于这是当今的热门话题,我无法理解某些概念。如果我听起来很蠢,请原谅,但是当我尝试创建不可变对象时,我发现大多数帖子都包含以下几点
现在我不明白为什么我们需要以下几点
我在这里添加我的课程和测试用例:
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。
让我知道我做错了什么。
答案:将构造函数createInstance()
设为私有并提供(工厂方法)本身并不能帮助:这是您应该做的几件事,以允许用户在仍然可以控制实例的方式的同时实际使用该类及其实例。被创建。
答案:将类声明为final
意味着用户无法扩展它,因此它“阻止”用户使用这种“解决方法”。将属性声明为final
不允许类的用户对其进行更改。不能“意外地修改”它,但是可以使用反射来“恶意地修改”它。让我们看一个例子,假设您有:
final public class SomeClass {
final Integer i = 1;
}
从另一个类中,您可以执行以下操作:
class AnotherClass {
public static void main (String[] args) throws Exception {
SomeClass p = new SomeClass();
Field i =p.getClass().getDeclaredField("i");
i.setAccessible(true);
i.set(p, 5);
System.out.println("p.i = " + p.i); // prints 5
}
}
答:您可以使用构建器模式或任何有助于您控制类实例创建的模式。
进一步:
如果要确保您的类是不可变的,请确保任何类都getter
返回该类成员的深层副本。此技术称为“保护性/防御性复制”。您可以在此处了解更多信息
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句