How String object is created from an literal? [duplicate] - java

If i write :
String s = new String("abc");
It creates an object of type String with the value "abc".
And if i write :
String s = "abc";
This also creates an object with value "abc".
How does without encountering new keyword, an object is created.
Also if i write:
s.append("def");
It creates two more string objects that is:
a. "abcdef"
b. "def"
So on encountering anything within double inverted commas make a new String object.
How does that happen?

It is called a String literal, and is specified in the JLS 3.10.5:
A string literal consists of zero or more characters enclosed in double quotes. Characters may be represented by escape sequences (§3.10.6) - one escape sequence for characters in the range U+0000 to U+FFFF, two escape sequences for the UTF-16 surrogate code units of characters in the range U+010000 to U+10FFFF.

"abc" is a String literal , defined by the specifications of the language.
Refer JLS 3.10.5:
A string literal consists of zero or more characters enclosed in double quotes. Characters may be represented by escape sequences (§3.10.6) - one escape sequence for characters in the range U+0000 to U+FFFF, two escape sequences for the UTF-16 surrogate code units of characters in the range U+010000 to U+10FFFF.
Suggested Reading:
Difference between string object and string literal.
Java String Pool
Also , read String is Really Special:
String literals are stored in a common pool. This facilitates sharing of storage for strings with the same contents to conserve storage. String objects allocated via new operator are stored in the heap, and there is no sharing of storage for the same contents.
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
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

