gpt4 book ai didi

java - 如何在java中使对象不可变

转载 作者:太空狗 更新时间:2023-10-29 23:04:15 26 4
gpt4 key购买 nike

由于这是最近的热门话题,我无法理解某些概念。如果我听起来很愚蠢,请原谅我,但是当我尝试创建不可变对象(immutable对象)时,我在大多数帖子中发现了以下几点

  • 最后一节课 - 有道理
  • 不允许属性的修改器( setter )- 有道理
  • 将属性设为私有(private) - 有意义

现在我不明白为什么我们需要以下几点

  • 将构造函数设为私有(private)并提供与构造函数或工厂方法具有相同属性的 createInstance 方法?它有什么帮助?
  • 使属性成为最终属性 - 帖子的帖子未能解释这一点以及我阅读的一些地方以避免意外修改。当没有修改器并且类是 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。

如果我做错了什么,请告诉我。

最佳答案

  • 将构造函数设为私有(private)并提供与构造函数或工厂方法具有相同属性的 createInstance 方法?它有什么帮助?

答案:将构造函数设为私有(private)并提供 createInstance()(工厂方法)本身并没有帮助:这是您应该做的几件事之一允许用户实际使用该类及其实例,同时您仍然可以控制实例的创建方式。

  • 使属性成为最终属性 - 该帖子未能解释这一点以及我在某处阅读以避免意外修改的地方。当没有修改器并且类是 final 时,你怎么会意外修改?将属性设置为 final 有何帮助?

回答:将一个类声明为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/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com