another language idea: have two interfaces for hashing objects. The first one is your standard one that has a method hashCode() The second one extends the first, but has a method named List<Object> getHashables(), and it takes all of the returned objects and combines their hashes
that way, you don't have a gazillion hashcode functions that do the combining themselves
or, even better, you could use those objects for object equality as well
Ha I just looked up the proof in Hardy& Wright, and as a subsequent theorem there was one talking about "quadratfrei" numbers. I didn't know that the german "quadratfrei" (squarefree) was also used in english (or perhaps used to be used)