In Java, when you do "hello", the java compiler creates a String Object similar to new String("hello"). This object is maintained in the String Pool (String#intern()).
SO doing String i = "hello". It checks if i exists in the pool by checking from String#intern(). If yes, it reuses it else it creates a new one and puts in the pool. See this for more info.

As all of them have answered "abc" is a String literal. And for your second part of question, i.e, why after executing statement s.append("def") two objects are created because in Java String is immutable.

Related

How new String() and normal String created ? String class in java (Confusion) [duplicate]

This question already has answers here:
Strange behavior with string interning in Java
(4 answers)
Closed 5 years ago.
I was reading about String in java and was trying to understand it.
At first, it was easy how String s1="11" and String s2=new String ("11") works(created) and I understood intern method also.
But I came across this example (Given by a friend) and made me confused about everything.
I need help to understand this.
String s1 = new String(new String("2")+new String("2"));
s1.intern();
String s2="22";
System.out.print(s1==s2); //=>true as output.
String s3 =new String (new String("2")+new String("2"));
s3.intern();
String s4="22";
System.out.print(s3==s4); //=>false as output.
Answer of this code is true and false.
Part for S1 and s2 was good and was true according to my understanding but the second part I didn't understand.
Hope someone can break the code line by line and help me understand.
s1.intern(); adds s1 to the pool of strings, therefore the string "22" is now in the pool of strings. Therefore when you write s2 = "22" that's the same "22" as s1 and thus s1 == s2.
s3.intern() does NOT add s3 to the pool of strings because the string "22" is already there.
s3.intern() does return that same "22" which is s1 BUT IT IS NOT USED. Therefore s3 is not equal s4.
In java exist the heap and the stack,
Heap is where all Objects are saved
stack is where vars are saved
Now also exist another kind of list for Strings and Integers (numbers)
As you know a String can be created in some ways like
like new String("word") or just = "word" when you use the first way you create a new object (heap) when you use the other you save the word in a stack of words (Java engenniers thought it would be good if you don't create manny objects or words are repeated so they created an special stack for words, same for Integers from 0 to 127) So as I said You have to know that there is an stack and a Heap look at this example
String wordOne ="hola";
String wordTwo = "hola";
String wordTres = "hola";
System.out.println(wordOne == wordTwo);
System.out.println(wordTres == wordTwo);
System.out.println(wordOne == wordTres);
String wordFour = new String("hola");
System.out.println(wordOne == wordFour);
Integer uno = 127;
Integer dos = 127;
System.out.println(uno == uno);
Integer tres = 128;
Integer cuatro = 128;
System.out.println(tres == cuatro);
String x = "word"; is saved in an special Stack
String y = new String("it is not");
But tbh I don't remeber so well the rules for tha stack, but in any case i recomend you to compare all words using wordX.equals(wordY)
An also numbers in objects could be compared using == from 0 to 127 but the same if you use objects use equals, although using numbers there is a better do to do it in spite of use equals, convert one number to a primitive value (the memory will be better)
When you are making string with new keyword,JVM will create a new string object in normal(non pool) heap memory and the literal will be placed in the string constant pool. In your case, The variable s1 will refer to the object in heap(non pool).
String s1 = new String(new String("2")+new String("2"));
But in the next line your are calling intern() method.
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.
Check Javadocs.
As "22" is not in string pool, a new string literal "22" will be created and a reference of it will be returned. When you are writing:
String s2="22";
it simply refers "22" in string pool. But calling s3.intern() will not create a new string literal as "22" exists in the pool. Check the Javadocs for intern() again. It says if exists in pool, then string from the pool is returned not reference. So, this time s3 references to a different object.
But s4 is referred to same object as s1,s2.
You can print the objects hashcode for checking if the are same or not. Like:
System.out.println(System.identityHashCode(s1));
Notice that the type String is capitalized and is not one of Java's 8 primitive types (int, boolean, double, char, etc.). This indicates that any instance of a String is an object that was built using the 'blueprint' of the class String. Because variables in Java that refer to objects only store the memory address where the actual object is stored, when you compare Strings with == it compares memory location.
String str1 = new String("hello");
String str2 = str1; //sets str1 and str2 pointing to same memory loc
if (str1 == str2){
//do stuff; the code will enter this if-statement in this case
}
The way to compare the values within objects in Java is with equals(), such as:
String str1 = new String("hello");
String str2 = new String("hello"); //str2 not same memory loc as str1
if (str1.equals(str2)){
//do stuff; the code will enter this if-statement in this case
}
This is a common error for beginners, since the primitive types are not objects and you CAN compare two ints for equality like:
int one = 1; //primitive types are NOT objects
int two = 2; //notice when I make an int, I don't have to say "new"
//which means a new **object**
if (int1 == int2) {
//do stuff; in this case the program will not enter this if-statement
}
It seems that you understand everything but the meaning of the very last line. See my comment on the last line.
String s1 = new String(new String("2")+new String("2")); //declare AND initialize s1 as a new String object
s1.intern();
String s2="22"; //declare a new variable s2 and point it to the same object that s1 is pointing to
System.out.print(s1==s2);
String s3 =new String (new String("2")+new String("2"));
s3.intern();
String s4="22";
System.out.print(s3==s4); //check if s3 and s4 are stored in the same memory location = FALSE
In java object1 == object2 means
that do object1 and object2 have the same address in memory?
object1.equals(object2)
means are they equal, for example do they have the same values of all fields?
So, For two Strings S1 and S2,
string1.equals(S2) means, do they have the same characters in the same sequence?
S1 == S1 means are string1 and string2 stored at the same address in memory?

How many objects will be created for String?

I know that When we use String literals as given below the String object is created in String pool (if it doesn't exist).
String str1= "hello";
String str2= "hello";
In above case only one string object will be created in pool.
But, when we use new keyword it always creates a new String object in heap memory (even though there is one in String pool)
String str3=new String("hello"); // here a new object will be created in heap.
Here, i have one confusion regarding how many objects will be created in below cases and where (pool or heap memory).
1) String s="Hello";
String s1 = new String ("Hello");
2) String s = new String("Hello");
String s1 = new String("Hello");
3) String s="Hello";
String s1=new String (s);
4) String s1 = new String ("Hello");
String s="Hello";
Every invocation of new String(...) will create a new instance. You can use String.intern() to get an instance from the pool.
String s="Hello";
String s1 = new String ("Hello");
System.out.println(System.identityHashCode(s)==System.identityHashCode(s1));
String si= new String ("Hello").intern();
String s1i = new String ("Hello").intern();
System.out.println(System.identityHashCode(si)==System.identityHashCode(s1i));
This prints false and true
We can account for memory in Java’s String objects in the same way as
for any other object, except that aliasing is common for strings.
The standard String
implementation has four instance variables: a reference to a character array (8 bytes)
and three int values (4 bytes each). The first int value is an offset into the character array;
the second is a count (the string length).
In terms of the instance variable names in
the drawing on the figure, the string that is represented consists of the characters
value[offset] through value[offset + count - 1]. The third int value in String
objects is a hash code that saves recomputation in certain circumstances.
Therefore, each String object uses a total of 40 bytes (16 bytes for
object overhead plus 4 bytes for each of the three int instance variables plus 8 bytes for
the array reference plus 4 bytes of padding).
This space requirement is in addition to
the space needed for the characters themselves, which are in the array. The space needed
for the characters is accounted for separately because the char array is often shared
among strings. Since String objects are immutable, this arrangement allows the implementation
to save memory when String objects have the same underlying value[].
String values and substrings.
A String of length N typically uses 40 bytes (for the
String object) plus 24 2N bytes (for the array that contains the characters) for a
total of 64 + 2N bytes. But it is typical in string processing to work with substrings, and
Java’s representation is meant to allow us to do so without having to make copies of the string's characters!
Source: Algorithms 4th Edition
How many objects are being created for your examples?
1) 4
2) 4
3) 3
4) 4
Note that each String object contains a char-array with the content of the string. So when creating a new String you actually create two objects.
1) 2) and 4)
Each line in your examples either creates a String in the pool which contains a char-array (therefore we have two objects) or create a new String which - again - contains a char-array. Note that in neither of these examples the strings share any of the content.
3)
This example is different since we use the first String (2 objects) to create the second String. In this case the second String will be a new object but it will use the very same char-array as the first one, therefore not creating a new one. This leads to a total of only 3 objects instead of 4.
One more example
String s1 = "Hello";
String s2 = "Hello";
In this case we will have only 2 objects, since s1 and s2 will both point to the same String object in the pool with the same char-array.

