为什么这个 class 是可变的?

Why is this class mutable?

public class Test {
    private final String url;
    public Test(String url) {
        this.url = url;
    }
    public String getUrl() {
        return url;
    }
}

测试 class 有:

  1. 只有一个实例变量是私有的和最终的。
  2. 没有二传手。
  3. 初始化实例变量的唯一方法是通过构造函数。
  4. 并且一旦设置了 URL,即使在 getUrl 中也无法修改它,即使该方法被 Test.class 的任何子class 覆盖也是如此。

但是我正在阅读的一本书说上面的测试 class 是可变的,因为:

你能帮我理解为什么测试 class 是可变的吗?

Test 的任意实例不能保证是不可变的,尽管 Test 的直接实例是。但是考虑这个子类:

public class MutableTest extends Test {
        private int mutable;
        public MutableTest(String url) {
                super(url);
        }

        @Override
        public String getUrl() {
                return super.getUrl() + mutable++;
        }
}

那你可以这样写:

Test instance = new MutableTest("http://example.com/");
String firstGet = instance.getUrl();
String secondGet = instance.getUrl();
assertEquals(firstGet, secondGet); // Boom!

接收已知类型为 Test 的对象的对象将知道该对象是不可变的。但是,接收类型 Test 的非空引用的对象将没有语言定义的方式来确保由此标识的对象不可变。有些人似乎认为这是一个主要的担忧。但是,总的来说,我认为不应该。

如果 class 是有用的可继承的,通常很容易设计出完全不适合任何非设计目的的派生类型。一种语言甚至可以尝试阻止这种情况的唯一方法是大大限制派生类型可以做的有用事情的范围。然而,除了一些特殊类型的 classes(通常与安全相关的那些)之外,通常最好确保派生的 classes 可以做有用的事情,而不是担心它们做作和做事的可能性。没用的东西。