Effective Java Item 9, is the CaseInsensitiveString example correct?

effective-java, java

Solution

The solution is correct, because symmetry is not violated. You're wrong concerning `s.equals(cis)`. It will return `false` in any case as `String` internally tests if the other object is also instanceof `String` and returns `false` if not. (And `CaseInsensitiveString` does not extend `String`.)

So as `s.equals(cis)` is `false` and `cis.equals(s)` is `false`, symmetry is given.

Sidenote about `instanceof`

Note that `String#equals(Object o)` uses `o instanceof String` to check the type of its argument. This is only correct because `String` is `final` and cannot be subclassed! Otherwise we could write a subclass of `String` and the following would happen:

String s = "Hello";
SubclassOfString sos = new SubclassOfString("Hello");
s.equals(sos) == true // as sos is instanceof String
sos.equals(s) == false // as s is NOT instanceof SubclassOfString

So if your classes are not `final`, use `this.getClass() == o.getClass()` instead of `instanceof` for type checking in `equals(Object)`!

Problem

I'm reading the second edition of the book, page 36. I don't understand the solution to the simmetry problem: ``` @override public boolean equals(Object o) { return o instanceof CaseInsensitiveString && ((CaseInsensitiveString) o).s.equalsIgnoreCase(s); } ``` If I have the `CaseInsensitiveString cis= new CaseInsensitiveString("hello")` and the `String s="hello"` this behaves in a non-symmetric manner, because `s.equals(cis)` is true, but `cis.equals(s)` is false... What am I missing?

Original source