11
  public class Comparison {
        public static void main(String[] args) {
            String s = "prova";
            String s2 = "prova";
            System.out.println(s == s2);
            System.out.println(s.equals(s2));
        }
    }

outputs:

true
true

on my machine. Why? Shouldn't be == compare object references equality?

Johnydep
  • 6,027
  • 20
  • 57
  • 74
giorgiosironi
  • 1,077
  • 1
  • 11
  • 18

11 Answers11

32

Because String instances are immutable, the Java language is able to make some optimizations whereby String literals (or more generally, String whose values are compile time constants) are interned and actually refer to the same (i.e. ==) object.

JLS 3.10.5 String Literals

Each string literal is a reference to an instance of class String. String objects have a constant value. String literals-or, more generally, strings that are the values of constant expressions -are "interned" so as to share unique instances, using the method String.intern.

This is why you get the following:

System.out.println("yes" == "yes"); // true
System.out.println(99 + "bottles" == "99bottles"); // true
System.out.println("7" + "11" == "" + '7' + '1' + (char) (50-1)); // true
System.out.println("trueLove" == (true + "Love")); // true
System.out.println("MGD64" == "MGD" + Long.SIZE);

That said it needs to be said that you should NOT rely on == for String comparison in general, and should use equals for non-null instanceof String. In particular, do not be tempted to intern() all your String just so you can use == without knowing how string interning works.

Related questions


On new String(...)

If for some peculiar reason you need to create two String objects (which are thus not == by definition), and yet be equals, then you can, among other things, use this constructor:

public String(String original) : Initializes a newly created String object so that it represents the same sequence of characters as the argument; in other words, the newly created string is a copy of the argument string. Unless an explicit copy of original is needed, use of this constructor is unnecessary since Strings are immutable.

Thus, you can have:

System.out.println("x" == new String("x")); // false

The new operator always create a new object, thus the above is guaranteed to print false. That said, this is not generally something that you actually need to do. Whenever possible, you should just use string literals instead of explicitly creating a new String for it.

Related questions

Community
  • 1
  • 1
polygenelubricants
  • 376,812
  • 128
  • 561
  • 623
  • 4
    +1 because all answers are basically the same, but this one takes the trouble to explain. – Zsolt Török Jul 30 '10 at 09:47
  • since which version was this implemented? – Louis Rhys Jul 30 '10 at 11:03
  • 2
    Common reason to do `new String(...)` is when working with substrings. If your String is large, and you call substring() on it, returned substring will still keep reference to large original string. This may cause problems and memory leaks in some situations -- large string is not GCed although you no longer use it in the code. To "fix" this, you can do `new String(largeString.substring(...))`. (I felt like I should add some useful comment too). – Peter Štibraný Jul 30 '10 at 12:52
  • @Peter: yes, this is in the linked question ("What is the purpose..."). I was considering adding it here, but wasn't sure if this is already too long and/or too confusing for beginners. – polygenelubricants Jul 30 '10 at 12:55
11

JLS, 3.10.5 => It is guaranteed that a literal string object will be reused by any other code running in the same virtual machine that happens to contain the same string literal

Manuel Selva
  • 18,554
  • 22
  • 89
  • 134
5

If you explicitly create new objects, == returns false:

String s1 = new String("prova");
String s2 = new String("prova");
System.out.println(s1 == s2); // returns false.

Otherwise the JVM can use the same object, hence s1 == s2 will return true.

Behrang
  • 46,888
  • 25
  • 118
  • 160
2

It does. But String literals are pooled, so "prova" returns the same instance.

Konrad Garus
  • 53,145
  • 43
  • 157
  • 230
2
String s = "prova";
String s2 = "prova";

s and s2 are literal strings which are pointing the same object in String Pool of JVM, so that the comparison returns true.

Truong Ha
  • 10,468
  • 11
  • 40
  • 45
1

Yes, "prova" is stored in the java inner string pool, so its the same reference.

InsertNickHere
  • 3,616
  • 3
  • 26
  • 23
1

Source code literals are part of a constant pool, so if the same literal appears multiple times, it will be the same object at runtime.

Michael Borgwardt
  • 342,105
  • 78
  • 482
  • 720
1

The JVM may optimize the String usage so that there is only one instance of the "equal" String in memory. In this case also the == operator will return true. But don't count on it, though.

fish
  • 1,050
  • 9
  • 13
0

You must understand that "==" compares references and "equals" compares values. Both s and s1 are pointing to the same string literal, so their references are the same.

duffymo
  • 305,152
  • 44
  • 369
  • 561
0

When you put a literal string in java code, the string is automatically interned by the compiler, that is one static global instance of it is created. Or more specifically, it is put into a table of interned strings. Any other quoted string that is exactly the same, content-wise, will reference the same interned string.

So in your code s and s2 are the same string

Adrian Regan
  • 2,240
  • 13
  • 11
0

Ideally it should not happen ever. Because java specification guarantees this. So I think it may be the bug in JVM, you should report to the sun microsystems.

Darshan Prajapati
  • 843
  • 2
  • 11
  • 33