Second pass...
then Object== on an indirect types is not a substitutibility test, you can have two strings that are equals when calling equals() but not when calling Object==, so it's a substitutibility test only when it returns true otherwise, you don't know.
Maybe this is part of the disconnect: you are using the term "substitutibility" incorrectly. Two identity objects that are .equals() but not == are _not_ substitutible, because they have an observable difference -- their identity. Substitutibility means "you can't discern any difference." For example, when comparing ints, all "ones" are interchangeable, regardless of what memory location or register they are stored in. But when comparing Integers, regardless of their content, they have an extra component of state -- the identity -- which is observable through a number of means. So two distinct (!=) Integer objects are not substitutible, even if they describe the same Integer.
On all types where == is defined in Java (modulo NaN), == is currently a substitutibility test, because two object references are only substitutible if they are the same object.
