我正在寻求对 definition of Value-based Classes 的一些澄清.我无法想象,最后一个要点 (6) 应该如何与第一个一起工作
- (1) 它们是最终的和不可变的(虽然可能包含对可变对象的引用)
- (6) 它们在相等时可自由替换,这意味着在任何计算或方法调用中根据 equals() 交换任意两个相等的实例 x 和 y 不会产生明显的行为变化.
Optional
就是这样一个类。
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
我是不是读错了,还是需要更精确一些?
更新
Eran 的回答是有道理的(它们不再相等),但让我移动目标:
...
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;
}
我知道这是一种奇怪的方法。但我想,它符合“任何计算或方法调用”的条件,不是吗?
最佳答案
they are freely substitutable when equal, meaning that interchanging any two instances x and y that are equal according to equals() in any computation or method invocation should produce no visible change in behavior
一次b.get().add("a");
被执行,a
不再是 equals
至 b
,所以你没有理由期待 assertTrue(a.get().isEmpty());
和 assertTrue(b.get().isEmpty());
会产生相同的结果。
基于值的类是不可变的这一事实并不意味着您不能改变此类类实例中存储的值(如 though may contain references to mutable objects
中所述)。这只意味着一旦你创建一个 Optional
带有 Optional a = Optional.of(new ArrayList<String>())
的实例, 你不能改变 a
持有对不同 ArrayList
的引用.
关于java - 基于值的类混淆,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47528317/