> Perhaps more interesting, the three next-most-common superclasses are
> "convergent evolution" of an identical class (but with a different name)
>
> public abstract class ToStringless {
> @Override
> public final String toString() {
> return super.toString();
> }
> }
>
> This class prevents @AutoValue from synthesizing a toString() method, so
> Object.toString() gets locked in. Often this is used for a string which may
> be "sensitive", but perhaps there are other use cases. Of records with
> superclasses, 9% have something like this as their superclass. No state, just
> behavior. There's another superclass that also fixes identity-based hashCode
> and equals(). If we include this in the count, we get over 10%.
OK, so these fall into the narrow gap between what interfaces can do and what
abstract classes can — implement Object methods. That’s interesting, and worth
remembering.
Of course, it’s also easy to implement toString() in the record (and would be
even lower overhead with something like CMB.).