Lecture 9: Equality, Copying and Views9.1The Object ContractEvery class extends Object, and therefore inherits all of its methods. Two of these areparticularly important and consequential in all programs, the method for testingequality:public boolean equals (Object o)and the method for generating a hash code:public int hashCode ()Like any other methods of a superclass, these methods can be overridden. We’ll see ina later lecture on subtyping that a subclass should be a subtype. This means that itshould behave according to the specification of the superclass, so that an object of thesubclass can be placed in a context in which a superclass object is expected, and stillbehave appropriately.The specification of the Objectclass is rather abstract and may seem abstruse. But fail-ing to obey it has dire consequences, and tends to result in horrible obscure bugs.Worse, if you don’t understand this specification and its ramifications, you are likely tointroduce flaws in your code that have a pervasive effect and are hard to eliminatewithout major reworking. The specification of the Objectclass is so important that itis often referred to as ‘The Object Contract’.The contract can be found in the method specifications for equalsand hashCodein theJava API documentation. It states that:·equalsmust define an equivalence relation – that is, a relation that is reflexive, sym-metric, and transitive;·equalsmust be consistent: repeated calls to the method must yield the same resultunless the arguments are modified in between;·for a non-null reference x, x.equals (null)should return false;·hashCodemust produce the same result for two objects that are deemed equal bythe equalsmethod;61
9.2Equality PropertiesLet’s look first at the properties of the equalsmethod. Reflexivity means that an objectalways equals itself; symmetry means that when aequals b, bequals -a; transitivitymeans that when aequals band bequals c, aalso equals c.These may seems like obvious properties, and indeed they are. If they did not hold, it’shard to imagine how the equalsmethod would be used: you’d have to worry aboutwhether to write a.equals(b)or b.equals(a), for example, if it weren’t symmetric.What much less obvious, however, is how easy it is to break these properties inadver-tently. The following example (taken from Joshua Bloch’s excellent Effective Java:Programming Language Guide, one of the course recommended texts) shows how sym-metry and transitivity can be broken in the presence of inheritance.