title: Overriding the java equals() method - not working?
body: <p>I ran into an interesting (and very frustrating) issue with the <code>equals()</code> method today which caused what I thought to be a well tested class to crash and cause a bug that took me a very long time to track down. </p>
  
  <p>Just for completeness, I wasn't using an IDE or debugger - just good old fashioned text editor and System.out's. Time was very limited and it was a school project.</p>
  
  <p>Anyhow - </p>
  
  <p>I was developing a basic shopping cart which could contain an <em><code>ArrayList</code> of <code>Book</code> objects</em>. In order to implement the <code>addBook()</code>, <code>removeBook()</code>, and <code>hasBook()</code> methods of the Cart, I wanted to check if the <code>Book</code> already existed in the <code>Cart</code>. So off I go -</p>
  
  <pre><code>public boolean equals(Book b) {
      ... // More code here - null checks
      if (b.getID() == this.getID()) return true;
      else return false;
  }
  </code></pre>
  
  <p>All works fine in testing. I create 6 objects and fill them with data. Do many adds, removes, has() operations on the <code>Cart</code> and everything works fine. I read that you can <em>either have <code>equals(TYPE var)</code> or <code>equals(Object o) { (CAST) var }</code></em> but assumed that since it was working, it didn't matter too much.</p>
  
  <p>Then I ran into a problem - I needed to create a <code>Book</code> object with <em>only</em> the <code>ID</code> in it from within the Book class. No other data would be entered into it. Basically the following:</p>
  
  <pre><code>public boolean hasBook(int i) {
      Book b = new Book(i);
      return hasBook(b);
  }
  
  public boolean hasBook(Book b) {
      // .. more code here
      return this.books.contains(b);
  }
  </code></pre>
  
  <p>All of a sudden, the <code>equals(Book b)</code> method no longer works. This took a VERY long time to track down without a good debugger and assuming the <code>Cart</code> class was properly tested and correct. After swaapping the <code>equals()</code> method to the following:</p>
  
  <pre><code>public boolean equals(Object o) {
      Book b = (Book) o;
      ... // The rest goes here   
  }
  </code></pre>
  
  <p>Everything began to work again. Is there a reason the method decided not to take the Book parameter even though it clearly <b> was </b> a <code>Book</code> object? The only difference seemed to be it was instantiated from within the same class, and only filled with one data member. I'm very very confused. Please, shed some light?</p>