The NullBean class violates the transitivity property which is required by the contract for overwriting Object.equals ( see https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#equals(java.lang.Object ). That is: If A and B are equal, and B and C are equal, then A and C should be equal as well.

However, a NullBean N1, the value null, and a NullBean N2 break transitivity: N1 is equal to null, null is equal to N2, but N1 is not equal to N2.

Comment From: jhoeller

NullBean is almost exclusively used for comparisons against null and not each other - but point taken, in terms of the equals contract, it could accept any other instance of NullBean as equal if ever encountering it - while still not being identical to it in terms of identity comparisons. We need to double-check whether this has semantic side effects with the present arrangement, we might only be able to consider this for 6.0.

Technically NullBean will never be strictly compliant with the equals contract since the latter only talks about non-null references and typically asks implementations to return false for equals(null).

Comment From: jhoeller

I'm afraid we'll have to leave this as-is, even if is bending the rules a bit. The present behavior makes null representations from different beans not equal which can be beneficial to distinguish between the same null bean as opposed to a null representation from distinct bean definitions. That characteristic seems more important than transitivity.