I know this is an old question but here's how I look at it (I find very useful):
Technical explanations
In Java, all variables are either primitive types or references.
(If you need to know what a reference is: "Object variables" are just pointers to objects. So with Object something = ...
, something is really an address in memory (a number).)
==
compares the exact values. So it compares if the primitive values are the same, or if the references (addresses) are the same. That's why ==
often doesn't work on Strings; Strings are objects, and doing ==
on two string variables just compares if the address is same in memory, as others have pointed out. .equals()
calls the comparison method of objects, which will compare the actual objects pointed by the references. In the case of Strings, it compares each character to see if they're equal.
The interesting part:
So why does ==
sometimes return true for Strings? Note that Strings are immutable. In your code, if you do
String foo = "hi";
String bar = "hi";
Since strings are immutable (when you call .trim()
or something, it produces a new string, not modifying the original object pointed to in memory), you don't really need two different String("hi")
objects. If the compiler is smart, the bytecode will read to only generate one String("hi")
object. So if you do
if (foo == bar) ...
right after, they're pointing to the same object, and will return true. But you rarely intend this. Instead, you're asking for user input, which is creating new strings at different parts of memory, etc. etc.
Note: If you do something like baz = new String(bar)
the compiler may still figure out they're the same thing. But the main point is when the compiler sees literal strings, it can easily optimize same strings.
I don't know how it works in runtime, but I assume the JVM doesn't keep a list of "live strings" and check if a same string exists. (eg if you read a line of input twice, and the user enters the same input twice, it won't check if the second input string is the same as the first, and point them to the same memory). It'd save a bit of heap memory, but it's so negligible the overhead isn't worth it. Again, the point is it's easy for the compiler to optimize literal strings.
There you have it... a gritty explanation for ==
vs. .equals()
and why it seems random.