To add a little more info to the answers you already got:
Java has two types of storage. One is the stack, which includes variable names and their values. One is the heap, that is just a huge collections of free-floating objects.
Now, if you're working with primitive types (like int
, boolean
or char
), assigning a variable like
int myInt = 1;
pushes that variable on thje stack - the name is myInt
, the value is 1
.
If you, however, have an object (like strings are), assigning a variable does a little bit more.
String myString = "Hey!";
now creates an object (instance of String
) somewhere on the heap. It has no name there, only some address in the memory where it can be found.
In addition to that, it pushes a variable on the stack. The name is myString
- and the value is the address of the object on the heap.
So why is this relevant to comparing variables? Because ==
compares values of variables. ON THE STACK, that is. SO if you compare primitive types, everything works as expected. But if you're comparing Objects, ==
still only compares the values of the variables - which is, in that case, the addresses to the objects. If the addresses are the same, it returns true. That does mean, both variables point to the same object. If the addresses are different, ==
returns false., Without ever looking at the heap, where the objects really are.
An example:
String a = new String("Hey!");
String b = a;
if (a == b) System.out.println("true");
else System.out.println("false");
will echo "true" - because both variables contain the same object.
String a = new String("Hey!");
String b = new String("Hey!");
if (a == b) System.out.println("true");
else System.out.println("false");
will echo "false" - because you have two objects on the heap now, and a
points to the one, while b
points to the other. So while the contents of both objects may be the same, the contents of a
and b
on the stack are different.
Therefore, to compare any object, always use .equals()
if you want to compare contents, not instance-equality.
[Addendum]:
With strings, this is even more complicated. As you already found out already,
String a = "Hey!"; // mention the difference to the example above:
String b = "Hey!"; // I did NOT use the `String()` cosntructor here!
if (a == b) System.out.println("true");
else System.out.println("false");
will actually give you "true". Now why is THAT? One might think that we still create two objects. But actually, we are not.
String
is immutable. That means, once a String has been created, it cannot be modified. Ever. Don'T believe that? Take a look!
String myString = "test"; // we create one instance of String here
myString += " and more"; // we create another instance of String (" and more")
// and append that. Did we modify the instance stored in
// myString now? NO! We created a third instance that
// contains "test and more".
Therefore, there is no need to create additional instances of String
with the same content - which increases performance, as Strings are widely used, in masses, so we want to have as few of them as possible.
To archive that, the JVM maintains a list of String Objects we already created. And every time we write down a String literal (that is something like "Hey!"
), it looks in that lists and checks if we already created an instance that has that value. If so, it returns a pointer to that exact same instance instead of creating a new one.
And THIS is, why "Hey!" == "Hey!"
will return true.