Because you have to compare compatible types, since comparing incompatible types for equality will always be false
.
String
is compatible with Object
, so comparing references with those types is not a compile-time error. StringBuilder
is compatible with Object
, so you can assign a StringBuilder
to an Object
-typed variable. But String
and StringBuilder
are not compatible with each other. So if you have a String
reference, and an Object
reference, you can compare them without a compile-time error. But if you have a String
reference and a StringBuilder
reference, you can't — the compiler knows that the comparison will never be true
.
Note how it's all about the type of the references (the variables), not the type of the objects assigned to them. That's why it's possible to set up your second scenario and have it compile, even though it can never have a true result.