的一些澄清.我无法想象,最后一个要点(6)应该如何与第一个一起工作
>(1)它们是final和immutable(尽管可能包含对可变对象的引用)
>(6)它们在相等时可自由替换,这意味着在任何计算或方法调用中根据equals()交换任意两个实例x和y应该不会产生行为的可见变化.
可选是这样一个类.
Optional a = Optional.of(new ArrayList<String>()); Optional b = Optional.of(new ArrayList<String>()); assertEquals(a, b); // passes as `equals` delegated to the lists b.get().add("a"); // now bite the last bullet assertTrue(a.get().isEmpty()); // passes assertTrue(b.get().isEmpty()); // throws
我读错了,还是需要更准确?
更新
伊兰的答案是有道理的(他们不再平等),但让我移动目标:
... assertEquals(a, b); // now, they are still equal assertEquals(m(a, b), m(a, a)); // this will throw assertEquals(a, b); // now, they are equal, too
让我们定义一个有趣的方法m,它会做一些变异并再次撤消它:
int m(Optional<ArrayList<String>> x, Optional<ArrayList<String>> y) { x.get().add(""); int result = x.get().size() + y.get().size(); x.get().remove(x.get().size() - 1); return result; }
我知道,这是一种奇怪的方法.但我想,它有资格作为“任何计算或方法调用”,不是吗?
您可以从您所指的规范中获得您的操作的无效性:
A program may produce unpredictable results if it attempts to distinguish two references to equal values of a value-based class, whether directly via reference equality or indirectly via an appeal to synchronization, identity hashing, serialization, or any other identity-sensitive mechanism . Use of such identity-sensitive operations on instances of value-based classes may have unpredictable effects and should be avoided.
(强调我的)
修改对象是一种身份敏感操作,因为它只影响具有您用于修改的引用所代表的特定标识的对象.
当你调用x.get().add(“”);您正在执行一项操作,允许识别x和y是否代表同一个实例,换句话说,您正在执行身份敏感操作.
尽管如此,我希望如果未来的JVM真正尝试替换基于值的实例,它必须排除引用可变对象的实例,以确保兼容性.如果执行生成Optional的操作,然后解压缩Optional,例如……流findAny().get(),如果中间操作允许用另一个在中间点可选用的点上相等的元素替换该元素,那将是灾难性/不可接受的(如果该元素本身不是值类型) …
翻译自:https://stackoverflow.com/questions/47528317/value-based-classes-confusion