java - 基于值的类混淆

标签 java java-8 immutability value-class

我正在寻求对 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不再是 equalsb ,所以你没有理由期待 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/

相关文章:

java - Java中的数组 "remember"它们的类型如何?

java - 从 ListView Javafx 打印

java - 在 Tomcat 中运行不同 Java 版本的 Web 应用程序

java - 将 Lambda 表达式简化为一行

java - 通过 Java-8 中的公共(public)字段减少对象集合

ruby - 为什么在 Ruby 方法中使用感叹号?

javac 未显示在 .bat 文件中

immutability - 必须返回多个对象是糟糕设计的标志吗?

java - 使用不同的方法设置对象的多个字段

java - 非运行时分配方案——ArrayList