Java Strings Confusion [duplicate] - java

This question already has answers here:
How do I compare strings in Java?
(23 answers)
Closed 6 years ago.
String s1 = "abc";
String s2 = "abc";
String s3 = new String("abc");
String s4 = new String("abc");
if (s1 == s2) is giving true
while (s3 == s4) is giving false.
Can somebody give a detailed explanation onto what is String pool, heap, how many objects are created in each line and how many objects created in total.
Why s3==s4 is giving false?
A detailed explanation will be much appreciated.

When you do new String(...), it is evaluated at runtime and hence creates two different instances and you end up getting s3 == s4 as false. Same thing happens when you use StringBuilder and do something like sb.toString() which is again evaluated at runtime.
For Example,
StringBuilder sb = new StringBuilder();
String foo = sb.append("abc").toString();
String bar = new String("abc");
String foobar = "abc";
Here foo, bar and foobar are all different objects and hence foo == bar or foo == foobar will evaluate to false.
On the other hand s1 == s2 returns true because abc one declared, already exists in the String Pool and in this case both the objects points to the same reference in the pool.

String Class in java is defined in java.lang package and it is exactly that, a class and not a primitive like int or boolean.
Strings are developed to offer operations with many characters ans are commmonly used in almost all the Java applications
Some interesting facts about Java and Strings:
String in immutable and final in Java and in this case JVM uses String Pool to store all the String objects.
What are different ways to create String Object?
We can create String object using new operator like any normal java class or we can use double quotes (literal assignment) to create a String object.
There are too several constructors available in String class to get String from char array, byte array, StringBuffer and StringBuilderetc etc.
To your Question:
When we create a String using double quotes, JVM looks in the String pool to find if any other String is stored with same value. If found, it just returns the reference to that String object else it creates a new String object with given value and stores it in the String pool.
When we use new operator, JVM creates the String object but don’t store it into the String Pool. We can use intern() method to store the String object into String pool or return the reference if there is already a String with equal value present in the pool.
So when you do
String s1 = "abc";
String s2 = "abc";
those are checked in the StringPool and since s1 already exist there, s2 will take the same reference, hence, s1 ==s2 is true.
but when you do:
String s3 = new String("abc");
String s4 = new String("abc");
you are using the new operator, therefore the JVM is not checking if there is an string already in the heap, it will just allocate a new space for s4, so is s3==s4 ??? of course no.
Please take a look at the image below for a more illustrative example.

Related

Java String Memory-Address [duplicate]

This question already has an answer here:
How is String concatenation working in following
(1 answer)
Closed 1 year ago.
Why is the result false?
String s1 = "hello";
String s2 = "world";
String s3 = "helloworld";
String s4 = s1+s2;
System.out.println(s3==s4);
As I know, there's already one "helloworld" in the constant pool.
Thanks for answering, but what I want to ask is not the difference between "==" and "equals", I just want to make sure s1+s2; makes a new String, even though there's already one String Object with value "helloworld" in memory.
You need to understand that they all are object instance of class String
String s1 = "hello";
String s2 = "world";
String s3 = "helloworld";
This creates 3 objects with different values and different memory
String s4 = s1+s2;
Now you are again creating a new object with same value as s1 and s2 but since its a new object it has different memory.
System.out.println(s3==s4);
Now with this line you are trying to compare the values for these 2 objects and in String class the correct way to do it is by using equals() method i.e.,
System.out.println(s3.equals(s4));
For detailed information please check this:
https://www.geeksforgeeks.org/difference-equals-method-java/
(s3==s4) - means comparing references, not values. reference s3 is not the same as reference s4. s3 and s4 are two different instances of String.
use equals for comparing values of objects. override equals for your own classes if it necessary.

java "== " unusual behaviour [duplicate]

