2

I was kind of telling some one that , we must use String.equals method to compare two strings values, we can not simply use == operator in java to compare Strings, and told him that == will return false as it doesn't compare the string value but String object reference value.

I have written this example to show him, but for my surprise it always prints true for == operator.. here is the code

public void exampleFunc1(){

    String string1 = "ABC";
    String string2 = "ABC";

    if(string1 == string2)
        System.out.println("true");
    else{
        System.out.println("false");

    }   
    System.out.println(" Are they equal "+(string1 == string2)); // this shouldn't print True but it does
    System.out.println(" Are they equal "+(string1.equals(string2)));

}

Output:-

Are they equal true

Are they equal true

So question here is in what circumstances == operator on objects can print true, except that both objects are same instance?

AAnkit
  • 27,299
  • 12
  • 60
  • 71
  • 1
    See the answer to [String comparison and String interning in Java](http://stackoverflow.com/questions/3885753/string-comparison-and-string-interning-in-java), which points out that compile-time constants can be interned so two literals end up refering to the same string object. – Simon Sep 01 '13 at 05:01

3 Answers3

2

String is one of a few special cases.

Class String keeps a special pool of "interned" Strings. Method myString.intern() looks up myString in this pool. If another String with the same contents already exists in the pool, a pointer to it is returned. If not, myString is added (and a pointer returned).

When you say myString= myString.intern() ;, you are effectively making myString refer to a shared copy or its underlying String available for future sharing (and no duplication). Most library methods creating Strings are subject to this, particularly String literals.

Other cases of "interning" occur with wrapper types Integer, Long, etc. They don't have constructors, but static methods valueOf() that return pre-built, shared objects when they can (usually the 256 values closest to zero), and new objects when they can not. The later is not much problematic because these types are more lightweight than Strings. Long, for example, has a payload of just 8 bytes. String contains a char[] that even empty is 16 bytes or so.

To answer your question, you can not count on any "interning" mechanisms. They have changed in the past, and they could change in the future (or even from one JVM to another), making your code unusable. Always use equals.

Mario Rossi
  • 7,651
  • 27
  • 37
  • thanks, And what happens if we change one string value – AAnkit Sep 02 '13 at 02:41
  • @Ankit How? With concatenation? My impression is that concatenation interns the result. With `String` functions? Same thing. The only escape to this is to **force** the creating of new `String`s by using `String` constructors. If the Java team had thought of interning before, these would not exist, and things would be similar to wrapper types (no constructors, just constructor-like static methods). – Mario Rossi Sep 02 '13 at 02:59
  • thats sound nice, Thanks :) , Happy coding. – AAnkit Sep 02 '13 at 03:20
1

You should use

String string1 = new String("ABC");

String string2 = new String("ABC");

Then everything would be correct like what you think,

In this case, "ABC" is just a reference to a const string.

jackalope
  • 1,554
  • 3
  • 17
  • 37
  • @Ankit That's because `new` forces a new `String` to be created. Constructors can't return a different object than the one they are constructing. However, if you subject both strings to interning, you will be back to `string1 == string2`. – Mario Rossi Sep 01 '13 at 05:24
0

The compiler may be optimizing the assignments and only creating one String object. If you use the explicit String constructor, the == operation should behave as expected.

Chris Bode
  • 1,265
  • 7
  • 16