在this 6岁的问题中,最高答案说不可能验证不变性。另一方面,在底部有两个最近的答案,表明可以使用:
检测类是否是不可变的。
我的问题是:这些工具在现实生活中是否有用?还有其他(更好的)解决方案吗?去年这几年有什么改变吗?
答案 0 :(得分:1)
虽然我确信有很多工具可以直接测试一个类是不可变的,但真正的问题是测试允许具有接口或抽象类声明的字段的不可变类。基本上只允许密封的不可变类作为子字段,因为继承通常会破坏不变性。
很难使用Java Collections API制作复合不可变对象(即不使用Map
,List
或Set
等。
另一个问题是,因为某个字段final
并未真正使其成为" final"。许多序列化工具(如Hibernate)将很乐意构建不可变对象并通过反射设置最终字段。
我看到的唯一真正的方法是通过运行时分析来检测真正的不变性,但是在您的代码实际遇到可变性发生的特定用例之前可能需要很长时间,我想这种仪器相当昂贵
另一种有趣的不可变对象的推论是,它们在构造时不应该改变外面的东西。那就是构造一个不可变对象应该是副作用免费的。这是工具将很难的地方。您可以使用构造函数轻松创建一个不可变对象,该构造函数可以执行各种外部恶意操作,例如启动线程或设置系统属性。
答案 1 :(得分:0)
关于某个工具在现实生活中是否有用,这取决于你为什么需要不变性(因为引用的帖子要求,你是在运行时验证,还是通过检查,或者防止恶意代码,或者只是确保你自己的代码是不可变的?)。如果你手动检查类,那么类是不可变的最简单的保证是所有字段写入仅在构造函数中发生,或者所有字段都是最终的(或两者都是)。
但这仍然有限,因为"最终的对象x"确保您的参考不会改变,但不会改变参考对象的变化。正如Adam所说,如果这是一个列表,那么底层列表可能会发生变化,这可能会导致您的(否则是不可变的)类中出现线程问题。如果您使用列表中的值来确定您的哈希代码(您使用x.hashCode()作为生成自己的哈希代码的一部分),那么您的哈希代码将更改违反其他规则(因此列表的不可变视图不是&# 39;甚至足够了。
如果您的不可变类不会受到保留对象更改的影响,那么它可能适合您的目的。
在运行时检查必须限制时间/深度/范围,因此不能完美。这些工具(或任何类似的运行时方法)有一些用处,但它实际上取决于您需要确定不变性的原因。如果您可以将不可变性作为API要求的一部分进行规范,则检测违反该规则的行为(例如,对象的hashCode更改),并在更改时抛出异常,然后您不需要自己检测它。或者相信你的来电者。如果您正在尝试编写不可变类,那些工具根本不会提供帮助。如果你真的在寻找线程安全,那么不变性本身就是一个不够的答案。
这个问题不是一个令人满意的答案(这是一个很好的答案),但我认为在大多数情况下,如果你更仔细地研究问题,它最终会成为一个错误的问题。