from above are not equivalent since if you insert an element into one you can

From above are not equivalent since if you insert an

This preview shows page 9 - 11 out of 14 pages.

from above are not equivalent, since if you insert an element into one, you can see thatthe other doesn’t change. But two distinct strings that contain the same sequence ofcharacters are equivalent, since you can’t modify them and thus discover that they aredifferent objects. (We’re assuming you’re not allowed to use == in this experiment.)Two objects are observationally equivalentif you can’t tell the difference between themusing observer operations (and no mutations). On these grounds, the empty lists t1andt2from above are equivalent, since they have the same size, contain the same elements,etc. And two distinct strings that contain the same sequence of characters are alsoequivalent.Here’s how you code equalsand similar. For a mutable type, you simply inherit theequalsmethod from Object, but you write a similarmethod that performs a field-by-field comparison. For an immutable type, you override equalswith a method that per-forms a field-by-field comparison, and have similarcall equalsso that they are thesame.This solution, when applied uniformly, is easy to understand and works well. But it’snot always ideal. Suppose you want to write some code that interns objects. This meansmutating a data structure so that references to objects that are structurally identicalbecome references to the very same object. This is often done in compilers; the objectsmight be program variables, for example, and you want to have all references to a par-ticular variable in the abstract syntax tree point to the same object, so that any infor-mation you store about the variable (by mutating the object) is effectively propagatedto all sites in which it appears.To do the interning, you might try to use a hash table. Every time you encounter a newobject in the data structure, you look that object up in the table to see if it has a canon-ical representative. If it does, you replace it by the representative; otherwise you insertit as both key and value into the table.Under the Liskov approach, this strategy would fail, because the equality test on thekeys of the table would never find a match for distinct objects that are structurallyequivalent, since the equalsmethod of a mutable object only returns true on the verysame object.9.5.3The Java ApproachFor reasons such as this, the designer of the Java collections API did notfollow thisapproach. There is no similarmethod, and equalsis observational equivalence. 69
Image of page 9
This has some convenient consequences. The interning table will work, for example. But it also has some unfortunate consequences. The seating plan program will break, because two distinct empty lists will be deemed equal. In the Java List specification, two lists are equal not only if they contain the same ele- ments in the same order, but also if they contain equal elements in the same order. In other words, the equals method is called recursively. To maintain the Object contract, the hashCode method is also called recursively on the elements. This results in a very nasty surprise. The following code, in which a list is inserted into itself, will actually fail
Image of page 10
Image of page 11

  • Left Quote Icon

    Student Picture

  • Left Quote Icon

    Student Picture

  • Left Quote Icon

    Student Picture