C# String/string: Compare string like in Java (by Reference) - java

How do I compare strings by reference like in Java? I know C#'s strings are compared by value with ==.
Object.ReferenceEquals does not work well too because C# assigns the existing address of a string to a new string if its contents already exist within the intern pool.
I've read this post and they suggest this:
Comparing VALUE and REFERENCE of types
string str = "hello";
string str2 = new StringBuilder().Append("he").Append("llo").ToString();
What I want to happen is something to this effect:
string s1 = "a";
string s2 = "a";
Console.WriteLine(s1 == s2); //False
//Or
Console.WriteLine(Object.ReferenceEquals(s1,s2)); //False
However, this is not the case for the 2 strings above. How do I achieve the same effect without using a StringBuilder?

You can use String.Copy to create a new instance:
string s1 = "a";
string s2 = String.Copy(s1);
Console.WriteLine(Object.ReferenceEquals(s1,s2)); //False

You could simply use new:
char[] charArray = new char[3];
charArray[0] = 'a';
charArray[1] = 'b';
charArray[2] = 'c';
string s1 = new string(charArray);
string s2 = new string(charArray);
Console.WriteLine(Object.ReferenceEquals(s1, s2));
Runnable example: https://ideone.com/H1O16q
The reason this works is because new always creates a new instance of the given type without doing any internalization. Every major OOP language behaves this way, as far as I'm aware.

In C# , string is immutable reference type. so, it has similar behaviors as value type (Ex: as your example here). But string builder is purely reference type.
So, you cannot use string to compare reference, but you can use stringbuilder.
StringBuilder p = new StringBuilder("test");
StringBuilder q = new StringBuilder("test");
Console.WriteLine(p == q); //false

Related

Where is the return object of java substring method created?

,the below code :
String str1 = "SachinTendulkar";
String str2 = str1.substring(6, str1.length());
String str3 = "Tendulkar";
the values in str2 and str3 are the same, but they do not refer to the same objects, what is exactly happening, where is str2 object created?
Thanks in advance.
String str2 = str1.substring(6, str1.length());
The above line will create a new Object, however String str3 = "Tendulkar"; is String literal and may reuse an instance from the string constant pool. String literals are by default intern String object and creating a String object using new String is not intern by default.
Now if you create an object with new String("Some String") it will explicitly create a new String object in heap. Now let take a look at String#substring method it returns like below. That means it will create a new String Object every time it successfully executes.
return ((beginIndex == 0) && (endIndex == value.length)) ? this
: new String(value, beginIndex, subLen);
String is the only class that can be instanciated using characters, that means it's exactly as if you wrote
String str2 = new String(str1.substring(6, str1.length()));
So basically str2 is a new instance of the String class, so is str3, they are two different objects.

what happens with new String("") in String Constant pool

if i create a string object as
String s=new String("Stackoverflow");
will String object created only in heap, or it also makes a copy in String constant pool.
Thanks in advance.
You only get a string into the constant pool if you call intern or use a string literal, as far as I'm aware.
Any time you call new String(...) you just get a regular new String object, regardless of which constructor overload you call.
In your case you're also ensuring that there is a string with contents "Stackoverflow" in the constant pool, by the fact that you're using the string literal at all - but that won't add another one if it's already there. So to split it up:
String x = "Stackoverflow"; // May or may not introduce a new string to the pool
String y = new String(x); // Just creates a regular object
Additionally, the result of a call to new String(...) will always be a different reference to all previous references - unlike the use of a string literal. For example:
String a = "Stackoverflow";
String b = "Stackoverflow";
String x = new String(a);
String y = new String(a);
System.out.println(a == b); // true due to constant pooling
System.out.println(x == y); // false; different objects
Finally, the exact timing of when a string is added to the constant pool has never been clear to me, nor has it mattered to me. I would guess it might be on class load (all the string constants used by that class, loaded immediately) but it could potentially be on a per-method basis. It's possible to find out for one particular implementation using intern(), but it's never been terribly important to me :)
In this case you are constructing an entirely new String object and that object won't be shared in the constant pool. Note though that in order to construct your new String() object you actually passed into it a String constant. That String constant is in the constants pool, however the string you created through new does not point to the same one, even though they have the same value.
If you did String s = "Stackoverflow" then s would contain a reference to the instance in the pool, also there are methods to let you add Strings to the pool after they have been created.
The new String is created in the heap, and NOT in the string pool.
If you want a newly create String to be in the string pool you need to intern() it; i.e.
String s = new String("Stackoverflow").intern();
... except of course that will return the string literal object that you started with!!
String s1 = "Stackoverflow";
String s2 = new String(s1);
String s3 = s2.intern();
System.out.println("s1 == s2 is " + (s1 == s2));
System.out.println("s2 == s3 is " + (s2 == s3));
System.out.println("s1 == s3 is " + (s1 == s3));
should print
s1 == s2 is false
s2 == s3 is false
s1 == s3 is true
And to be pedantic, the String in s is not the String that was created by the new String("StackOverflow") expression. What intern() does is to lookup the its target object in the string pool. If there is already a String in the pool that is equal(Object) to the object being looked up, that is what is returned as the result. In this case, we can guarantee that there will already be an object in the string pool; i.e. the String object that represents the value of the literal.
A regular java object will be created in the heap, and will have a reference s type of String. And, there will be String literal in String Constant Pool. Both are two different things.
My answer is YES!
Check the following code first:
String s0 = "Stackoverflow";
String s1 = new String("Stackoverflow");
String s2 = s1.intern();
System.out.println(s0 == s1);
System.out.println(s1 == s2 );
System.out.println(s0 == s2);
//OUTPUT:
false
false
true
s0 hold a reference in the string pool, while new String(String original) will always construct a new instance. intern() method of String will return a reference in the string pool with the same value.
Now go back to your question:
Will String object created only in heap, or it also makes a copy in String constant pool?
Since you already wrote a string constant "Stackoverflow" and pass it to your String constructor, so in my opinion, it has the same semantic as:
String s0 = "Stackoverflow";
String s1 = new String(s0);
which means there will be a copy in String constant pool when the code is evaluated.
But, if you construct the String object with following code:
String s = new String("StackoverflowSOMETHINGELSE".toCharArray(),0,13);
there won't be a copy of "Stackoverflow" in constant pool.