This question already has answers here:
How do I compare strings in Java?
(23 answers)
== and .equals() not working in java [duplicate]
(1 answer)
Closed 6 years ago.
import java.lang.String;
public class Test {
public static void main(String[] args) {
String a1="ka";
String a2="ka";
System.out.println("a1==a2? "+(a1==a2));
String a3="k";
String a4=new String("k");
System.out.println("a3==a4? "+(a3==a4))
System.out.println("a3==a4? "+(a3==a4.intern()));
String a5="k";
String a6=a4+"a";
System.out.println("a1==a6? "+(a1==a6));
}
}
Output that i got:
a1==a2? true
a3==a4? false
a3==a4? true
a1==a6? false
a1===a2 is true as line 5 will not create new String literal in string pool area.Only reference to previously created string is returned.
a3==a4? false as a4 will have refernce to the String object instead of the string in the string in string pool area. My question is if a3 is referencing the string constant instead of the String object, how is it able to use the methods of the String class?
a4.intern() will return the reference to the string in the string pool which happens to be same as a3
a6=a4+"a" will create a new string "ka". But this actually make use of StringBuilder class and its append method . It is then converted to string using toString(). Does this process store the newly created string "ka" in the string pool area? Since the string is already in the pool the code at line 12 should return the reference to it. So the a1==a6 should be true.rt?
I am new to java. Please guide me where i am doing the mistake?
You are comparing the Strings wrongly (because you are in fact comparing references)
String Class in java is defined in java.lang package and it is exactly that, a class and not a primitive like int or boolean.
String is immutable and final in Java and in this case JVM uses String Pool to store all the String objects.
What are different ways to create String Object?
We can create String object using new operator like any normal java class or we can use double quotes (literal assignment) to create a String object.
To your Question:
When we create a String using double quotes, JVM looks in the String pool to find if any other String is stored with same value. If found, it just returns the reference to that String object else it creates a new String object with given value and stores it in the String pool.
When we use new operator, JVM creates the String object but don’t store it into the String Pool. We can use intern() method to store the String object into String pool or return the reference if there is already a String with equal value present in the pool.
So when you do
String s1 = "abc";
String s2 = "abc";
those are checked in the StringPool and since s1 already exist there, s2 will take the same reference, hence, s1 ==s2 is true.
but when you do:
String s3 = new String("abc");
String s4 = new String("abc");
you are using the new operator, therefore the JVM is not checking if there is an string already in the heap, it will just allocate a new space for s4, so is s3==s4 ??? of course no.
Please take a look at the image below for a more illustrative example.

Count Distinct String Object Instances

How many distinct String object instances are created in the following code segment?
String s1 = new String("hello");
String s2 = "GoodBye";
String s3 = s1;
Not sure about all my reasoning here.
By using the keyword new that creates an instance from the String class, I am guessing that has to be an object. However, I am confused, is String after the new now considered a method because it has ( ) and then it is calling a String literal "hello" in it?
String s2 = "Goodbye";
I think this is a String literal, and since Strings are actually objects even the String literal is considered object. Not 100% sure if that is true.
String s3 = s1; Just refers back to s1. Therefore, it is not distinct.
So my answer is 2 distinct objects.
Please explain if I am a right or wrong.
The correct answer is 3.
String s1 = new String("hello");
String s2 = "GoodBye";
String s3 = s1;
The compiler will put both literals "hello" and "GoodBye" into a "constant pool" during compilation time, which then will be loaded by the classloader. So the JVM automatically interns all String literals used by this class, when it loads that class. More about this: When are Java Strings interned?. The String constant pool is then managed during runtime.
During runtime the JVM will create the third String object when it reaches the line String s1 = new String("hello").
So you would and up with three distinct String objects, where two of them contain the same word "hello". So s1.equals("hello") would be true, but s1 == "hello" would be false, because s1 references to a different String on the heap, than the literal "hello".
The line String s3 = s1 just creates a variable s3 with a copied reference to the String object of s1. It doesn't create a new object.
Also mind that you can "manually" add Strings into the String constant pool by using the method String#intern. So s1.intern() == "hello" is true, because the String reference returned from s1.intern() is the reference to the literal "hello" which was already in the constant pool.
If you like to get another and maybe more detailed explanation with some drawings about objects and their location, you can check this article on javaranch.

String pool Objects [duplicate]

