I thought it all sounded good up until someone said that we have to make sure there is toString() implemented for all (non-primitive) objects being sent in to the method that is being cached, as the parameters’ outputs from toString() are being used to create the key.
It took me about a minute to realize that what this effectively does is tie the toString() method into the complicated subject of Object Identity.
Now, as Java programmers, we all have to deal with Identity, mostly by defining the equals(…) and hashCode() methods, with respect to the "Equals and HashCode Contract". ("Equal objects must produce the same hash code as long as they are equal, however unequal objects need not produce distinct hash codes.")
Now, I have to include toString() into the mix with the equals(…) and hashCode() concerns, and I think this upsets me.
Whereas I used to be able to use toString() as a debugging tool, now I have to (potentially) neuter it’s debugging capabilities to tow the line with equals(…). Example: Consider a domain-object that is using Hibernate optimistic locking… I used to be able to include the version column in my toString() output to look for sequencing bugs, but now I won’t be able to because version is very specifically dis-included from the concept of Identity.
(The only upside I see to this is that as long as I can get toString() and equals(…) to work together in defining identity, I could probably use toString().hashCode() as a shortcut for the hashCode() output.)
But, what are our other choices? Should I recommend that we use the hashCode() for the cache keys, or should I recommend using Serializable for more mature serialization?