在项目的规格说明和要求中提到,产品ID不应该可更改,它是Long类型。这是否意味着它必须是不变的?如果是,那么如何通过编程来检查对象的不变性?
List
字段可能是不可变的,也可能是可变的,这取决于它所引用的内容)。 - Joachim Sauer是的,您可以确定一个对象是否是不可变的。然而,这是非常复杂的业务,因此解决方案无法适用于 Stack Overflow 上的答案。
有两种方法可以确定一个类是否是不可变的:
现有的静态分析工具是 MutabilityDetector(https://github.com/MutabilityDetector)。
现有的运行时检查工具是 Bathyscaphe(https://github.com/mikenakis/Bathyscaphe)(我是作者)。
在我看来,静态分析在某些情况和特定场景下是有用的,但并不总是能够提供完整的解决方案。完整的解决方案需要运行时检查,正如我在我的博客中所解释的那样:https://blog.michael.gr/2022/05/bathyscaphe.html,这也是为什么我编写了Bathyscaphe。class Product {
private Long id;
Product() { id = 42; }
Long getId() { return id; }
void setId(Long newId) { id = newId; }
:
}
所有这些Long都是不可变的,但产品ID仍然会发生更改:因为setId
将一个不同的不可变Long值分配给id成员。
然而,如果您只删除那个setId
方法(并且在Product类中不编写任何类似的内容),则产品ID现在是不可更改的。
public class MutationOfImmutableException extends Exception {
/**
*
*/
private static final long serialVersionUID = 1L;
public MutationOfImmutableException(String string) {
super(string);
}
}
我们的类(我想不出一个好名字,但我想这传达了这个想法)有
public void setName(String name) throws MutationOfImmutableException {
throw new MutationOfImmutableException("Cannot mutate this immutable instance");
}
setName()
方法时,编译器都会警告我们要正确处理异常。p.setName("Anees"); // Cannot do this until handled!
Product
,则可以从setId()
抛出一个已检查异常,以避免一切混乱!setters
设置为私有,这样您甚至不会遇到这种情况。