1

Possible Duplicate:
How do I compare strings in Java?
Demonstrating string comparison with Java

I am getting confused by the very basics here. Since I've started using java I was always told "do not use == for string comparison; always use equals". Now I've started learning for the OCJP and came across some confusing points.

1)

String s1 = "Monday"; 
String s2 = "Monday";

s1 == s2 returns true;

2) Let's say a have a class defined as follows:

class Friend {
    String name;

     Friend(String n){
        this.name = n;
    }

     public boolean equals(Object o){
         return ((Friend) o).name == this.name;
     }
}

and I create instances of two objects:

Friend f1 = new Friend("1");
Friend f2 = new Friend("1");

f1.equals(f2) will return true

3) Finally, I have MyClass with main method defined:

public static void main(String[] args) {
        System.out.println(args[0] == "x");
    }

After the invocation java MyClass x false will be printed.

What is the difference between 1, 2 and 3? Why isn't false returned in case 1 and 2, when two strings obviously refer to different objects?

Community
  • 1
  • 1
Maggie
  • 7,823
  • 7
  • 45
  • 66

4 Answers4

2

String literals are "interned" (stored and referenced to one sharable value) to share instances, according to section 3.10.5 of the Java Language Specification.

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

This means that two string literals refer to the same internal object, and therefore are equal when compared using ==, as is done in examples 1 and 2. However, the args[0] string in example 3 is not a literal, but if you compare its interned value, like following, the expression will be true.

System.out.println(args[0].intern() == "x"); //prints true

Likewise, if you don't intern one of the strings in example 1 or 2, the related expression will be false.

String s1 = "Monday";
String s2 = new String("Monday");
System.out.println(s1 == s2); //prints false
FThompson
  • 28,352
  • 13
  • 60
  • 93
  • Java 7 add java.lang.String to switch/case construct. Are all the `case "xxx":` interned? – Aubin Oct 27 '12 at 09:21
  • @Aubin Yes, such strings are interned, but the switch statement interns the switch key before comparing if I recall correctly. – FThompson Oct 27 '12 at 09:44
1

The short is answer is: String pool. You can find a brief explanation here:

What is String pool in Java?

and a longer here:

http://www.dreamincode.net/forums/topic/187631-the-string-pool/

Community
  • 1
  • 1
Gergely Bacso
  • 14,243
  • 2
  • 44
  • 64
1

Try debugging with hashCode() method

s1.hashCode() must be equal to s2.hashCode() 

but

args[0].hashCode() is not equal to "x".hashCode()
vels4j
  • 11,208
  • 5
  • 38
  • 63
0

Initializing String values using #1 approach makes both variables refer the same String in memory, so this is why == returns true.

However, String values that end up being created in other ways will almost always refer different locations in memory, so == will return false. This is why equals is the best way to check String equality.

Dan D.
  • 32,246
  • 5
  • 63
  • 79