Disclaimer: I am the creator of EqualsVerifier. I just opened this question :).
Joachim Sauer mentions the workaround correctly.
Let me explain why EqualsVerifier does not like your implementation. Suppose now that Person not abstract; this makes the examples a little easier. Let them say that we have two Person objects, for example:
Person person1 = new Person("John"); Person person2 = new Worker("John", "CEO of the world");
And let equals on both of these objects:
boolean b1 = person1.equals(person2); // returns true boolean b2 = person2.equals(person1); // returns false
b1 true because the Person equals method is called and it ignores workDescription . b2 is false because the Worker equals method is called, and the instanceof or getClass() check is that the method returns false.
In other words, your equals method is no longer symmetrical, and it is a requirement for the equals to be implemented correctly, according to Javadoc .
You can really use getClass() to get around this problem, but then you have another problem. Let's say you use Hibernate or a mocking structure. These structures use bytecode manipulation to subclass your class. Essentially, you get a class like this:
class Person$Proxy extends Person { }
So let me say that you make a circular trip to the database, for example:
Person person1 = new Person("John"); em.persist(person1); // ... Person fetchedPerson = em.find(Person.class, "John");
Now call equals :
boolean b3 = person1.equals(fetchedPerson); // returns false boolean b4 = fetchedPerson.equals(person1); // also returns false
b3 and b4 are false because person1 and fetchedPerson have different classes ( Person and Person$Proxy , to be precise). equals now symmetrical, so at least it follows the contract, but it's still not what you want: fetchedPerson no longer "behaves" like Person . In technical terms: this violates the Liskov replacement principle , which is the basis for object-oriented programming.
There is a way to do all this work, but it's quite complicated. (If you really want to know: this article explains how to do this.) To keep things simple, EqualsVerifier suggests you make the equals and hashCode methods final. In most cases, this will work fine. If you really need to, you can always follow a difficult route.
In your case, since Person is abstract, you can also not implement equals in Person , but only in Worker (and any other subclasses you may have).