java string with new operator and a literal

Suppose we create a String s as below
String s = new String("Java");
so this above declaration will create a new object as the new operator is encountered.
Suppose in the same program if we declare a new String s1 as below :
String s1 = "Java";
Will this create a new object or will it point to the old object with Java as it is already created with new operator above.
Well, the second line won't create a new object, because you've already used the same string constant in the first line - but s1 and s will still refer to different objects.
The reason the second line won't create a new object is that string constant are pooled - if you use the same string constant multiple times, they're all resolved to the same string. There still has to be a String object allocated at some point, of course - but there'll only be one object for all uses. For example, consider this code:
int x = 0;
for (int i = 0; i < 1000000; i++) {
String text = "Foo";
x += text.length();
}
This will not create a million strings - the value of text will be the same on every iteration of the loop, referring to the same object each time.
But if you deliberately create a new String, that will definitely create a new object - just based on the data in the existing one. So for example:
String a = new String("test");
String b = new String("test");
String x = "test";
String y = "test";
// Deliberately using == rather than equals, to check reference equality
System.out.println(a == b); // false
System.out.println(a == x); // false
System.out.println(x == y); // true
Or to put it another way, the first four lines above are broadly equivalent to:
String literal = "test";
String a = new String(literal);
String b = new String(literal);
String x = literal;
String y = literal;
String myString = new String("Java");
creates two objects.
String myString = "Java";
creates one object.
In order to create a new object we use new keyword, Object cannot be created without using new.
As per the declaration in the first instance a new Object is created but in the second instance you are only declaring a variable with a value.
So its not an Object.
String s1="foo"; literal will be created in StringPool.
String s2="foo"; this time it will check "foo" literal is already available in StringPool or not as now it exist so s2 will refer the same literal as s1.
String s3=new String("foo"); "foo" literal will be created in StringPool first then through string arg constructor String Object will be created i.e "foo" in the heap due to object creation through new operator then s3 will refer it.
When you create a String with literal (e.g. String str = "Hello";) the Object is not created in Heap it will be available in StringPool only, however when you create a String using 'new' operator (e.g. String str = new String("Hello")) then the Object in StringPool is created along with one more object in Heap. So we are creating two objects unnecessarily. So string creating with literal is preferred way.

