java中的类不变吗?
我GOOGLE了这个话题,但除了维基百科,我没有find任何进一步有用的文件或文章。
任何人都可以用简单的语言向我解释这是什么意思,或者向我介绍一些好的和易于理解的文档?
这并不意味着参考java的任何东西。
一个类不variables只是一个对所有类的实例都适用的属性,不pipe其他代码如何。
例如,
class X { final Y y = new Y(); }
X具有不变的类,它有一个y
属性,它永远不为null
,它的types为Y
class Counter { private int x; public int count() { return x++; } }
未能保持两个重要的不variables
- 这个
count
从来不会因为可能的下溢而返回一个负值。 - 那要求
count
是严格单调增加。
修改后的类保留这两个不variables。
class Counter { private int x; public synchronized int count() { if (x == Integer.MAX_VALUE) { throw new IllegalStateException(); } return x++; } }
但是不能保持调用总是正常成功(不存在TCB违规† )的调用的不变性,因为count
可能会抛出exception,或者如果死锁线程拥有计数器的监视器,它可能会阻塞。
每个带有类的语言都可以轻松地维护一些类不variables,而不是其他类。 Java也不例外:
- Java类一贯有或没有属性和方法,所以接口不variables很容易维护。
- Java类可以保护他们的
private
领域,所以依靠私人数据的不variables很容易维护。 - Java类可以是最终的,所以可以维持依赖于不存在通过构造恶意子类来违反不variables的代码的不variables。
- Java允许
null
值以多种方式潜入,因此很难保持“有实际价值”的不variables。 - Java具有线程,这意味着不同步的类在维护依赖线程中的顺序操作的不variables时会遇到麻烦。
- Java有一些例外,这就很容易维护不variables,比如“返回一个带有属性p的结果或者不返回任何结果”,但是难以维护像“总是返回一个结果”这样的不variables。
† – 外部性或TCB违规是系统devise师乐观承担的事件不会发生的事件。
通常我们只是相信基本的硬件在讨论构build在它们上面的高级语言的属性的时候就可以发挥作用,而我们不variables的论据并没有考虑到以下可能性:
- 程序员使用debugging钩子来改变局部variables,程序以代码不能运行的方式运行。
- 您的同事不使用带有
setAccessible
reflection来修改private
查找表。 - Loki改变物理导致你的处理器错误地比较两个数字。
对于一些系统,我们的TCB可能只包括系统的一部分,所以我们可能不会这样认为
- pipe理员或特权守护进程不会终止我们的JVM进程,
但我们可以假设
- 我们可以检查点到一个可靠的交易文件系统。
更高级别的系统,TCB通常越大,但是从TCB中获得的信息越不可靠,您的不variables越有可能持续下去,从长远来看系统的可靠性越高。
对于一个实例类,它们必须是真实的。 例如,如果一个类有一个属性X和不variables可以是X必须大于0.据我所知,没有内置的方法来维护不变式,你必须使属性私有,并确保你的getter和setter强制执行不变属性。
有注释可用,可以使用reflection和拦截器来检查属性。 http://docs.oracle.com/javaee/7/api/javax/validation/constraints/package-summary.html
不变意味着不pipe是什么样的变化,也不论使用/改变它,都应该坚持自己的条件。 也就是说,一个阶级的财产即使经过公共方法的转化,也总是满足或满足某种条件。 因此,这个类的客户或用户是确保类和它的属性。
例如,
- 条件函数的参数是,它应该总是> 0(大于零)或不应该为空。
- 一个账户类的minimum_account_balance属性声明,它不能低于100.所以所有的公共函数都应该尊重这个条件,并保证类的不变性。
- 基于规则的variables之间的依赖关系,也就是说,一个variables的值依赖于另一个variables,所以如果一个变化,使用一些修正规则,其他也必须改变。 这两个variables之间的关系必须保留。 如果没有,则不变式被违反。