3
String str1 = new String("I love programming");
String str2 = new String("I love programming");
boolean boo = str1 == str2; // evaluates to false

String str1 = "I love programming";
String str2 = "I love programming";
boolean boo = str1 == str2; // evaluates to true

Why does first one evaluate to false and second one evaluate to true?

And here you can find more: What is the Java string pool and how is "s" different from new String("s")?

Community
  • 1
  • 1
Haggra
  • 3,539
  • 2
  • 20
  • 28
  • The compiler likely optimized away the second string and put them into the same object. Since strings are immutable there's no harm in doing so. The first two strings had their constructors called explicitly, so new objects were created, likely their internal pointer is also pointing to the same place where the last two. – lared Jan 11 '15 at 00:05

4 Answers4

13

== will return true if the objects themselves have the same addresses. For space and efficiency reasons, repeated literals are optimized to use the same address. The second str1 and str2 are equal to the same address, thus == returns true.

In the first example, because you are explicitly declaring memory using the new keyword, the str1 and str2 don't have the same addresses. Thus, str1==str2 evaluates to false.

When testing equality, use the String.equals(); function instead. Thus, str1.equals(str2); //true

umop aplsdn
  • 300
  • 1
  • 12
  • @Tyler: does that mean Java actually searches through its memory for equal Strings when declaring a new one? So when declaring `str2` it finds that `str1` is equal to it and thus sets it to the same address? – dokaspar Jan 11 '15 at 00:15
  • @dokaspar look up the docs for the `String.intern();` function. I'm not entirely sure about how each JDK implements interning exactly, but it should be something like that. Remember, only literals are interned, not new Objects. – umop aplsdn Jan 11 '15 at 00:18
  • @dokaspar I think it's implementation dependent what strings are really "same", but in this case it's done by the compiler: it sees the string four times (twice in the constructor calls), and stores them once in the constant pool of the class file. So there is no lookup at runtime, the classfile references the same string (constant, not object) several times. Exercise for the reader: are equal string literals in different class files the same? – Silly Freak Jan 11 '15 at 00:29
  • (okay, so I tested it... at least on OpenJDK 7, they seem to be the same. I'd say the class loader matches the class file's constant pool against the interned strings) – Silly Freak Jan 11 '15 at 00:37
1

The equals() method compares the contents of the String and the == compares the reference in Java.

Drew Kennedy
  • 4,118
  • 4
  • 24
  • 34
Coding Enthusiast
  • 3,865
  • 1
  • 27
  • 50
1

It's there in the Java Memory Model

The first equality statement returns false as your're comparing two different references of two different objects as you used the key word new which allocate memory space inside the heap in to two distinct memory addresses, the seconds, the JVM will allocate memory space once "into the stack" (from Java 7 they are in the heap as well) and the compiler optimizes memory usage by making the two variables pointing to the same memory space which it explains that the equality result is true.

Here's an interesting reading about heap, stack, ...etc. JVM Internals Blog

Cheers

Abderrazak BOUADMA
  • 1,526
  • 2
  • 16
  • 38
  • This answer is not quite correct: String literals are required by the Java Language Specification to be interned, which means they can not be allocated on the stack. – meriton Jan 11 '15 at 00:25
  • your comment is right starting from java 7, thank's – Abderrazak BOUADMA Jan 11 '15 at 00:35
  • Actually, it's been that way since Java 1.0, see for instance http://titanium.cs.berkeley.edu/doc/java-langspec-1.0/3.doc.html#101083 – meriton Jan 11 '15 at 01:57
0

Not like C. (==) compares references of java string variables. It compares two address where the strings are stored. Two compare them by values, you need to use string1.equals(string2).

Santhosh
  • 1,771
  • 1
  • 15
  • 25