Diff bet new String("xyz") and "xyz" in Java [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
difference between string object and string literal
Hello,
Foremost, let’s come up with Java facts with String
Strings are immutable
My Question - If Strings are immutable then below statement should have compilation error!
String str = "xyz";
or
String str = new String("xyz");
str = "abc"; //COMPILATION ERROR
or
str = new String("abc"); //COMPILATION ERROR
What is the difference between below instantiation ?
String str = "xyz";
and
String str = new String("xyz");
Amit.
Strings are immutable means you can't do something like str[1] = 'x' i.e you cannot change the content of the string.
This will answer your second question.
Strings are immutable, so you cannot change the contents of a string.
In the following code:
String str = "xyz";
str = "abc";
you're not changing the contents of a String instance, but rather assigning a new String instance to the variable str. That is, if you do:
String str = "xyz";
String otherStr = str;
String str = "abc";
Then otherStr will remain the same. So you're not actually changing the object that str points to.
As for your second question
String str = "xyz";
takes the a String-object with value "xyz" from the String pool, while
String str = new String("xyz");
instantiates a new object.
That is, if you do
String a = "xyz", b = "xyz";
you will have a == b, while if you do
String a = new String("xyz"), b = new String("xyz");
this will not be the case.example
For more information, see:
What is String literal pool?
Questions about Java's String pool
Strings are immutable. String references are not. That's the distinction.
So:
String str = "abc";
str is a variable, referring to an immutable string "abc". Now if I do:
str = "def";
str is still a variable, referring to a different immutable string ("def"). I can change what str points to all I want, str is a variable. I can't change the actual content of any string (because Java's strings are immutable, by design). Whenever you do something that would seem to modify the string (say, toUpperCase), what it's actually doing is creating a new string with a copy of the old string's contents, modified in the way described.
The point of having strings be immutable is that I know that if I have a reference to a string, that string can never change. This is a very useful guarantee when passing strings around. If we didn't have this guarantee, we'd be copying strings all the time just to protect ourselves from someone modifying them. For instance, consider a standard setter function for a name property:
void setName(String n) {
this.name = n;
}
If strings weren't immutable, we'd have to do this:
void setName(String n) {
this.name = new String(n); // Blech, duplication
}
...so that we know our copy of the string won't change in ways we don't expect it to. This would result in a lot of duplication of string data in memory, most of it unnecessary, and so the designers of Java quite intelligently decided that strings would be immutable, and any changes you might want would create a new string rather than modifying the old one in-place. (You can get modify-in-place behavior for those situations that really warrant it by using char[] instead.)
Regarding your separate question about the difference between str = "abc"; and str = new String("abc"), the difference is that the latter (using the constructor) is guaranteed to return a new reference, whereas the former is not. E.g.:
String a = "abc";
String b = "abc";
String c = new String("abc");
a == b (checking whether the references match, not the strings) will be true, because literal strings are interned. a == c is guaranteed to be false, because we used the constructor for c. a.equals(b) and a.equals(c) will both be true, because a, b, and c all refer to equivalent strings.
If Strings are immutable then below
statement should have compilation
error!
You are misunderstanding the immutability concept. Look at Prasoon's answer.
String immutability means you cannot alter the contents inside the string.
String a = "hello";
String b = "hello";
System.out.println(a==b); // returns true.
Here both a and b both string literals refer the same object.
What is the difference between two
instantiations ?
String a = "hello";
String b = "hello";
System.out.println(a==b); // returns true.
Both refer to same String literal.
String a = new String("hello");
String b = new String("hello");
System.out.println(a==b); // returns false.
Two different String Objects are created.
String str = "xyz";
is an internal cached string instance.
String str = new String("xyz");
is a new object not instanciated from the cache
As side fact notice the following behaviour ...
"xyz" == "xyz" evals true
new String("xyz") == new String("xyz") evals false
new String("xyz").equals(new String("xyz")) evals true
notice also that == in Java compares object references.

Java Strings and StringPool

public String makinStrings() {
String m = "Fred47";
String s = "Fred";
s = s + "47";
s = s.substring(0);
return s.toString();
}
How many objects are created by the code?
I made a simple test:
public static void main(String[] args) {
String m = "a";
m += "bc";
String s1 = "mabc".substring(1);
String s2 = "abc";
System.out.println(m == "abc");
System.out.println(m == s1);
System.out.println(m == s2);
System.out.println(s1 == s2);
}
Shouldn't the result be "true, true, true, true", if m, s1, s2 point to the same object ("abc")?
Instead the result is "false, false, false, false"!
The result would be true in that case - but m, s1 and s2 all refer to different strings. Interning is performed automatically for constant string expressions, and can be explicitly invoked by calling the intern method, but it doesn't happen for string concatenation and substrings automatically.
In Sun's Java 7 implementation, x.substring(0) will actually return the same reference (x) back again, but I don't believe that's guaranteed by the API.
To look at your example:
public String makinStrings() {
String m = "Fred47";
String s = "Fred";
s = s + "47";
s = s.substring(0);
return s.toString();
}
The first two lines require that there are two strings in memory, but I don't know exactly when it's guaranteed that the objects are created. Once they have been created, they will stick around - so calling makinStrings again won't create any more in those two lines.
The string concatenation will create a new string object.
The substring call won't create a new string object in the implementation I've looked at - but it could.
The call to s.toString() won't create a new string (and this is specified in the JavaDoc).
No, just because two strings are equal does not mean that their references are equal.
The compile interns some strings to save space, so if you try:
String s1 = "abc";
String s2 = "abc";
Then s1 == s2 will be true, but this is a special case and not a general rule. Strings generated at runtime in general do not share the same reference by default.

Categories