Details
-
Bug
-
Status: Closed
-
Major
-
Resolution: Fixed
-
None
-
None
-
None
-
Operating System: All
Platform: All
-
28180
Description
equals considers self equal to any Object that has an accessible public getName
() method which returns a string that is the same than the internal name iName.
So if you compare two objects of subclasses of Enum that are not related
otherwise, but incidentally have the same name iName the equals method returns
true.
But even worse, it's also possible to compare a subclass of Enum to an object
of a totally unrelated class and to consider the objects equal if the totally
unrelated class provides a getName method that returns a string equal to iName.
If the getName method of the other object isn't accessible, an
IllegalAccessException is thrown and caught in the equals method and false is
returned which in this case seems to be correct.
The root of the problem is the use of reflection without checking first whether
the names of the classes (via other.getClass().getName().equals(this.getClass
().getName())) are the same (not the classes themselves, this is tested by the
equals method) before invoking the getName method on the other object via
reflection. If the names of the classes aren't equal, false can be returned
immediately instead of using reflection. Only if the classnames are equal
reflection should be used to determine equality.
Note: The old implementation of Enums.equals in the commons-lang 2.0
distribution seems to work ok in the first case with both objects being
subclasses of Enum. In the second case of the totally unrelated class, a
ClassCastException is thrown, but according to Joshua Bloch (Effective Java)
and the SDK-API-Documentation for Object.equals this violates the contract for
equals because equals is supposed to deliver true or false for any two non null
references.