1

I have this code,

class  Test{

public static void main(String args[])
{
Boolean a;
Boolean b;
char [] c={'S','t','r','i','n','g'};

a=("String".replace('g','G')=="String".replace('g', 'G')); 
b=("String".replace('g','g')=="String".replace('g', 'g'));

System.out.println("---"+a);
System.out.println("---"+b);
System.out.println(c.toString()=="String");
}

The Out put is ---false ---true false

I did visit JLS documentation by oracle where it says. The replace method: Returns a new string resulting from replacing all occurrences of oldChar in this string with newChar. If the character oldChar does not occur in the character sequence represented by this String object, then a reference to this String object is returned. Otherwise, a new String object is created that represents a character sequence identical to the character sequence represented by this String object, except that every occurrence of oldChar is replaced by an occurrence of newChar.

when the O/p one is false why the O/p second is true?

JLS document says about toString method: This object (which is already a string!) is itself returned. then why not O/p third is true?

Can any one please explain it to me

Thanks in advance GPAR

stark
  • 12,615
  • 3
  • 33
  • 50
Gpar
  • 181
  • 1
  • 1
  • 7
  • 2
    Use equals insted of == – Uhla Nov 08 '14 at 17:01
  • I'm guessing this is because of the string pool used internally, where identical strings won't be created twice. On a side note: format your code. – keyser Nov 08 '14 at 17:06
  • 1
    @Uhla no, this is not that this question is about. `ToYonos` no, this is not a duplicate. – Tom Nov 08 '14 at 17:19
  • It's related to [How do I compare strings in Java?](http://stackoverflow.com/questions/513832/how-do-i-compare-strings-in-java), but the answer to that question doesn't address the other part of what's going on here: the `String.replace()` method doesn't create a new string instance when there's nothing to actually replace (thus allowing the reference-equality check to succeed). So not a duplicate per se. – Peter Duniho Nov 08 '14 at 23:06

3 Answers3

5

"String".replace('g','g') makes no changes and returns the original string. Both the string literals are in the string pool as a single object. So

 "String".replace('g','g')=="String"

That's why your b boolean was true.

As for c, you are calling toString() on a char array. A char array is not a String.. There is no reason that should return the same instance as another String in your code.

khelwood
  • 55,782
  • 14
  • 81
  • 108
2
a=("String".replace('g','G')=="String".replace('g', 'G'));

This returns false, because the replace method returns a completely new String instance. The check == returns false, because both parts refer to different String instances.

b=("String".replace('g','g')=="String".replace('g', 'g'));

This returns true, because the replace method returns the String instance on which it was called, if oldChar and newChar are the same (source). Since "String" is an interned String, both parts are referring to the same instance.

c.toString()=="String";

This returns false again, because toString() returns a new String instance containing the array representation. This representation can look like this [C@50206be6. That means even a c.toString().equals("String") call wouldn't return true.

Tom
  • 16,842
  • 17
  • 45
  • 54
  • @SotiriosDelimanolis yes, that is right, thank you. I've tested it with `System.out.println(c);`, but this is not the same as `System.out.println(c.toString());`. – Tom Nov 08 '14 at 17:31
  • 1
    Now you've got a complete answer. +1 – Sotirios Delimanolis Nov 08 '14 at 17:31
  • Then cant we have String from array of character? Sorry this is diverting from my original question. i.e char[] c in my code to String? – Gpar Nov 08 '14 at 18:00
  • JLS documentation says replace method returns old String reference only when there is no char available for replace. i.e only if 'g' in my example was not available. Here its not the case. In all other case it will create a new String. Am I missing something? @Tom – Gpar Nov 08 '14 at 18:03
  • @Gpar You can create a String out of a char array by using `new String(c)`. As you can see in the linked source code, the `replace` method does "nothing" if `oldChar` and `newChar` are the same. – Tom Nov 08 '14 at 18:06
  • Thanks @tom my last 2 points are clear but is String.replace('g','G') on left hand side of assignment operator is different from one on the right hand side? is it not one object in a string pool? – Gpar Nov 08 '14 at 18:54
  • Again I am diverting my question a bit here What will toString is for? if it does not even return a String? @tom – Gpar Nov 08 '14 at 18:55
  • @Gpar No, they are not in the string pool, because they are created with `new String(...)`. To add them to the pool, call `intern()` on a string obejct: `"String".replace('g', 'G').intern() == "String".replace('g', 'G').intern()` is `true`. – Tom Nov 08 '14 at 19:20
  • @Gpar `toString` returns a `String` and it usefull to get a string representation of an object. The standard implementation of it (in the class `Object`) creates somethin "cryptic" like this: `[C@50206be6`. `[` means that the object is an array type and `C` means that is of type `char`. `@50206be6` is a memory adress. You can override the `toString` method in your own classes to change that behavior. – Tom Nov 08 '14 at 19:21
  • Sorry again, I got my answer to the previously asked question @tom. But, Howcome "String"=="String" are equal and created in the string pool and not String.replace('g','G')? Can you please explain this to me? – Gpar Nov 08 '14 at 20:53
  • @Gpar `#replace` creates a new String instance using the `new` operator. That means, calling that method twice creates the String instances `A` and `B` which contain the exact same value. That means `A == B` is `false` (due to the different instances), but `A.equals(B)` is `true` (due to the same value). `"String"` retrieves the interned String reference. If you call `"String"` x times, you will always get the exact same String instance, instead of new ones. Calling `A.intern()` will add `A` to the String pool. So `"StrinG"` will give the exact same reference as `A` holds. – Tom Nov 08 '14 at 21:15
0

Afaik the == operator checks if the object is actually the same. If you want to compare the content of the object, you should use .equals()

It might be a bit confusing why the first check return false but not the second. I think it might be due to .replace(a, b) where a == b does not actually modify the string and so the instance is the same, whereas when the strings are altered the instance is different.

So in short: Use a.equals(b); instead of a == b;

Gelx
  • 129
  • 7
  • Thanks I do know the difference between the equals method and == operator. I just want to figure out which method of String creates new string and which one returns the same reference? – Gpar Nov 08 '14 at 17:48