小编典典
对于Java而言,这并不意味着什么。
类不变式只是一个属性,它始终为一个类的所有实例保存,无论其他代码做什么。
例如,
class X {
final Y y = new Y();
}
X具有不变的类,即存在一个y属性,并且永远不存在,null并且它具有type值Y。
class Counter {
private int x;
public int count() { return x++; }
}
无法保持两个重要的不变式
这count永远不会返回,因为可能下溢负值。
要求count严格单调增加。
修改后的类保留了这两个不变式。
class Counter {
private int x;
public synchronized int count() {
if (x == Integer.MAX_VALUE) { throw new IllegalStateException(); }
return x++;
}
}
但无法保留count始终正常成功调用的不变式(缺少TCB-violations
†),因为count如果死锁线程拥有计数器的监视器,它可能会引发异常或阻塞。
每种带有类的语言都易于维护某些类不变式,而不能维护其他不变式。Java也不例外:
Java类始终具有或不具有属性和方法,因此接口不变式易于维护。
Java类可以保护其private字段,因此依赖私有数据的不变量易于维护。
Java类可以是最终的,因此可以维护不依赖通过编写恶意子类来违反不变量的代码的不变量。
Java允许null值以多种方式潜行,因此很难维护“具有真实值”的不变式。
Java具有线程,这意味着不同步的类很难维护依赖于同时发生的线程中顺序操作的不变式。
Java有一些异常,可以轻松维护诸如“返回带有属性p的结果或不返回结果”之类的不变量,而维护诸如“始终返回结果”之类的不变性则更加困难。
†- 外部性 或 违反
通常,我们只相信基本硬件能够像在其上构建的高级语言的属性那样进行宣传,而我们不变式的论点并未考虑以下可能性:
当程序运行时,使用调试钩子来更改局部变量的程序员以代码无法运行的方式运行。
您的对等方不使用反射setAccessible来修改private查找表。
Loki改变物理结构会导致处理器错误地比较两个数字。
对于某些系统,我们的TCB可能仅包括系统的一部分,因此我们可能不会假定
管理员或特权守护程序不会终止我们的JVM进程,
但是我们可以假设
我们可以检查点到可靠的事务性文件系统。
系统级别越高,通常其TCB越大,但是从TCB中获得的不可靠信息越多,不变量保持的可能性就越大,从长远来看,系统越可靠。
2020-11-01