String s1 = new String("string");
String s2 = new String("string");
String s3 = "string";
String s4 = "string";
System.out.println(s1 == s2); //FALSE
System.out.println(s2.equals(s1)); //TRUE
System.out.println(s3 == s4); //TRUE
System.out.println(s3.equals(s4)); //TRUE
What is the difference between creation of s1 and s3 ?
Please let me know
In String we are having only String object then why it treats this two differently.
s1 and s2 are having different memory address while s3 and s4 has same memory address.
why it works based on new operator.?
The String objects that represent string literals in your Java source code are added to a shared String pool when the classes that defines them are loaded1. This ensures that all "copies" of a String literal are actually the same object ... even if the literal appears in multiple classes. That is why s3 == s4 is true.
By contrast, when you new a String, a distinct new String object is created. That is why s1 == s2 is false. (This is a fundamental property of new. It is guaranteed to create and return a new object ... if it completes normally.)
However, in either case, the strings will have the same characters, and that is why equals is returning true.
While it is important to understand what is going on, the real lesson is that the correct way to compare Java strings is to use equals and not ==.
If you want to arrange that your String objects can be tested for equality using ==, you can "intern" them using the String.intern method. However, you have to do this consistently ... and interning is an expensive process in various respects ... so it is generally not a good idea.
1 - Actually, it is a bit more complicated than that. They objects get added to the pool at some time between class loading and first use of the literals. The precise timing is unspecified and JVM implementation dependent. However it is guaranteed to happen just once, and before any application code sees the String object reference corresponding to the literal.
s1 is a new String object that does not belong to a part of any pooled instance. s3 is an instance of a string that comes from a pool. Lookup java String pool. Take a look at the related intern() method on String.
The concept is not unique to java. String interning is supported in other languages. On that related note, pooling frequently used objects follows the flyweight pattern and is not limited to Strings. Take a look at Integer.valueOf(). Integers have a constant pool of their own too.
The JVM has an automatic optimisation. Unless you specifically create a new String object, and another String object already exists with the same value, the JVM automatically assumes that a new object is not a necessity, and will assign you a pointer to the equal String object that already exists.
Essentially, when you use the second option, this is what happens:
Step 1
First Object is created no problem.
Step 2
Before the second object is created, the String pool is checked for a value.
If that value currently exists, then there is no need to create a new object. It just returns the reference to the String object.
Step 3
Instead of being assigned a new Object, it is simply given a reference to the object made in step 1. This is to save memory.
This happens because the new operator forces creation of a new instance of String, while in the second case, as String is an immutable class, the JVM provides you with the same String instance for both variables to save memory. As there is no chance one of such objects will change causing the second one change as well (immutable, remember?) this is OK.
Related
I was trying to understand String#intern method. Now it has caused even more confusion.
package com;
public class Main {
public static void main(String[] args) {
String s1 = new String("GFG"); // Line-1
String s2 = s1.concat("GFG"); // Line-2
s2.intern(); // Line-3
String s4 = "GFGGFG"; // Line-4
// s2.intern(); // Line -5
System.out.println(s2 == s4);
}
}
The above code prints true. If I comment line 3 and uncomment line 5 it is printed false.
For line 3 the SCP is checked and the String is added to SCP.
But how did s2 equals to s4 in that case ?
s2 is still referencing to an object in heap which is pointing to SCP constant. Right ?
Can anyone please explain what is happening ? I've gone through different SO questions, but was not able to understand it still.
EDIT
I'm just trying to understand the intern method. I know the difference b/w == and equals and the latter is preferred.
String.intern() returns a canonical representation for the string object.
A pool of strings, initially empty, is maintained privately by the class String.
When the intern method is invoked, if the pool already contains a string equal to this String object as determined by the equals(Object) method, then the string from the pool is returned. Otherwise, this String object is added to the pool and a reference to this String object is returned.
It follows that for any two strings s and t, s.intern() == t.intern() is true if and only if s.equals(t) is true.
In simple words, Intern is responsible to make exact copy of contents in memory (string constant pool). Memory will be shared for all copied contents.
By applying String.intern() on a couple of strings will ensure that all strings having same contents share same memory. For example, if a name ‘Amy’ appears 100 times, by interning you ensure only one ‘Amy’ is actually allocated memory.
To prove it, we can use an operator == (used to compare reference) and equals method (to compare content).
public class InternExample{
public static void main(String args[]){
String s1=new String("hello");
String s2="hello";
String s3=s1.intern();//returns string from pool, now it will be same as s2
System.out.println(s1==s2);//false because reference variables are pointing to different instance
System.out.println(s2==s3);//true because reference variables are pointing to same instance
System.out.println(s2.equals(s3));//true because content are same
}}
Output:
false
true
true
Explanation:
Case-1: s1 and s2 has same content but pointing to different reference in memory as new String always create new reference so it is false.
Case-2: s3 is interned or copied from s1 and pointing to same reference in memory as intern function just make a copy and keep same reference so it is true.
Case-3: s2 and s3 has same content
It is very simple ... on the surface.
If you would have written:
s2 = s2.intern();
Then the location is irrelevant, always yielding s2 == s4.
What happens without the assignment seems a miracle for retrieving s2.
The JVM exchanging the string of s2 under the hood.
(Disassembly with javap -c did not show me something special.)
As intern is native, slow,
and the JVM is involved, I am not willing to dive further in this esoteric subject of String interning; pure speculations what could be happening.
But definitely baffling, an interesting issue.
This question already has answers here:
How do I compare strings in Java?
(23 answers)
Compare two objects with .equals() and == operator
(16 answers)
Closed 7 years ago.
I looked it up in a book, which is usually more thorough in terms of explanations than a website.
Take this for ex.:
if (nickname == "Bob")
The condition will be true only if nickname is referring to the same String object.
Here is a sentence I found confusing, can anyone please explain to why this is the case:
For efficiency, Java makes only one string object for every string constant.
The book points out that the way of assembling the object "Bob" also affects whether the condition will be true of not, which confuses me the most.
For ex.:
String nickname = "Bob";
...
if (nickname == "Bob") //TRUE
But if "Bob" is created from .substring() method, condition will be FALSE.
String name = "Robert";
String nickname = name.substring(0,3);
...
if (nickname == "Rob")//FALSE
Why is this so?
Edit: in the end of the book's explanation, I found a sentence which also confuses me a lot:
Because string objects are always constructed by the compiler, you never have an interest in whether two strings objects are shared.
Doesn't everything we write get constructed by the compiler?
You need to understand 2 things
1)
String a = "Bob";
String b = "Bob";
System.out.println(a.equals(b));
System.out.println(a == b);
How do you think? What the output?
true
true
What doing this? First string created in string pool in permanent generation memory. Second string get existing object from pool.
String a = "Bob"; // create object in string pool(perm-gen)
String b = "Bob"; // getting existing object.
How right you noticed :
For efficiency, Java makes only one string object for every string constant.
2)
String nickname = name.substring(0,3);
As String is immutable object name.substring(0,3); created new String("Rob") in heap memory, not in perm-gen.
Note :
In Java 8 String pool is created in PermGen area of Heap, garbage collection can occur in perm space but depends upon JVM to JVM. By the way from JDK 1.7 update, String pool is moved to heap area where objects are created.
Read more here.
String literals are internally handled by the JVM so that for every unique String literal, it always refers to the same object if it has the same value. For example, a string literal "test" in class A will be the exact same object as a string literal "test" in class B.
Doesn't everything we write get constructed by the compiler?
The compiler simply adds a the string literal to the classes constant pool upon compilation and loads it with a special instruction called LDC, the rest is handled by the JVM, which loads the string constant from a special string constant pool that never removes / garbage-collects any objects (previously permgen).
However, you can get the 'internal' version of any string (as if it was a string literal) using String#internal(), which would cause the == operator to work again.
It's about objects.
Since these aren't primitives == doesn't compare what they are. == compares where they are (in heap memory).
.equals() should (if implemented) compare what's contained in that memory.
This is a detail that is easily forgotten because small strings and boxed numbers often don't get new memory when created because it's more optimal to instead point you to cached version of the same thing. Thus you can ask for a new "Bob" over and over and just get handed a reference (memory address) to the same "Bob". This tempts us to compare them like primitives since that seems to work the same way. But not every object will have this happen to it so it's a bad habit to let yourself develop.
This trick works only when 1) a matching object already exists, 2) it's immutable so you can't surprise users of other "copies" by changing it.
To abuse an old metaphor, if two people have the same address it's a safe bet that they keep the same things at home, since it's the same home. However, just because two people have different addresses doesn't mean they don't keep exactly the same things at home.
Implementing .equals() is all about defining what we care about when comparing what is kept in these objects.
So only trust == to compare values of primitives. Use .equals() to ask an object what it think's it's equal to.
Also, this isn't just a java issue. Every object oriented language that lets you directly handle primitives and object references/pointers/memory address will force you to deal with them differently because a reference to an object is not the object it self.
The objects value is not the same as it's identity. If it was there would only ever be one copy of an object with the same contents. Since the language can't perfectly make that happen you're stuck having to deal with these two concepts differently.
This question already has answers here:
What is the difference between "text" and new String("text")?
(13 answers)
Closed 2 years ago.
String s="hi";
String s1=new String("hi");
In memory perspective, where are s and s1 stored? whether it is in heap memory or stack.
And s points "hi" and s1 points to memory location of where hi exists?
Please help?
Consider following
String s = "hi";
String s1 = new String("hi");
variable s will refer to the string literal hi that is referenced from String constant pool and if there are some more variables like s2 = "hi", then s and s2 will refer to same object.
String s1 = new String("hi");
This will create a new String at runtime.
In first case ,all the strnig literals are created when class is loaded in JVM
In seconds case, string objects are created when new String() is executed.
You can find a good tutorial about string constant pool at following link
http://www.thejavageek.com/2013/06/19/the-string-constant-pool/
String s="hi";
This statements creates the String object containing "hi" on the String pool.
String s1=new String("hi");
This statement creates a String object containing "hi" on the heap memory and a copy of it on StringPool (if "Hi" is not contained in stringPool).But here, S will point to the object on heap.
At class loading time, all String literals will be placed in pool. When you use new String("hi") an object will be created on heap. s and s1 are reference variables , it should reside in the method call stack ! The string literal "hi" will be handled by the JVM, by creating a String object on the heap, and having a reference to it from the String pool. The new operator merely takes the string object, whose reference is passed in the constructor, and create a new object. It just so happens that the string being passed to the constructor is a literal.
"hi" is a String literal. This gets created once in the String Constant Pool. In Java 7 that's in the Heap with other objects, but prior to that it was created in the Perm-Gen
String s = "hi";
String s1 = new String("hi");
new String("hi") creates a new String object on the heap, separate from the existing one.
s and s1 are references to the two separate objects. References themselves actually live on the stack, even though they point to objects in the heap.
s and s1 are just references to the strings, therefore they will be stored on the stack, unlike the string instances that are referenced by s and s1. In this case the value that s refers to will be put in the string pool whereas the value refered by s1 won't. Why? because the constructor of a string has been used to make that string. Only literals are pooled, and even if you chose those literals to be concatenations of other literals ( for example, if you have made String s2 = "h" + "i" then s and s2 would point to the same instance of a string that was stored in the string pool).
This leads to a little trap though: because pooled strings point to the same object it is tempting to use == operator instead of equals method to compare strings, which is just dangerous, because there are scenarios where == is the same as equals() but there are a lot more where == will have a different result than the equals() method.
Above answers are correct but shouldn't you use String *s1 = new String("hi") in place ofString s1 = new String("hi") ,as call to new will be returning a pointer to the string object.
I am fairly new to C++. Excuse me, if I am wrong.
PS: I am using the gcc version 4.4.7 20120313 (Red Hat 4.4.7-4) (GCC).
According to me when we create String using literal like String s="hello"
s object will reference the String "hello" that is stored in the String Constant pool.
If we will create the new String using New keyword like String s = new String("hello") then in this case two object is created. object s referenced the another object that is stored in the normal heap area and this object will referenced the String Hello that is stored in the String constant pool.
For more details please follow the link:-http://www.javatpoint.com/java-string
Java has string pool, due to which objects of string class are immutable.
But my question stands -
What was the need to make String POOL?
Why string class was not kept like other class to hold its own values?
Is internally JVM need some strings or is this a performance benefit. If yes how?
A pool is possible because the strings are immutable. But the immutability of the String hasn't been decided only because of this pool. Immutability has numerous other benefits. BTW, a Double is also immutable, and there is no pool of Doubles.
The need for the String pool is to reduce the memory needed to hold all the String literals (and the interned Strings) a program uses, since these literals have a good chance of being used many times, in many places of the program. Instead of having thousands of copies of the same String literal, you just have thousand references to the same String, which reduces the memory usage.
Note that the String class is not different from other classes: it holds its own char array. It may also share it with other String instances, though, when substring is called.
When we compiler see's that a new String literal has to be created,it first check's the pool for an identical string,if found no new String literal is created,the existing String is referred.
the benifit of making string as immutable was for the security feature. Read below
Why String has been made immutable in Java?
Though, performance is also a reason (assuming you are already aware of the internal String pool maintained for making sure that the same String object is used more than once without having to create/re-claim it those many times), but the main reason why String has been made immutable in Java is 'Security'. Surprised? Let's understand why.
Suppose you need to open a secure file which requires the users to authenticate themselves. Let's say there are two users named 'user1' and 'user2' and they have their own password files 'password1' and 'password2', respectively. Obviously 'user2' should not have access to 'password1' file.
As we know the filenames in Java are specified by using Strings. Even if you create a 'File' object, you pass the name of the file as a String only and that String is maintained inside the File object as one of its members.
Had String been mutable, 'user1' could have logged into using his credentials and then somehow could have managed to change the name of his password filename (a String object) from 'password1' to 'password2' before JVM actually places the native OS system call to open the file. This would have allowed 'user1' to open user2's password file. Understandably it would have resulted into a big security flaw in Java. I understand there are so many 'could have's here, but you would certainly agree that it would have opened a door to allow developers messing up the security of many resources either intentionally or un-intentionally.
With Strings being immutable, JVM can be sure that the filename instance member of the corresponding File object would keep pointing to same unchanged "filename" String object. The 'filename' instance member being a 'final' in the File class can anyway not be modified to point to any other String object specifying any other file than the intended one (i.e., the one which was used to create the File object).
What was the need to make String POOL?
When created, a String object is stored in heap, and the String literal, that is sent in the constructor, is stored in SP. Thats why using String objects is not a good practice. Becused it creates two objects.
String str = new String("stackoverflow");
Above str is saved in heap with the reference str, and String literal from the constructor -"stackoverflow" - is stored in String Pool. And that is bad for performance. Two objects are created.
The flow: Creating a String literal -> JVM looks for the value in the String Pool as to find whether same value exists or not (no object to be returned) -> The value is not find -> The String literal is created as a new object (internally with the new keyword) -> But now is not sent to the heap , it is send instead in String Pool.
The difference consist where the object is created using new keyword. If it is created by the programmer, it send the object in the heap, directly, without delay. If it is created internally it is sent to String Poll. This is done by the method intern(). intern() is invoke internally when declaring a String literal. And this method is searching SP for identical value as to return the reference of an existing String object or/and to send the object to the SP.
When creating a String obj with new, intern() is not invoked and the object is stored in heap. But you can call intern() on String obj's: String str = new String().intern(); now the str object will be stored in SP.
ex:
String s1 = new String("hello").intern();
String s2 = "hello";
System.out.println(s1 == s2); // true , because now s1 is in SP
a quick and confusing question. If Class A and Class B have this inside them:-
String name="SomeName";
and both classes are instantiated, is it true that both instances refer to same memory location of variable "name" say when we do this objA.name or objB.name ? which has value "SomeName" and since String is immutable, several instances of both classes of same JVM use the same variable repeatedly? I read somewhere online that, unless there is
String example=new String("something");
is used, the former declaration always creates one copy and it is used until all its applications are terminated for reclaiming memory.
Note: I see several answers, which one do I count on, can someone conclude. Thank you all for your effort, appreciate it.
Yes, if you create two strings like:
String a = "Hello";
String b = "Hello";
They will be the exact same object. You can test it yourself by doing
System.out.println(a == b);
If they are the same object, then their internal reference to the character array will be exactly the same.
Now, if you did String c = "Hell" + "o";, it would not have the same reference since it would have been (internally) built using StringBuilder.
There is a lot of good information here.
The relevant sections has (Note: The following is copied from that web site):
As mentioned, there are two ways to construct a string: implicit construction by assigning a String literal or explicitly creating a String object via the new operator and constructor. For example,
String s1 = "Hello"; // String literal
String s2 = "Hello"; // String literal
String s3 = s1; // same reference
String s4 = new String("Hello"); // String object
String s5 = new String("Hello"); // String object
Java has designed a special mechanism for keeping the String literals - in a so-called string common pool. If two String literals have the same contents, they will share the same storage locations inside the common pool. This approach is adopted to conserve storage for frequently-used strings. On the other hands, String object created via the new operator are kept in the heap. Each String object in the heap has its own storage just like any other object. There is no sharing of storage in heap even if two String objects have the same contents.
You can use the method equals() of the String class to compare the contents of two Strings. You can use the relational equality operator '==' to compare the references (or pointers) of two objects. Study the following codes:
s1 == s1; // true, same pointer
s1 == s2; // true, s1 and s1 share storage in common pool
s1 == s3; // true, s3 is assigned same pointer as s1
s1.equals(s3); // true, same contents
s1 == s4; // false, different pointers
s1.equals(s4); // true, same contents
s4 == s5; // false, different pointers in heap
s4.equals(s5); // true, same contents
Edit to add: Run this SSCE to test reference equality between two constant strings in to different classes:
class T {
String string = "Hello";
public static void main(String args[]) {
T t = new T();
T2 t2 = new T2();
System.out.println(t.string == t2.string);
}
}
class T2 {
String string = "Hello";
}
prints out true.
If "something" is literally hard-coded into your source code, then the two variables will point to the same in-memory String object.
Per the Java spec, a string literal (one that's defined as a literal in the byte codes) is "interned", so that any reference to that literal will obtain the exact same pointer, even if the reference is to an identical literal in an entirely separate class.
A string constructed at runtime (eg, "abc" + "xyz" or new String("abc")) will not be interned, and so the pointer will generally be unique. (But note that an optimizing compiler may combine "abc" + "xyz" into the single literal "abcxyz", resulting in an interned value.)
the former declaration always creates one copy and it is used until all its applications are terminated for reclaiming memory.
Strings, like other object are reclaimed when a GC is performed and there is no strong reference to it. Even intern'ed Strings can be cleaned up when they are no longer used.
I would add one more detail to all the solutions above. String interning is just an optimization of Java/C# compiler. It's not good to rely on it as it can be turned off in both cases.
It may also behave differently in different compilers/VM's implementations