java String comparison in concat

package data;
public class A {
String s = "maew";
String s2 = s + "class";
String s1 = "maewclass";
System.out.println(s2 == s1);
}
}
but both will be in string constant pool and if with same content an object is created one more reference will not get created. s2 and s1 should point to same object in string constant pool.so answer should be true why its giving false
String constant pool is an internal java feature which you should never rely on. For instance the following code will produce "true"
String s1 = "Hello";
String s2 = "Hello";
boolean result = s1 == s2;
But the following code will produce "false":
String s1 = "Hello";
String s2 = new String("Hello");
boolean result = s1 == s2;
String constant pool behavior may change from one java version to another since it is an internal optimization feature. It shouldn't be relied on. In your case, I suspect because you used String s2 = s + "class"; it did create a new instance.
In any case any String comparison MUST be done with method equals() of class String
I haven't look at the documentation, just did my own testing and what i believe that the reason you are getting "false" is because your S2 was a result of concatenation of an object (s) and the other string.
If you run this code
// String s = "maew";
String s2 = "maew" + "class";
String s1 = "maewclass";
System.out.println(s2 == s1);
The it is indeed returning true. So I believe, that java is not keeping result of Object.toString + "string" in the stringpool.
String grima = "grima";
String gri = "grima";
if (grima == gri)
System.out.println("grima == gri"); // The message is displayed
Both variables refer to same "grima" in string constant pool.
String pndey = "pandey";
String pan = "pande";
pan = pan + "y"; // The value for pan will be resolved during runtime.
if (pndey == pan)
System.out.println("pndey == pan"); // The 2 references are different
Now in the second case if I change
pan = pan + "y"; to pan="pande" +"y", then "pndey == pan" message will be displayed, because the compiler resolves the literal during compilation time.
Now as per Java docs on string:
Literal strings within the same class (§8 (Classes)) in the same package (§7 (Packages)) represent references to the same String object (§4.3.1).
Literal strings within different classes in the same package represent references to the same String object.
Literal strings within different classes in different packages likewise represent references to the same String object.
Strings computed by constant expressions (§15.28) are computed at compile time and then treated as if they were literals.
Strings computed by concatenation at run time are newly created and therefore distinct.
The result of explicitly interning a computed string is the same string as any pre-existing literal string with the same contents.
You read more here: https://codingninjaonline.com/2017/09/18/stringstring-constant-pool-in-java/
you need to use s2.equals(s1) instead of == please go through link provided for more
here
Update :
When we create object its reference is placed in the string constant pool memory.
So in your case when program is run...
JVM finds the variable s2 which refers to s + "class" in which s is also referencing maew and will be placed in the string constant pool memory.Then it finds another variable s1 which is referring maewclass.
JVM finds two different string references so both the variables s2 and s1 will not be refer for same string (say..maewclass).
At point when class is loaded if two same values are passed it is will refer to previous object rather creating the new one...
String objects with same values will always refer to the same String object.
String s = "a";
String s2 = "a";
System.out.println(s.equals(s2)); //-------return true
System.out.println(s == s2); //-------return true
_____
s ------------------> | |
| "a" |
s2 ------------------> |_____|
^
|
___________|____________
| Heap |
| String Constant Pool |
|______________________|
String objects created using new operator will be different from literals
String s = "a";
String s2 = new String("a");
System.out.println(s.equals(s2)); //-------return true
System.out.println(s == s2); //-------return false

