0

Is there any in-built contract checking in Java e.g. for the contract between a hashcode and the equals function?

For this question, let's stick with the hashcode/equals contract as an example, but I'm interested in contract checking in general. I have read in multiple places that equals and hashcode must satisfy a "contract" in Java:

  • Equals must follow the three rules of an equivalence relation and also must be consistent on repeated calls
  • Equal objects implies equal hashcodes

I understand the conditions, and they make sense to me. However, I'm wondering, is this just a contract that's written down on paper- essentially a strong guideline for developers to not write buggy code- or is it something that will be caught by Java as either a compile time or run time exception?

Colm Bhandal
  • 3,343
  • 2
  • 18
  • 29
  • 1
    It will not be caught by Java as either a compile time or run time exception. You are responsible for (writing the code that) adhering to the contract. – nbokmans Oct 13 '17 at 09:16
  • If equals the same does not imply hashcode the same, then you can get some weird behavior. E.g. the same object could be mapped to different buckets in a hashmap. – Tim Biegeleisen Oct 13 '17 at 09:17
  • Thanks guys- that's what I thought. So it's basically a strong guideline for Java not to write code that will be really terrible and buggy... BUT we could still theoretically write a program that violates the contract and it might compile and run fine, for years, without any of the bugs becoming apparent. – Colm Bhandal Oct 13 '17 at 09:19
  • @ColmBhandal Yes – khelwood Oct 13 '17 at 09:20

2 Answers2

1

It will not be enforced at compile time.

Some classes may enforce the behaviour at runtime - for example you could write a method that checks that two objects that are equal have the same hashcode or send an exception.

Also note that there are situations where you may want to deviate from the recommended contract on purpose.

assylias
  • 321,522
  • 82
  • 660
  • 783
  • Thanks. I would be really interested to see an example where deviation from this contract would actually be desirable? – Colm Bhandal Oct 13 '17 at 09:27
  • For example `Comparable` "strongly recommends" that `compareTo` be consistent with `equals` (i.e. `(a.compareTo(b) == 0) == (a.equals(b)`). But there are cases where deviating from this recommendation is useful, for example: https://stackoverflow.com/a/14534751/829571 – assylias Oct 13 '17 at 09:39
1

It is not (and can not be) caught automatically in compile or runtime (except if you explicitly check for it.

Simple counter examples:

public boolean equals(Object other){
    return new Random().nextInt(3) == new Random().nextInt(3);
}

public int hashCode() {
    return new Random().nextInt(3);
}

However it is a good idea to create unit tests that check these contracts. I have encountered bugs that were hard to spot due to utilizing badly implemented equals/hashcode.

Viktor Mellgren
  • 4,318
  • 3
  • 42
  • 75
  • yeah the more I think about it, the more I realise that this can't be automatically caught. I see there are frameworks in Java for correct-by-construction designs. I wonder if there are any frameworks that attempt to check for this contract violation at compile time. Would be an interesting project. – Colm Bhandal Oct 13 '17 at 09:25
  • 1
    If you are interested in something in that direction check out https://en.wikipedia.org/wiki/Java_Modeling_Language – Viktor Mellgren Oct 13 '17 at 11:41
  • Nice! Very interesting. It looks like this allows you to at least specify in a natural way these contacts in a way like Hoare triples & then this is converted to runtime assertions. I doubt it would be possible to write a tool in general that can give a YES/NO answer at compile time for any JML spec though- probably an undecidable problem like most of these general things in computer science. Anyway, very interesting. Wish industry was using this more. – Colm Bhandal Oct 15 '17 at 10:24