public class Strings
{
public static void main(String ads[])
{
String a = "meow";
String ab = a + "deal";
String abc= "meowdeal";
System.out.println (ab==abc);
}
}
why output is false?
In this program ab is created in string literal and then abc created but why ab and abc not refer to the same memory in string constant pool ,because before creating abc it search in string constant pool for String meowdeal.
Java only pools strings it knows about at compile time; string constants and constant string expressions. a is a local variable, so a + "deal" is a string expression that isn't evaluated until runtime (even though you looking at it can see that it should be constant). The Java compiler doesn't know it's a constant expression, and doesn't put it in the pool. It performs the string concatenation at runtime, resulting in a different object than any in the pool.
I'll explain what's happening:
public class Strings {
public static void main(String ads[]) {
String a = "meow"; // new string created
String ab = a + "deal"; // again a new string created. Reference different.
String abc = "meowdeal"; // a whole new string.
System.out.println(ab == abc);// even though the values are same, reference is different. For value equality, use .equals()
}
}
Your question implies that you expect Java to check the result of every string concatenation to see if there is a matching string in the string constant pool - but this would be grossly inefficient. String concats are always new objects unless all the strings are compile-time constants.
If you really want to compare the strings using == you need to intern the constructed string like so:
ab=(a+"deal").intern();
However this would be for a very specific use case and very uncommon.
Note that this is a different case from when two constants are concatenated; given "ab"+"cd" the compiler is required to resolve the expression to "abcd" and pool the result. The same would be true if one or both of the values are compile-time constants, static final ....
Related
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.
Inherited an existing codebase, unable to contact original developer.
I understand that for a normal Java bean, you have variable declarations, getters and setters.
public class FooBean{
private String foo;
private String bar;
// getters and setters
}
However in this code, I notice that all the strings are initialised.
public class FooBean{
private String foo = new String();
private String bar = new String();
// getters and setters
}
The code that handles this bean doesn't have any particular special case and it seems to work exactly the same with the initialisations removed.
Is there a reason to create this way? Does it have some kind of side effect I'm not realising?
It doesn't prevent the fields from being set to null, so the same kind of value checking is required in either case.
It just gives an initial non null value.
But it would be better to write
private String foo = "";
private String bar = "";
since there is no need to create new String objects, better reuse the empty string instance from the string pool.
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.
Considering that there's no reason to use new String(); instead of "" (in this case, there can be some edge cases where you want distinct empty Strings), this is probably just a bad habit he's learned somewhere.
No, this doesn't really make sense. It's usually bad practice to use the String constructor over a simple literal "".
There is a small but important difference between foo = new String() and foo = "" though:
String foo1 = new String();
String bar1 = new String();
System.out.println(foo1 == bar1);
String foo2 = "";
String bar2 = "";
System.out.println(foo2 == bar2);
The output of this will be
false
true
foo2 and bar2 will point to the same literal and will therefore be 'equal' (in the sense of ==). See here for details.
You should never rely on this, though. Always use equals on strings
class helloworld
{
public static void main(String args[]) {
String str1="hello";
String str2="world";
String str=str1+str2;
str.intern();
System.out.println(str=="helloworld");
}
}
o/p: false
After Executing the program it produces false as output.if equals() is used instead of "==" it returns true.why so?
2.In this case after changing classname it produces true as output.
class main
{
public static void main(String args[]) {
String str1="hello";
String str2="world";
String str=str1+str2;
str.intern();
System.out.println(str=="helloworld");
}
}
o/p:true
Why the contradiction occurs b/w interned string comparison using "==" with classname (in case of comparison string name is used as classname)?
The reason is that in the first example, the string "helloworld" is already in the string pool, on account of its being the name of the class. So interning it doesn't add anything to the string pool. So str won't be the interned value, and the comparison will be false.
In the second example, str.intern() actually adds str to the string pool, because "helloworld" is not already there. Then, when the "helloworld" literal is encountered, the string object that's actually used is the one that's in the string pool. That's just str, so the comparison will be true.
String is immutable. You must use the return value of str.intern(). Just calling str.intern() and ignoring the return value does nothing.
str = str.intern();
Supplementing answers, here a nice articles about intern()
English: https://weblogs.java.net/blog/2006/06/26/all-about-intern
Russian: http://habrahabr.ru/post/79913/
String in an immutable Object. And as of intern() function as per javadoc
When the intern method is invoked, if the pool already contains a
string equal to this <code>String</code> object as determined by
the {#link #equals(Object)} method, then the string from the pool is
returned. Otherwise, this <code>String</code> object is added to the
pool and a reference to this <code>String</code> object is returned.
So you must assign the return value Eg string = string.intern();
As for your output it should be true irrespective of your class name because as mentioned above it has nothing to do with calling intern().
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Strings are objects in Java, so why don't we use 'new' to create them?
In Java, class objects are created like-
MyClass a=new MyClass();
then how String class objects are created like-
String a="Hello";
What does this "Hello" does to create new object?
String a = "Hello" doesn't actually create a new object. Instead, when the compiler sees a string literal like "Hello", it adds the string to the string literal pool, from which it will be loaded later.
Providing a String as a literal finally makes it in the String Literal Pool of the JVM. Quoting from this article:
String allocation, like all object allocation, proves costly in both time and memory. The JVM performs some trickery while instantiating string literals to increase performance and decrease memory overhead. 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. Java can make this optimization since strings are immutable and can be shared without fear of data corruption.For example:
public class Program
{
public static void main(String[] args)
{
String str1 = "Hello";
String str2 = "Hello";
System.out.print(str1 == str2);
}
}
The result is
true
Unfortunately, when you use
String a=new String("Hello");
a String object is created out of the String literal pool, even if an equal string already exists in the pool. Considering all that, avoid new String unless you specifically know that you need it! For example
public class Program
{
public static void main(String[] args)
{
String str1 = "Hello";
String str2 = new String("Hello");
System.out.print(str1 == str2 + " ");
System.out.print(str1.equals(str2));
}
}
The result is
false true
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.