How to programmatically prove that String s = new String("abc") adds the literal String "abc" to the String pool

I was asked this question somewhere : In
String s=new String("abc");
how to programmatically prove that the String literal "abc" will be added to the String pool?
PS: I know the JLS says - All String literals(Strings enclosed between "") are added to the String pool.
Also, I looked at the Byte code generated, but in Byte code , I can see only Class Constants pool not Strings Constant pool.
You can use
s != s.intern()
which yields true.
Explanation: Assume "abc" was not in the string pool before calling s.intern(). Then s.intern() would add s to the string pool and both sides would be equal(reference equality ==).
E.g. this prints false:
String s2 = "x".concat("yz"); // "xyz" is not in the string pool, since it's calculated using a method
System.out.println(s2 != s2.intern());
Since both sides are not equal, "abc" was in the string pool before calling intern(), which proofs the claim. (reductio ad impossibilem)
Note: This does not work, if you assign the string literal directly by using String s = "abc";. However you could still create a new string using new String(s) in that case and work with the new string.

Is string Object Created in Heap if we use new String("abcd") [duplicate]

This question already has answers here:
How do I compare strings in Java?
(23 answers)
Closed 8 years ago.
String s1 = new String("anil");
String s2 = s1.toUpperCase();
String s3 = s1.toLowerCase();
System.out.println(s1 == s2);
System.out.println(s1 == s3);
if string object created in heap then both are false.But it gives false,true.
String s1 = new String("anil");
This statement creates a new object
And this ,
String s3 = s1.toLowerCase();
points the location of 1st object that is s1
And thats the reason you are getting true for second condition
Also see how java handles strings to get a clear understanding
Hope this helps!!
There are four String objects here:
the literal, created by the compiler and classloader
s1, created by new String()
s2, created by toUpperCase()
s3, created by toLowerCase().
No two of them are equal via the == operator.
Except that toLowerCase() may return the same object if it is already lowercase. There's nothing in the Javadoc about that, so any such behaviour in an implementation cannot be relied on.
Here S1 object will be created in heap. Its value is stored in the constant string pool.
S2 is String literal not an object. So first JVM will check whether the string is there in constant pool. If String is there constant pool it will not create new object. It will return reference of the object available.
Here the s1.toUpper will return "ANIL". "ANIL" is not in the constant pool. so new object will be created. and comparing it with s1 (using'==') give false.
Same for S3. But for S3 it wont create new object as "anil" is already there in constant pool.
so will return the reference of S1. So it gives true.
Study the following link
Study this
Case 1: String with Capital First Letter.
> String s1 = new String("Ajay")
String s2 = s1.toUpperCase()
String s3 = s1.toLowerCase()
System.out.println s1 == s2
System.out.println s1 == s3
false
false
Case 2: String with Small First Letter.
> String s1 = new String("ajay")
String s2 = s1.toUpperCase()
String s3 = s1.toLowerCase()
System.out.println s1 == s2
System.out.println s1 == s3
false
true
in Case 1, since the string has capital letter, converting to lowercase will yield a new object hence a new reference for it while in Case 2 small first letter after converting to lowercase will still point to the same object because the original object was same hence creating two references for the same object.
You can see the output from the Groovy Shell pretty clear.
If you look at the toLowerCase() method in String class.
It calls toLowerCase(Locale locale)
toLowerCase(Locale locale) inturn uses Character.toLowerCase(c)
Character.toLowerCase(c) in Character class has this comment -
#param ch the character to be converted.
#return the lowercase equivalent of the character, if any;
otherwise, the character itself.

Categories

Resources