There is a difference between the static type of an object and the dynamic type of a variable.
The static type is the type known at compile time. For Object o = "Karan";
, the static type is the one at the left of o
, i.e. Object
. Now, one could ask why that is the case since at compile-time, it can be inferred that o
is a String
. Well if we consider something like
Object o;
if (someCondition) {
o = "Karam";
} else {
o = new StringBuffer();
}
then we cannot know whether o
is a String
or a StringBuffer
, thus its static type is Object
(since o
is defined as Object
).
The dynamic type is the type at runtime. In the example above, after the if
-statement has been executed, o
is either a String
or a StringBuffer
, but not both and nothing else. In your example, the dynamic type of Object o = "Karan";
is String
.
When variables are compared through equals(...)
, they must have the same dynamic type in order for the comparison to return true
(notice that this property is necessary, but not sufficient). Since o
in your example is, in fact, a String
AND the content is equal to s
, s.equals(o) == o.equals(s) == true
.
As to why s == o
returns true
: the question is answered in this post.