2

Kindly check my code and answer, tell me how it works in java technology.

String s1 = "roushan8";
String s2 = "roushan"+8;
String s3 = "roushan"+s1.length();
System.out.println(s1==s2);
System.out.println(s2==s3);
System.out.println(s3==s1);

The result is:

true
false
false
almightyGOSU
  • 3,731
  • 6
  • 31
  • 41
  • 3
    He doesn´t want to know that equals is the right answer, rather why `"roushan"+8` is the same object as `"roushan8"` while `"roushan"+s1.length();` is not – SomeJavaGuy Jul 29 '15 at 10:47
  • 3
    The concatenation of `"roushan"+8;` is done at compile time. Thus `s1` and `s2` are the same literal Strings and placed in the pool. On the other hand, `s1.length()` is a concatenation done at runtime. – Alexis C. Jul 29 '15 at 10:48
  • @AlexisC., you should have posted it as an answer. – Codebender Jul 29 '15 at 10:48
  • @Codebender I think they're already various duplicates about this :) – Alexis C. Jul 29 '15 at 10:50
  • `s1` = {`String@443`} `"roushan8"` `s2` = {`String@443`} `"roushan8"` `s3` = {`String@444`} `"roushan8"` – Andrew Tobilko Jul 29 '15 at 11:00
  • Kindly tell me how to print String reference value. – roushan kumar Singh Jul 29 '15 at 11:05
  • 1
    @roushankumarSingh You can't do it explicitly (references are different than pointers, and ware organized so we wouldn't have to worry about exact address of object in memory). But you can try using fact that original hashcode value will most probably based on memory address, so you could try using `System.identityHashCode` to get its value - we need this method, otherwise we would get value from overriden in String class hashCode method which is not based on memory address but on text stored by string. So try with `System.identityHashCode(s1)` (same for (`s2`, `s3`). – Pshemo Jul 29 '15 at 11:17
  • Thanks @pshemo, Now my doubt is clear. – roushan kumar Singh Jul 29 '15 at 11:42

2 Answers2

5

== compares references, not sate. So if both references hold exact same object == returns true, if the hold different objects, even if their state is same it will return false. To compare state of objects use equals method.

Now difference between

String s2 = "roushan"+8;
String s3 = "roushan"+s1.length();

is that s1.length() is not compile time constant (its value is not known at compilation time) while 8 is.

So when compiler knows value at compile time it can optimize our code, and concatenate strings once at compilation time, which means that

String s2 = "roushan"+8;

will be compiled as

String s2 = "roushan8";//there is no reason to repeat this concatenation every time at runtime

But for

String s3 = "roushan"+s1.length();

s1.length() must be calculated at runtime, which means that this code will have to be compiled it into something like

String s3 = new StringBuilder("roushan").append(s1.length()).toString();

Now strings literals like "roushan8" are by default interned (they end up in String literals pool, or are taken from them to avoid recreating same string twice). This means that

String s1 = "roushan8";
String s2 = "roushan8"; // <-- that is how "roushan"+8; will be compiled

will represent same interned "roushan8" literal from string pool, which is confirmed by ==.

But strings which ware created at runtime by using new String() (and StringBuilder#toString is internally creating new String()) are not interned. This means they will not try to use literal representing same text, but will create separate new String instance, so even if that instance will contain same text, it will be treated as different object then the one from String pool, which is stored by s1 or s2 references.


You can confirm this by taking a look at bytecode of

String s1 = "roushan8";
String s2 = "roushan"+8;
String s3 = "roushan"+s1.length();

which is

   0: ldc           #19                 // String roushan8
   2: astore_1
   3: ldc           #19                 // String roushan8
   5: astore_2
   6: new           #21                 // class java/lang/StringBuilder
   9: dup
  10: ldc           #23                 // String roushan
  12: invokespecial #25                 // Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
  15: aload_1
  16: invokevirtual #28                 // Method java/lang/String.length:()I
  19: invokevirtual #34                 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
  22: invokevirtual #38                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
  25: astore_3

where we can see that

10 "roushan" string is being loaded
12 and later used as argument in StringBuilder <initialization> (constructor)
16 next value of s1.lenbth is being calculated
19 and append to StringBuilder
22 now with StringBuilder#toString method we create String representing concatenated text
23 and store it in s3 variable

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

You should use s1.equals(s2). The == operator compares objects for being the same (located at the same address in memory), thus it won't always return true for equal strings.

Danil Gaponov
  • 1,413
  • 13
  • 23
  • Check this answer http://stackoverflow.com/questions/9698260/what-makes-reference-comparison-work-for-some-strings-in-java too – Danil Gaponov Jul 29 '15 at 10:49