在给我的问题具体化之前,让我提供一些背景知识:我的主要编程语言是C ++和Java。使用C ++时,我发现应用const正确性非常重要,即声明如下函数:
A::DoSomething( const B& arg ); // guarantees that arg is not modified
A::DoSomething() const; // guarantees that the object of type A is not modified
A::DoSomething( const B& arg ) const; // both of the above
事实上,我经常希望const
是默认值,并且必须以某种方式标记修改后的对象。
使用const
的主要原因是:
众所周知,Java没有const
关键字(您不能使用final
执行上述操作)并且此事已在此处讨论过,请参阅此处:{{3 }}
通常建议的Java替代方法是使您的类不可变。虽然这不是const
的完全替代,因为它适用于每个类而不是每个使用类的上下文,但在大多数情况下它对我来说都可以正常工作。
但是不可变类有一个大问题:不可变性不明显。 要知道一个类是否真的是不可变的,据我所知,你基本上必须检查完整的源代码。任何方法都可以有一个后门,通过它可以修改对象。
那么有更简单的方法来检查不变性吗?或者是否有任何最佳实践以某种方式将一个类标记为不可变?
注意:我知道这两种语言都提供了绕过常量或不变性的“邪恶技巧”:C ++有const_cast
而Java有反射。但是对于我的问题,我们假设没有使用它们。
答案 0 :(得分:14)
Java没有一流的不变性支持,所以你没有可靠的方法来检测类是否是不可变的。
Java Concurrency In Practice建议(参见附录A作为参考)使用@Immutable
中的类级javax.annotation.concurrent
注释,这是表示不变性的最方便,最常用和最标准的方法;自定义javadoc也很好。请注意,它只是声明,而不是实际约束。
课程设计也是一个很好的指标:
this
引用不会从构造函数中泄漏)可以在Oracle tutorials中找到不可变类设计属性的完整列表。
因此,要检查类是否是不可变的,首先要查看类级注释和javadoc,然后再查看实现本身。
为了提供额外的健全性检查(如果您认为注释为不可变类可能是错误的可变),FindBugs(静态分析工具)有Mutability Detector插件,它有效地执行上面列出的相同操作:检查class具有@Immutable
注释并验证(通过反射)所有不变性规则都得到满足(还有一些其他的东西,比如来自Guava等的不可变集合支持)。可变性检测器也可以用作没有FindBugs的库,它允许你编写类似的测试:
@Test
public void testImmutable() {
assertImmutable(MyClass.class);
}
答案 1 :(得分:-1)
强制实现不变性的最简单方法是通过Lombok库中的 @Value 注释。