This question already has answers here:
Questions about Java's String pool [duplicate]
(7 answers)
Closed 7 years ago.
Can you please clarify me, how many objects will be created in below case and why? I am slightly confused with this.
String s1 = "cat";
String s2 = "cat";
String s3 = "c"+"at";
String s4 = new String("cat");
String s5 = "kitty"+"cat";
String s6 = new String("kittycat");
String s7 = s5;
String s8= new String(s5); // Newly Added in this Question
Let's look step-by-step:
String s1 = "cat";
String s2 = "cat";
These two will be just the same constant pool entry created in your class file by javac compiler. When this class is loaded, this string (along with all other constant pool strings) will be automatically interned, thus it will be also merged with other "cat" strings in other classes.
String s3 = "c"+"at";
This is practically the same: if string concatenation can be computed during the compilation, it's done by javac. So it's practically the same as s1 and s2. This is covered by JLS, chapter 15.18.1:
The String object is newly created (§12.5) unless the expression is a constant expression (§15.28).
String s4 = new String("cat");
Here you explicitly create a new object. Java language guarantees that when you use a new keyword, you will have a new distinct object which cannot be the same as any of objects created previously. However if you use this object only in current methods (or in methods which can be inlined into the current) and don't use == operation to compare it with other strings, JIT compiler can skip the object allocation for optimization. But if you actually use == or System.identityHashCode, or this method is executed as interpreted frame, then it will be actually new object.
The "cat" string which is passed to the parameter is actually the same object as s1, s2, and s3.
String s5 = "kitty"+"cat";
This is similar to s3: the javac compiler will just create a "kittycat" string during the compilation. Looking into bytecode you cannot even know that there was a concatenation in the source.
String s6 = new String("kittycat");
This is similar to s4: new object is created explicitly. If you try to use s6 == "kittycat" later, you will get false.
String s7 = s5;
Here you just assign a reference to the previously created s5 string, thus no new object is created here.
So the answer is: at most 4 strings will be created, but in some cases it can be optimized down to 2 strings. And the most important: if you try to check how many strings you have from inside the same program (i.e. not using Java agent or analysing memory dump), you will always get four.
user3360241 - Your answer seems to be correct... Not sure why it's been down voted without giving any explanation... if you do this the size will be two..
Set<Integer> set = new HashSet<Integer>();
set.add(s1.hashCode());
set.add(s2.hashCode());
set.add(s3.hashCode());
set.add(s4.hashCode());
set.add(s5.hashCode());
set.add(s6.hashCode());
set.add(s7.hashCode());
System.out.println("size :: "+set.size());

Understanding how string comparison works in Java [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How do I compare strings in Java?
I am new to Java and I have difficulties in understanding String comparison. Can anyone explain the differences between the following scenarios?
Scenario 1 :
String a = "abc";
String b = "abc";
When I run the if(a == b) it returns true.
Scenario 2 :
String a = new String("abc");
String b = new String("abc");
and run if(a == b) then it returns false.
What is the difference?
== operator compares the references of two objects in memory. If they point to the same location then it returns true.String object in java are Immutable, so when you create Strings like in scenario1 then it didn't create new string. It just points the second string to the memory location of first string.
However, .equals() method compares the content of the String. When strings has same value then this method returns true.
So, in general it is recommended to use equals() method instead of ==.
It's because of Java String constant memory pool. Same valued literals are stored once.
String a = "abc";
String b = "abc";
// Now there is 1 string ("abc") and 2 references pointing to it.
String a = new String("abc");
String b = new String("abc");
// Now you have 2 string instances and 2 references.
Scenario 1 returns true because of a compiler optimization.
In general you should use equals() instead of == to compare strings.
In Java you need to use like this if(str.equals(str2)) which compares actual value of string rather than references.
Case1:
String a = "abc";
String b = "abc";
if(a == b)
In this case abc is cached in String constant pool thus a new string is not created String b = "abc"; b just refers to the string created by a it returns true as a and b both point to the same Object in the memory.
Case2:
String a = new String("abc");
String b = new String("abc");
and run if(a == b) then it returns false.
Here a two Strings are created and == operator just checks if two references point to the same reference, which it doesnt in this case thus it returns false
Two ways of creating string are
1) String s ="hello"; No. of string literal = 1 i.e. "hello" - No. of String objects on heap = 0
2) String s= new String("hello"); - No. of string literals =1 and No. of string objects =1
Java maintains a string pool of "LITERALS" and objects are going to stay on heap.
Advantage of string pooling: 1) Reduced memory usage*(PermGenSpace Issue) 2) Faster Comparision i.e == comparision 3) Faster lookup
Disadvantages: 1) Overhead of maintaining pool
How to pool String objects? Use Intern() on a string to add it to the pool. Downside of interning: 1) You may forget to intern some strings and compare them by == leading to unexpected results.
The reason is that the String literal "abc" will be turned into a global String instance for all its ocurrences, it will be the same String instance therefore you can be sure that "abc" == "abc". It is possible for the compiler to do that because String instances are immutable. However, if you explicitly allocate the String they will be two different instances and they will also be different to the String instance implicitly created by the compiler i.e. new String("abc") != new String("abc") and "abc" != new String("abc").
Another good example to understand what the compiler is doing is to look at this code:
"abc".contains("a");
you see that the literal behaves like an instance of a String type. You may exploit this to minimize programming errors e.g.
// this is OK and the condition will evaluate to false
String myStringValue = null;
if ("abc".equals(myStringValue)) { // false
whereas this code results in NPE:
// this will produce a NPE
String myStringValue = null;
if (myStringValue.equals("abc")) { // NPE

Categories