作者热门文章
- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
由于这是最近的热门话题,我无法理解某些概念。如果我听起来很愚蠢,请原谅我,但是当我尝试创建不可变对象(immutable对象)时,我在大多数帖子中发现了以下几点
现在我不明白为什么我们需要以下几点
我在这里添加我的类和测试用例:
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。
如果我做错了什么,请告诉我。
最佳答案
答案:将构造函数设为私有(private)并提供 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
返回一个 deep-copy 类(class)成员。这种技术称为“保护性/防御性复制”。您可以阅读更多相关信息 here
关于java - 如何在java中使对象不可变,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24545239/
我是一名优秀的程序员,十分优秀!