我搜索了这个主题,但除了 Wikipedia我没有找到任何其他有用的文档或文章。
谁能用简单的语言向我解释它的含义或向我推荐一些易于理解的好文档?
最佳答案
这并不意味着任何关于 Java 的特殊含义。
类不变量只是一个属性,它始终适用于类的所有实例,无论其他代码做什么。
例如,
class X {
final Y y = new Y();
}
X 具有类不变量,即存在 y
属性,并且它永远不会是 null
并且它的值类型为 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 违规†),因为 count
可能如果死锁线程拥有计数器的监视器,则抛出异常或阻塞。
每种带有类的语言都可以很容易地维护一些类不变量,而其他的则不然。 Java 也不异常(exception):
- Java 类始终具有或不具有属性和方法,因此接口(interface)不变量易于维护。
- Java 类可以保护其
private
字段,因此依赖私有(private)数据的不变量易于维护。 - Java 类可以是最终类,因此可以维护不存在通过制作恶意子类而违反不变量的代码的不变量。
- Java 允许
null
值以多种方式潜入,因此很难维护“具有真实值”的不变量。 - Java 有线程,这意味着不同步的类难以维护依赖于线程中一起发生的顺序操作的不变量。
- Java 有一些异常(exception),这使得维护诸如“返回具有属性 p 的结果或不返回结果”之类的不变量变得容易,但维护诸如“始终返回结果”之类的不变量变得更加困难。
† - 外部性 或 TCB违规是系统设计师乐观地认为不会发生的事件。
通常我们只相信基本硬件在谈论基于它们的高级语言的属性时会像宣传的那样工作,并且我们的不变量持有的论点没有考虑以下可能性:
- 当程序以代码无法运行的方式运行时,程序员使用调试 Hook 来更改局部变量。
- 您的同行不使用带有
setAccessible
的反射来修改private
查找表。 - Loki 改变物理特性导致您的处理器错误地比较两个数字。
对于某些系统,我们的 TCB 可能仅包括系统的一部分,因此我们可能不会假设
- 管理员或特权守护进程不会杀死我们的 JVM 进程,
...但我们可以假设:
- 我们可以检查点到可靠的事务文件系统。
系统级别越高,其 TCB 通常越大,但您可以从 TCB 中获得的不可靠的东西越多,您的不变量就越有可能保持,并且您的系统在很长一段时间内就越可靠运行。
关于java - Java中的类不变量是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8902331/