101

我用谷歌搜索了这个主题,但除了Wikipedia之外,我没有找到任何其他有用的文档或文章。

任何人都可以用简单的话向我解释它的含义或向我推荐一些易于理解的文档吗?

4

3 回答 3

104

对于 Java,这并不意味着什么。

类不变量只是一个属性,它始终适用于类的所有实例,无论其他代码做什么。

例如,

class X {
  final Y y = new Y();
}

X 具有类不变量,即有一个y属性,它从不存在null,它的值是 type Y

class Counter {
  private int x;

  public int count() { return x++; }
}

这无法保持两个重要的不变量:

  1. 由于可能的下溢,它count永远不会返回负值。
  2. 对的调用count严格单调递增。

修改后的类保留了这两个不变量。

class Counter {
  private int x;

  public synchronized int count() {
    if (x == Integer.MAX_VALUE) { throw new IllegalStateException(); }
    return x++;
  }
}

...但未能保留调用count总是正常成功的不变量(不存在 TCB 违规†</sup>),因为count可能会引发异常,或者如果死锁线程拥有计数器的监视器,它可能会阻塞。

每种带有类的语言都可以很容易地维护一些类不变量,而其他的则不然。Java也不例外:

  1. Java 类始终具有或不具有属性和方法,因此接口不变量易于维护。
  2. Java 类可以保护它们的private字段,因此依赖私有数据的不变量很容易维护。
  3. Java 类可以是最终的,因此可以维护不存在通过制作恶意子类来违反不变量的代码的不变量。
  4. Java 允许null值以多种方式潜入,因此很难维护“具有真正价值”的不变量。
  5. Java 有线程,这意味着不同步的类很难维护依赖于线程中一起发生的顺序操作的不变量。
  6. Java 有一些例外,这使得维护诸如“返回具有属性 p 的结果或不返回结果”之类的不变量变得容易,但难以维护诸如“始终返回结果”之类的不变量。

† -外部性TCB违规是系统设计人员乐观地认为不会发生的事件。

通常,我们只相信基本硬件在谈论基于它们的高级语言的属性时会像宣传的那样工作,并且我们的不变量持有的论点没有考虑以下可能性:

  • 当程序以代码无法运行的方式运行时,程序员使用调试挂钩来更改局部变量。
  • 您的同行不使用反射setAccessible来修改private查找表。
  • Loki 改变物理导致你的处理器错误地比较两个数字。

对于某些系统,我们的 TCB 可能仅包括系统的一部分,因此我们可能不会假设

  • 管理员或特权守护进程不会杀死我们的 JVM 进程,

...但我们可能会假设:

  • 我们可以检查点到可靠的事务文件系统。

系统级别越高,其 TCB 通常越大,但是您可以从 TCB 中获得的不可靠的东西越多,您的不变量就越有可能保持,并且从长远来看,您的系统将越可靠。

于 2012-01-17T22:07:30.037 回答
25

不变意味着无论发生什么变化或无论谁使用/转换它,都应该坚持其条件。也就是说,一个类的属性即使在使用公共方法进行转换之后,也总是满足或满足某个条件。因此,该类的客户或用户对类及其属性是有保证的。

例如,

  1. 函数参数的条件是,它应该始终 > 0(大于零)或不应该为空。
  2. Minimum_account_balance property of an account class states, it cannot go below 100. So all public functions should respect this condition and ensure class invariant.
  3. Rule based dependency between variables, that is, the value of one variable depends on another, so if one changes, using some fix-rule, the other must also change. This relationship between 2 variables must be preserved. If it does not, then invariant is violated.
于 2013-10-25T07:10:52.857 回答
12

它们是关于实例类必须为真的事实。例如,如果一个类有一个属性 X 并且不变量可以是 X 必须大于 0。据我所知,没有用于维护不变量的内置方法,您必须将属性设为私有并确保您的 getter 和 setter 强制执行不变属性。

有可用的注释可以使用反射和拦截器检查属性。 http://docs.oracle.com/javaee/7/api/javax/validation/constraints/package-summary.html

于 2012-01-17T22:05:45.563 回答