-2
if("String ".intern().trim()=="String"){
    System.out.println("Equals");
}else{
    System.out.println("Unequal");
}

above code is showing Unequal. I don't understand why? Can someone explain it?

Pshemo
  • 122,468
  • 25
  • 185
  • 269
  • 4
    I don't do any java, but just because I see such a question every week on SO, I know you shouldn't compare strings with `==` but with `.equals()` :-) – Laurent S. Feb 06 '14 at 13:01
  • 3
    @Bartdude I think this is a question about interned Strings - so the question is valid. – Puce Feb 06 '14 at 13:04
  • @Puce The problem is that the right side of the comparison hasn't been interned - therefore it will never equal to the interned form on the left side. – JB- Feb 06 '14 at 13:05
  • Maybe, but still it looks like a string comparison to me... I'm not into Java so I can't tell, but from the answers I see, my remark was valid... – Laurent S. Feb 06 '14 at 13:06
  • I *hope* you are only doing this as an experiment. In practice, using `intern()` so that you can compare strings using `==` is unlikely to be an effective optimization, and likely to make your code fragile. – Stephen C Feb 06 '14 at 13:14
  • @J.B String literals are always interned, so what you say there isn't true. – Dennis Meng Feb 06 '14 at 22:13

5 Answers5

3

I'm not really sure what you're facing, but if you want to compare the addresses of the strings by using the intern() method, this will also work:

if ("String ".trim().intern() == "String") {
    System.out.println("Equals");
} else {
    System.out.println("Unequal");
}

You only have to swap the trim() and intern() calls.

intern() searches for the string which is already on the heap and addresses this. When you use the == to compare the strings, the addresses will be equal.

For better visualization:

Value                         Evaluates to    Address    Explanation
"String"                      "String"        1          Creates new "String"
"String "                     "String "       2          Creates new "String "
"String ".trim()              "String"        3          trim() creates new "String"
"String ".trim().intern()     "String"        1          intern() finds the already created "String"
"String ".intern()            "String "       2          intern() finds the already created "String "
"String ".intern().trim()     "String"        4          trim() creates new "String"

That's also because trim() is generating a new String().

To try by yourself:

public class StringCompare {
    public static void main(String[] args) {
        System.out.println(System.identityHashCode("String"));
        System.out.println(System.identityHashCode("String "));
        System.out.println(System.identityHashCode("String ".trim()));
        System.out.println(System.identityHashCode("String ".trim().intern()));
        System.out.println(System.identityHashCode("String ".intern()));
        System.out.println(System.identityHashCode("String ".intern().trim()));
    }
}

Will output something like:

1500673861       // 1
1777631459       // 2
859434349        // 3
1500673861       // 1
1777631459       // 2
538093921        // 4
bobbel
  • 3,327
  • 2
  • 26
  • 43
2

You need to know that String literals are placed in string pool by default like

String s = "Hello";//this will be in string pool

but Strings created at runtime via new String(...) are not by default placed or retrieved from this pool.

String s2 = new String(s);// or even `new String("Hello")`
System.out.println(s == s2);// returns false, which means s2 holds different String
                            // object then from String pool

Now substring returns new String(...) objects, so it means they are not from String pool.

trim uses substring method internally which if

  • range specified to substring will be different than from 0 till length will return new String object with characters from specified range
  • range is from 0 till strings length (ideally covers entire string) returns same String with return this;

So in your code you are trying to place "String " in string pool (which you don't have to do, because you are using String literal "String " which is already placed in pool), Then you are using trim method on this object so since there is part to trim, it will create and return new String, different from original, and definitely not from String pool so comparing it with "String" literal with == will return false.

Pshemo
  • 122,468
  • 25
  • 185
  • 269
1

"String".intern() creates a different instance of String stored in permgen or metaspace while the original instance is stored on regular heap. Therefore your comparison will always be false.

JB-
  • 2,615
  • 18
  • 17
0

Always compare strings using equals()method!!!

wawek
  • 1,577
  • 1
  • 13
  • 23
0

Try something like this:

if("String ".trim().equals("String")){
    System.out.println("Equals");
}else{
    System.out.println("Unequal");
}

Useful Link

  1. ==, .equals(), compareTo(), and compare()
  2. Comparing Strings and Portions of Strings
  3. When should we use intern method of String on String constants (Example On Stack Overflow)
Community
  • 1
  • 1
ravibagul91
  • 20,072
  • 5
  • 36
  • 59