I use the == in the code below and prints out "Equals!", why? Can someone explain why these two different strings a and b are equal?
public class test
{
public static void main()
{
String a = "boy";
String b = "boy";
if(a == b)
{
System.out.println("Equals!");
}
else
{
System.out.println("Does not equal!");
}
}
}
This is due to String interning.
Java (The JVM) keeps a collection of String literals that is uses to save memory. So, whenever you create a String like so:
String s = "String";
Java 'interns' the string. However, if you create the String like so:
String s = new String("String");
Java will not automatically intern the String. If you created your strings this way, your code would produce different results.
A quick Google search reveals lots of good resources regarding String interning.
This article will explain it in details:
What is the difference between == and equals() in Java?
After the execution of String a =
“boy”; the JVM adds the
string “boy” to the string
pool and on the next line of the code, it
encounters String b = ”boy” again; in this case the JVM already
knows that this string is already
there in the pool, so it does not create a
new string. So both strings a and b point to the same string what means they
point to the same reference.
String a = "boy"; will create a new string object with value ("boy"), place it in the string pool and make a refer to it.
When the interpreter sees String b = "boy";, it first checks to see if string "boy" is present in the string pool, since it is present, no new object is created and b is made to refer to the same object that a is referring to.
Since both references contain the same content they pass the equality test.
Because the run time will have a string pool and when you need to assign a new constant string, the run time look inside the pool, if the pool contains it, then they set the variable point to the same String object inside the pool.
But you should never depends on this to check for content string equals. You should use the method: equals
Whenever we create a string like below :
String str1 = "abc";
String str2 = "abc";
JVM will check the str2 = "abc" in the string constant pool, if it is present then it wont create a new String instead it point to the string one in the string constant pool.
But in case of this String str = new String("abc"); it will always create a new String Object but we can use intern() function to force JVM to look into the string constant pool.
As rightly explained above, in the case of '==' comparison, the runtime will look into the String pool for the existence of the string. However, it very much possible that during garbage collection, or during memory issues, the virtual machine might destroy the string pool. The "==" operator therefor might or might not return the correct value.
Lesson - Always use equals() for comparison.
Related
As we know String is immutable, which means a new instance is created every time.
My question is that if I write:
System.out.println("Java"+"is"+"programming");
then how many objects are created in pool?
Your example will create a single string object in the string pool.
after that, if you do:
String x = "Javaisprogramming";
it will still point to the same object in the string pool. You can read more here
Your example will create a single string object. This is noted throughout the Java documentation.
The way I understand it, Java only adds new strings to the string pool when they're initially created. So,
String str1 = "hello";
Would be a single string in the pool.
So would
String str2 = "Java" + "is" + "cool";
Your Example will create 'single' string only which is
String x = "Javaisprogramming";
because '+' is a string concatenation operator in java(it internally call append()) so when you call System.out.println("Java"+"is"+"programming"); then compiler create one string object from concatenation and send it with println() method.
for more about '+' operator see this answer
This question already has answers here:
What is the difference between "text" and new String("text")?
(13 answers)
Closed 6 years ago.
If I declare a String as
String test=new String("testing");
and
String test1="testing1"
Since String is a class in JAVA how does test1 be a String Object without using a new Operator.Also,when a new Operator is used memory is assigned for new String("testing") so in the case of test1 how is the memory assigned?
Also,when the string is interned ,if two Strings have the same value with what reference is the String store once in the String intern pool?
Let us first consider this String test=new String("testing");
It creates an String Object in Heap.No Checking is done in String Pool for existence of this String in the pool.
and now this String test1="testing1"
It creates String a String Object in String Pool not in Heap.Before Creation check is done whether this string is already there in the pool.If yes its reference is returned else a new String is created in the pool and its reference is returned.Basically this is a String Literal, which is put in Constant pool for memory optimization and re-usability.
intern(): It is used when you construct an object using new() and you call intern() on that object then first a check is done in Stirng pool if that String already exists there or not,if yes it is directly used
Java has a separate memory for Strings that are created without calling the constructor with new. Every time such a String is created Java checks if that String is already in this memory. If it is, then Java sets the same reference to the new String until one of them changes.
When you create a String with the constructor using new then it behaves as a normal object in Java.
Take a look at this example:
String s1 = "Test";
String s2 = "Test";
When you compare this String with the == operator it will return true. s1.equals(s2) will also return true.
It looks different if you create String objects with the constructor like this:
String s1 = new String("Test");
String s2 = new String("Test");
When you now compare this Strings with the == operator it will return false, because the reference of this strings is now different (you created 2 unique String objects).
But if you use s1.equals(s2) it will return true as expected.
When you are using
String test1="testing1"
then it means you are storing only one copy of each distinct string value
but
String test=new String("testing");
gives you a new string object.
Consider your second assignment was:
String1 test1 = System.getenv("PATH");
Here, test1 is most probably also a reference to a String object, without using new().
You can assign references to already existing objects to new variables.
So where is the problem?
The problem is, you must not use sloppy wording like "test1 is a String object". It is not. It is a reference to a String object or null. That's all about it.
This question already has answers here:
Closed 11 years ago.
Possible Duplicates:
Java String declaration
Java Strings: “String s = new String(”silly“);”
What is the purpose of the expression “new String(…)” in Java?
Whats is the difference between
String a = new String("SomeValue");
and
String a = "SomeValue";
What is the difference and Which one is better and why ?
Thanks.
Unless you have a unusual, specific need and use case, always use the 2nd version, without the new.
Edited in response to #Ynwa
If you specifically need a String that you know is unique, and you will be comparing with == (which is also unusual), then use the 1st case. For example, it you have some Queue of Strings, and you need a specific String to mean "all done". Now, conceivably, you could use null or some weird String of Armenian characters, but maybe null is legal for your logic, and what if your software eventually gets used in Armenia? The clean way is
public final static String TERMINATOR = new String("Terminator"); // actual text doesn't matter ...
// then, some loop taking from the Queue
while (keepGoing) {
String s = myQueue.take();
if (s == TERMINATOR)
keepGoing = false;
else
// normal processing of s
}
If the client puts "Terminator" on the Queue, it will get processed. So you do not prevent them from using "Terminator". But if the client puts ThatQueueClass.TERMINATOR onto the Queue, it will get shut down.
In java there is a concept of String literal pool.To cut down the number of String objects created in the JVM, the String class keeps a pool of strings. Each time your code create a string literal, the JVM checks the string literal pool first. If the string already exists in the pool, a reference to the pooled instance returns. If the string does not exist in the pool, a new String object instantiates, then is placed in the pool.
String str1 = "Hello";
String str2 = "Hello";
System.out.print(str1 == str2);
Prints True.
If you do :
String str1 = "Hello";
String str2 = new String("Hello");
System.out.print(str1 == str2);
Prints False.
because, String object is created out of the String literal pool.
String str = new String("Hello");
Normally I have read, in many articles available on internet, that two objects are created when we write the statement above. One String object is created on the heap and one string object is created on the Literal Pool. And the heap object is also referring the object created on Literal Pool. (Please correct this statement of mine if it is wrong.)
Please note that the above explanation is as per my understanding after reading some articles on internet.
So my question is.. Are there any ways available to stop creating the string object in literal pool. How it can be done?
[Please let me know about the best link for understanding of this Literal Pool, How is it implemented]
There's only ever be one string with the contents "Hello" in the literal pool. Any code which uses a string constant with the value "Hello" will share a reference to that object. So normally your statement would create one new String object each time it executed. That String constructor will (IIRC) create a copy of the underlying data from the string reference passed into it, so actually by the time the constructor has completed, the two objects will have no references in common. (That's an implementation detail, admittedly. It makes sense when the string reference you pass in is a view onto a larger char[] - one reason for calling this constructor is to avoid hanging onto a large char[] unnecessarily.)
The string pool is used to reduce the number of objects created due to constant string expressions in code. For example:
String a = "Hello";
String b = "He" + "llo";
String c = new String(a);
boolean ab = a == b; // Guaranteed to be true
boolean ac = a == c; // Guaranteed to be false
So a and b refer to the same string object (from the pool) but c refers to a different object.
If I understand your question correctly, you're asking how to initialize a string without placing it in the string literal pool. You can avoid this as long as you don't declare a string literal expression (don't declare a series of characters in double quotes.)
// these two strings will be placed in the string literal pool
String one = "one";
String two = new String("two");
// this third string will NOT be placed in the string literal pool
String three = new String(new char[] {'t', 'h', 'r', 'e', 'e'});
We normally create objects using the new keyword, like:
Object obj = new Object();
Strings are objects, yet we do not use new to create them:
String str = "Hello World";
Why is this? Can I make a String with new?
In addition to what was already said, String literals [ie, Strings like "abcd" but not like new String("abcd")] in Java are interned - this means that every time you refer to "abcd", you get a reference to a single String instance, rather than a new one each time. So you will have:
String a = "abcd";
String b = "abcd";
a == b; //True
but if you had
String a = new String("abcd");
String b = new String("abcd");
then it's possible to have
a == b; // False
(and in case anyone needs reminding, always use .equals() to compare Strings; == tests for physical equality).
Interning String literals is good because they are often used more than once. For example, consider the (contrived) code:
for (int i = 0; i < 10; i++) {
System.out.println("Next iteration");
}
If we didn't have interning of Strings, "Next iteration" would need to be instantiated 10 times, whereas now it will only be instantiated once.
Strings are "special" objects in Java. The Java designers wisely decided that Strings are used so often that they needed their own syntax as well as a caching strategy. When you declare a string by saying:
String myString = "something";
myString is a reference to String object with a value of "something". If you later declare:
String myOtherString = "something";
Java is smart enough to work out that myString and myOtherString are the same and will store them in a global String table as the same object. It relies on the fact that you can't modify Strings to do this. This lowers the amount of memory required and can make comparisons faster.
If, instead, you write
String myOtherString = new String("something");
Java will create a brand new object for you, distinct from the myString object.
String a = "abc"; // 1 Object: "abc" added to pool
String b = "abc"; // 0 Object: because it is already in the pool
String c = new String("abc"); // 1 Object
String d = new String("def"); // 1 Object + "def" is added to the Pool
String e = d.intern(); // (e==d) is "false" because e refers to the String in pool
String f = e.intern(); // (f==e) is "true"
//Total Objects: 4 ("abc", c, d, "def").
Hope this clears a few doubts. :)
We usually use String literals to avoid creating unnecessary objects. If we use new operator to create String object , then it will create new object everytime .
Example:
String s1=“Hello“;
String s2=“Hello“;
String s3= new String(“Hello“);
String s4= new String(“Hello“);
For the above code in memory :
It's a shortcut. It wasn't originally like that, but Java changed it.
This FAQ talks about it briefly. The Java Specification guide talks about it also. But I can't find it online.
String is subject to a couple of optimisations (for want of a better phrase). Note that String also has operator overloading (for the + operator) - unlike other objects. So it's very much a special case.
In Java, Strings are a special case, with many rules that apply only to Strings. The double quotes causes the compiler to create a String object. Since String objects are immutable, this allows the compiler to intern multiple strings, and build a larger string pool. Two identical String constants will always have the same object reference. If you don't want this to be the case, then you can use new String(""), and that will create a String object at runtime. The intern() method used to be common, to cause dynamically created strings to be checked against the string lookup table. Once a string in interned, the object reference will point to the canonical String instance.
String a = "foo";
String b = "foo";
System.out.println(a == b); // true
String c = new String(a);
System.out.println(a == c); // false
c = c.intern();
System.out.println(a == c); // true
When the classloader loads a class, all String constants are added to the String pool.
Well the StringPool is implemented using The Hashmap in java. If we are creating always with a new keyword its not searching in String Pool and creating a new memory for it which might be needed later if we have a memory intensive operation running and if we are creating all the strings with new keyword that would affect performance of our application. So its advisable to not to use new keywords for creating string because then only it will go to String pool which in turn is a Hashmap ,(memory saved , imagine if we have lots of strings created with new keyword ) here it will be stored and if the string already exists the reference of it(which would usually reside in Stack memory) would be returned to the newly created string.
So its done to improve performance .
Syntactic sugar. The
String s = new String("ABC");
syntax is still available.
You can still use new String("string"), but it would be harder to create new strings without string literals ... you would have to use character arrays or bytes :-) String literals have one additional property: all same string literals from any class point to same string instance (they are interned).
There's almost no need to new a string as the literal (the characters in quotes) is already a String object created when the host class is loaded. It is perfectly legal to invoke methods on a literal and don, the main distinction is the convenience provided by literals. It would be a major pain and waste of tine if we had to create an array of chars and fill it char by char and them doing a new String(char array).
Feel free to create a new String with
String s = new String("I'm a new String");
The usual notation s = "new String"; is more or less a convenient shortcut - which should be used for performance reasons except for those pretty rare cases, where you really need Strings that qualify for the equation
(string1.equals(string2)) && !(string1 == string2)
EDIT
In response to the comment: this was not intended to be an advise but just an only a direct response to the questioners thesis, that we do not use the 'new' keyword for Strings, which simply isn't true. Hope this edit (including the above) clarifies this a bit. BTW - there's a couple of good and much better answers to the above question on SO.
The literal pool contains any Strings that were created without using the keyword new.
There is a difference : String without new reference is stored in String literal pool and String with new says that they are in heap memory.
String with new are elsewhere in memory just like any other object.
Because String is an immutable class in java.
Now why it is immutable?
As String is immutable so it can be shared between multiple threads and we dont need to synchronize String operation externally.
As String is also used in class loading mechanism. So if String was mutable then java.io.writer could have been changed to abc.xyz.mywriter
TString obj1 = new TString("Jan Peter");
TString obj2 = new TString("Jan Peter");
if (obj1.Name == obj2.Name)
System.out.println("True");
else
System.out.println("False");
Output:
True
I created two separate objects, both have a field(ref) 'Name'. So even in this case "Jan Peter" is shared, if I understand the way java deals..