96

I googled the topic, but besides Wikipedia I didn't find any further useful documentation or articles.

Can anybody explain to me in simple words what it means or refer me to some nice and easy to understand documentation?

Lii
  • 9,906
  • 6
  • 53
  • 73
Saurabh Kumar
  • 14,849
  • 42
  • 118
  • 186
  • 2
    +1 for the question because the Wikipedia page has a really great example of something I didn't know you could do - it even has examples. Their explanation is better than I could do for you though; it's pretty straightforward. – iandisme Jan 17 '12 at 22:06
  • https://www.stanford.edu/~pgbovine/programming-with-rep-invariants.htm – Savino Sguera Jan 17 '12 at 22:06
  • If you're interested in invariants w.r.t. Java, maybe you'd be interested in [contracts for Java](http://google-opensource.blogspot.com/2011/02/contracts-for-java.html). – Mike Samuel Jan 18 '12 at 14:05
  • 1
    A more simple explanation - – ip_x Jan 31 '13 at 23:58

3 Answers3

97

It doesn't mean anything in particular in reference to Java.

A class invariant is simply a property that holds for all instances of a class, always, no matter what other code does.

For example,

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

X has the class invariant that there is a y property and it is never null and it has a value of type Y.

class Counter {
  private int x;

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

This fails to maintain two important invariants:

  1. That count never returns a negative value because of possible underflow.
  2. That calls to count are strictly monotonically increasing.

The modified class preserves those two invariants.

class Counter {
  private int x;

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

...but fails to preserve the invariant that calls to count always succeed normally (absent TCB-violations) because count might throw an exception or it might block if a deadlocked thread owns the counter's monitor.

Each language with classes make it easy to maintain some class invariants but not others. Java is no exception:

  1. Java classes consistently have or do not have properties and methods, so interface invariants are easy to maintain.
  2. Java classes can protect their private fields, so invariants that rely on private data are easy to maintain.
  3. Java classes can be final, so invariants that rely on there being no code that violates an invariant by crafting a malicious subclass can be maintained.
  4. Java allows null values to sneak in in many ways, so it is tough to maintain "has a real value" invariants.
  5. Java has threads which means that classes that do not synchronize have trouble maintaining invariants that rely on sequential operations in a thread happening together.
  6. Java has exceptions which makes it easy to maintain invariants like "returns a result with property p or returns no result" but harder to maintain invariants like "always returns a result".

† - An externality or TCB violation is an event which a systems designer optimistically assumes will not happen.

Typically we just trust that the basic hardware works as advertised when talking about properties of high-level languages built on them, and our arguments that invariants hold don't take into account the possibility of:

  • A programmer using debug hooks to alter local variables as a program runs in ways that code cannot.
  • Your peers don't use reflection with setAccessible to modify private lookup tables.
  • Loki altering physics causing your processor to incorrectly compare two numbers.

For some systems our TCB might include only parts of the system, so we might not assume that

  • An administrator or privileged daemon won't kill our JVM process,

...but we might assume that:

  • We can checkpoint to a reliable transactional file-system.

The higher-level a system, the larger its TCB typically is, but the more unreliable things you can get out of your TCB, the more likely your invariants are to hold, and the more reliable your system will be in the long run.

Lii
  • 9,906
  • 6
  • 53
  • 73
Mike Samuel
  • 109,453
  • 27
  • 204
  • 234
  • 2
    Is "that `count` never returns the same value twice" really considered a class invariant? – ruakh Jan 17 '12 at 22:22
  • 1
    @ruakh, that's a good question. I'm not quite sure. Things like hashCode stability (for each instance i, i.hashCode() does not change) are often called class invariants which requires reasoning about values returned previously, so it seems reasonable to say that "for each instance i, i.count() not in (previous results of i.count())" is a class invariant. – Mike Samuel Jan 17 '12 at 22:28
  • @ruakh Isn't that a pure definition thing? If I postulate such an invariant, why not? It certainly can be an interesting and important guarantee (say for generating unique IDs). Personally I also think something like "if only single threaded code accesses this class, the following properties will hold" is useful, but I'm not sure if it's possible to extend the definition in such a way that it only has to hold while certain conditions are true. (And considering reflection it's basically impossible to guarantee anything interesting otherwise!) – Voo Jan 17 '12 at 23:16
  • 1
    @ruakh - you could model it as a class invariant or a method invariant. Either way, modelling it requires a conceptual history of previous calls to the method on a specific object. Actually, you could even model this as a post-condition on the method; i.e. that the result value is one that hasn't been returned previously. – Stephen C Jan 17 '12 at 23:20
  • @Voo: Re: "Isn't that a pure definition thing?": Certainly, but since the question here is, "What is a 'class invariant'?", I think the definition is 100% relevant. It seems preferable, to the extent possible, to use clear-cut examples, or else to explicitly call out cases of non-clear-cut-itude. (I'm not actively disagreeing with the example, by the way; I was just surprised by it, and was asking in order to make sure.) – ruakh Jan 17 '12 at 23:37
  • @ruakh, StephenC, I think everyone would agree that a priority queue that maintains the heap invariant across all possible combinations of method calls is maintaining a class invariant. If the term "class invariant" is appropriate when multiple methods are involved, why should an invariant that is preserved by code in exactly one method not be considered a special case of that? Why should a "method invariant" not be defined as "a class invariant that can be proven by reasoning only about a single method." – Mike Samuel Jan 17 '12 at 23:48
  • @MikeSamuel: To clarify, I was not surprised by "class invariant" as opposed to "method invariant", I was merely surprised by "class invariant" in reference to a requirement that something vary. I'm used to class invariants (such as the heap invariant) that can be expressed in terms of an instance's state at any given time, rather than invariants that require reference to all of the instance's previous states. (You mentioned hash-code stability as a counterexample to that, but it still seems qualitatively different somehow. I don't know.) – ruakh Jan 17 '12 at 23:55
  • @ruakh, would it be less surprising if I said "count() is strictly monotonically increasing". That only requires reference to one previous state. Unstrict monotonicity (as viewed by any given thread) is often an invariant desired of timers. – Mike Samuel Jan 18 '12 at 02:29
  • @MikeSamuel: Yes, I like that version a lot better, somehow. But please don't ask me to justify it. :-) – ruakh Jan 18 '12 at 02:43
  • "A class invariant is simply a property that holds for all instances of a class, always, no matter what other code does." - not true, Wikipedia is right, it's per-instance. If it's for all instances, I believe you would call it a constant. – orbfish Oct 02 '13 at 16:32
  • @orbfish, You seem to be referring to Wikipedia but I have no idea which part you're quoting that disagrees with me. Why wouldn't you call a property that always holds for a particular instance an *instance invariant*? – Mike Samuel Oct 02 '13 at 17:09
23

Invariant means something that should stick to its conditions no matter whatever changes or whoever uses/transforms it. That is to say, a property of a class always fulfills or satisfies some condition even after going through transformations by using public methods. So, the client or user of this class is ensured about the class and its property.

For example,

  1. Condition on a function argument is that, it should always be > 0 (greater than zero) or should not be null.
  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.
Yogesh Umesh Vaity
  • 16,749
  • 10
  • 82
  • 69
aab10
  • 231
  • 2
  • 4
12

They are facts that must be true about an instance class. For example if a class has a property X and invariant can be X must be greater then 0. To my knowledge there is no built-in method for maintaining invariants you must make properties private and make sure your getters and setters enforce invariance property.

There are annotations available which can check properties using reflection and interceptors. http://docs.oracle.com/javaee/7/api/javax/validation/constraints/package-summary.html

Geert
  • 2,767
  • 1
  • 17
  • 16
Usman Ismail
  • 16,170
  • 13
  • 72
  • 158