If Java had made primitives syntactically behave like immutable Objects with a proper implementation of equals(), Russell's suggestion would've made obvious sense and the language would've made more sense overall. The road not taken.
How does this overcome the need for two kinds of equality for objects? i.e. whether two pointers refer to the same address vs. whether they point to different addresses (or the same) that contain objects with the same value, according to that object's definition of equals().
Do you mean that the present == for primitives should be replaced with .equals(), and the == for object reference equality should be replaced by perhaps === or .refEquality(), and then the .equals() for objects should be left alone. and then, == be added as syntactic sugar for .equals().... Are those assumptions what you meant?
If so, the same outcome can be achieved with by changing object == to ===, and object .equals() to ==. However, there are reasons for treating primitives as objects other than this.
I expect you've a model in mind from some other language that resolves this in along different lines (C# would be one), and so you haven't felt the need to articulate the assumptions needed to make it work. If I've guessed wrongly, can you elaborate please?
The overwhelming majority of actual Java code needs at most one equality operation defined per class. Hamming compression and convention suggest that it be called == . Extensibility suggests that it desugar into .equals() or something like that.
For immutable objects like ints or Strings the implementation of equals() should compare internal values, because reference equality for passive immutable things is practically never useful. This should already obviate the majority of explicit calls to equals() in actual Java code, because most of them are comparing Strings anyway.
For mutable objects the default implementation of equals() should compare object identity (hashCode), but be overridable if the user wants something exotic.
Algorithms and data structures relying on equality, like hash tables, should provide the option of supplying the equality operator or hash function at construction time, just like printf frees the user from the need to commit to one Integer.toString() implementation in perpetuity.
This all sounds like a reasonable scheme to me. I can flesh it out in more detail if you request.
Yes, thanks, that's what I thought. BTW couple minor points: hashCode doesn't necessarily distinguish between objects (though most implementations would); and an exception for mutable objects is collections (e.g. a Set is mutable, but you want to be able to compare sets).
Yes, I'd want to compare sets, but using == for that feels to me a dubious programming practice, akin to using + for set union. A special method like hasIdenticalContents() would make me more comfortable, the longer name removing equals-ambiguity for readers and reflecting the nontrivial computation behind the scenes. And that would mesh nicely with other set operations like difference and containment that would be getting non-canonical names anyway...
Also, if you make Set.equals() depend on contents, you'll have to change the implementation of hashCode as well, wreaking havoc on sets containing mutable sets. So you really should only override equals() if your class is immutable or you're feeling especially exotic.
Your comment made no sense, then when I started to write a reply requesting clarification, it refreshed, and you'd added more. I feel much better now that it makes sense; and I'll watch out for the live-edit-comment in future (I do live-edit myself too).
But I'll say that naming is tricky, since programming languages are really human languages, and as such are affected by the familiarity of their specific users as much (or, at times, more) than pure logic. Highly illogical, I know.
EDIT: The present implementation of Set.equals() depends on contents; it's independent of hashCode, and there's no problem with sets of sets.