I read from the blogs that internally java use StringBuilder to concat the String when we use + operator. I was just checking it and found some strange outputs.
public class StringDemo {
public static void main(String[] args) {
String a = "Hello World";
String b = "Hello World";
String c = "Hello";
String d = c + " World".intern();
String e = new StringBuilder().append(String.valueOf(c)).append(" World").toString().intern() ;
String f = new StringBuilder(String.valueOf(c)).append(" World").toString().intern();
System.out.println(a == b); // Line 1 Expected output true
System.out.println(a == d); // Line 2 Output is false
System.out.println(a == e); // Line 3 Output is true
System.out.println(a == f); // Line 4 Output is true
}
}
So i am using + operator to concat two strings c & " World" and then use intern() method to move String in the pool for String d.
As per my understanding java use StringBuilder, so now I use StringBuilder to concat the String and use intern() method for Strings e and f.
So if both the equivalent then address of both the String must be same but the output of Line 2 not matching with Line 4 & 5.
Thanks in advance for your valuable feedback.
How + internally works in JAVA
Here is my post on the same, give a read Compiler version : How String concatenation works in java.
And coming to your code inside
System.out.println(a == d);
That should be false only.
As per your understanding you are expecting true. No. Your understanding is wrong. There is a clear difference between
String d = c + " World".intern();
And
String d = (c + " World").intern();
In first line only "World" got interned and the second line "Hello World" got interned
When you do (c + " World").intern(), you'll see the output true.
Related
This question already has answers here:
Java String Concatenation with + operator
(5 answers)
Closed 3 years ago.
Consider the below code snippet -
public class Student {
public static void main(String args[]) {
int a = 3;
int b = 4;
System.out.println(a + b +" ");
System.out.println(a + b +" "+ a+b);
System.out.println(""+ a+b);
}
}
The output for the above snippet is coming as -
7
7 34
34
It is clear from the output that if we use String at first in the print statement then the integers are concatenated. But, if we use integer at first then the values are added and displayed.
Can someone please explain why is this behavior?
I even tried to look at the implementation of println() method in PrintStream class but could not figure out.
Actually it's not println() implementation who's causing that, this is Java way to treat the + operator when dealing with Strings.
In fact the operation is treated from left to right so:
If the string comes before int (or any other type) in the operation String conversion is used and all the rest of the operands will be treated as strings, and it consists only of a String concatenation operation.
If int comes first in the operation it will be treated as int, thus addition operation is used.
That's why a + b +" " gives 7 because Stringis in the end of the operation, and for other expressions a + b +" "+ a+b or ""+ a+b, the variables a and b will be treated as strings if the come after a String in the expression.
For further details you can check String Concatenation Operator + in Java Specs.
It has nothing to do with the implementation of println. The value of the expression passed to println is evaluated before println is executed.
It is evaluated left to right. As long as both operands of + are numeric, addition will be performed. Once at least one of the operands is a String, String concatenation will be performed.
System.out.println(a + b + " ");
// int + int int + String
// addition, concatenation
System.out.println(a + b + " " + a + b);
// int + int int + String Str+Str Str+Str
// addition, concat, concat, concat
System.out.println("" + a + b);
// String+int String+int
// concat, concat
First case:
System.out.println(a + b +" ");
In this order, a + b will first be evaluated as a int sum, then converted to a string when adding the space (the second + here is for string concatenation).
Second case:
System.out.println(a + b +" "+ a+b);
Here the first part will be int sum operation then converted to a string as we add the space (the 2nd + is for string concatenation), the rest will be string concatenation as the left operand is already a string.
Third case:
System.out.println(""+ a+b);
Same as 2nd.
Notes:
In order to change this behavior, just add parenthesis to force the int sum before the string concatenations.
This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
toUpperCase in Java does not work [duplicate]
(5 answers)
Closed 6 years ago.
I want to change a string literal into all-uppercase one. Here is my code:
// a and b are the same literal
String a = "Test";
String b = "Test";
// now I want to change all b's letter
// into uppercases, but fail.
b.toUpperCase();
System.out.println("a = " + a + ", " + "b = " + b);
// print: a = Test, b = Test
String c = "Test1";
System.out.println("c = " + c + " , c.toUpperCase() = "
+ c.toUpperCase());
// print: c = Test1 , c.toUpperCase() = TEST1
// change letters of "Test" literal
// into uppercase and success
System.out.println("Test".toUpperCase());
// print: TEST
My question is:
1. b can't be changed into uppercase one, but c and "Test" can. Why?
What I know is:
1. a and b reference to the same object in string pool.
2. String is immutable, but it seems not relevant to this question.
Strings are immutable. So for change b:
b = b.toUpperCase();
Every time then you do something that changes a String, a new String object is created. So you need change the reference on object.
String is immutable, but it seems not relevant to this question
Actually, it's very relevant to the question
b can't be changed into uppercase one
Because toUpperCase() returns a new string by acting on the invoking string , use
b = b.toUpperCase();
c and "Test" can. Why?
c has not been changed it's result has been added to the string in System.out.println()
Let's take your code line by line and please read my comments :
// a and b are the same literal
/* FIRST POINT :
Here you assigned two times the same value "Test",
BUT IT'S 2 DIFFERENT OBJECTS IN MEMORY */
String a = "Test";
String b = "Test";
// now I want to change all b's letter
// into uppercases, but fail.
/* SECOND POINT :
Here you just apply a function (toUpperCase()) on "b" object.
This function returns a string object but
YOU ARE NOT DOING ANYTHING WITH IT
i.e. displaying it or reassigning it to another variable!
*/
b.toUpperCase();
System.out.println("a = " + a + ", " + "b = " + b);
// THAT'S WHY IT STILLS PRINT
// print: a = Test, b = Test
String c = "Test1";
System.out.println("c = " + c + " , c.toUpperCase() = "
+ c.toUpperCase());
/* THIRD POINT :
Here you apply a function (toUpperCase()) on "c" object but this time
YOU ARE REUSING THE RETURN STRING :)
i.e. you are displaying it!
*/
// print: c = Test1 , c.toUpperCase() = TEST1
// change letters of "Test" literal
// into uppercase and success
/* LAST POINT :
Here you do the same as you did before on "c" object
YOU ARE REUSING THE RETURN STRING AGAIN :)
i.e. you are displaying it!
*/
System.out.println("Test".toUpperCase());
// print: TEST
Last but not least calling toUpperCase()/toLowerCase() functions on string objects will never reassign the object's value. These functions only RETURN a string.
The way to reassign the string value is the usual way :
String a = "Test";
a = a.toUpperCase();
Please note, as many said, that this will create another object in memory "TEST" and assign it to "a" and your old string "Test" will then become a candidate to the garbage collector.
I hope it makes more sense now.
Cheers,
What happens when a string literal is changed?
Nothing. That is the string literal object cannot change, because as you point out you already know, it is immutable. References to it (variables like a,b,c) can be made to reference other strings, but that string instance will not change from "Test".
But to explain your code:
This is the difference between b and c:
b.toUpperCase(); //there's a result from this function you are not using
System.out.println("b = " + b);
System.out.println("c = " + c.toUpperCase()); //you're using the result here.
String is immutable, but it seems not relevant to this question
It is relevant, if you know that it is immutable, it is obvious that b cannot change to upper case and that a new string must be created as a result of toUpperCase and you must therefore use that. However b can be made to reference the new string, and this wont affect a or anything else which still references the old string:
b = b.toUpperCase(); //b now is set to the new upper case string
System.out.println("b = " + b);
My question is: 1. b can't be changed into uppercase one, but c and "Test" can. Why?
My answer is when you print c.toUpperCase(), variable c is not changed at all.
You merely returned the another String which was built to uppercase based on the content of c.
The same applies to String "test" as well.
Even if you do this, you are only pointing c to a new String:
String c = "Test1";
c = c.toUpperCase();
This is what happened:
//String c = "Test1";
+-------+
|"Test1"| <--- c
+-------+
//c = c.toUpperCase();
+-------+
|"TEST1"| <--- c
+-------+
+-------+
|"Test1"| <--- waiting to be collected by Garbage collector
+-------+
You need to change like this,because strings are immutable
public static void main(String[] args) {
// a and b are the same literal
String a = "Test";
String b = "Test";
// now I want to change all b's letter
// into uppercases, but fail.
b= b.toUpperCase();
System.out.println("a = " + a + ", " + "b = " + b);
// print: a = Test, b = Test
String c = "Test1";
// c=c.toUpperCase();
System.out.println("c = " + c + " , c.toUpperCase() = "
+ (c=c.toUpperCase()));
// print: c = Test1 , c.toUpperCase() = TEST1
// change letters of "Test" literal
// into uppercase and success
System.out.println("Test".toUpperCase());
// print: TEST
I suggest you to look into the Java API. By using toUpperCase you will get a new Object of String. If you want to print out the variable with new text, you should assign the new object to the variable. In case of c, you're printing out the returned "new" content of the object. The variable c will be lower case anymore.
This question already has answers here:
String equals and == with String concatenation [duplicate]
(4 answers)
Closed 7 years ago.
String a = "abc";
String b = "abc";
System.out.println("Result .... " + a==b); // false
System.out.println(a==b); // true
1st print statement prints false and 2nd prints true, though ideally it has to be true. Why is it false in 1st print statement ?
System.out.println("Result .... " +a==b); -> the result string will be appended with 'a' and then compares with b so it results false.
Order of operations:
"Result .... " + a==b
is equivalent to
("Result .... " +a) == b
which will be false since the two strings are not the same reference.
The explanation for this is that the + addition operator has a higher precedence than == logical equivalence.
The expression a == b is returning true in your second statement due to interning, in which a and b actually refer to same string object.
Click here for a link to Oracle's table of operator precedence in Java.
Forgot checking equality by == in java. In Java this operation checks equality of object link. Additionally it is applicable for checking equality of simple numbers. You should use .equals method
String a = "abc";
String b = new String(a);
System.out.printLn(a == b);//false
System.out.println(a.equals(b));//true
Learn about operation order in java
It is because in "Result .... " +a==b it first add "Result .... " with a and then == to b. If you write like this "Result .... " +(a==b), then it will be OK.
In the first statement, you're comparing "Result .... " + a with b. In the second one, you're comparing a with b, hence the difference. Change your first statement as follows:
System.out.println("Result .... " + (a==b));
And keep in mind that strings should be compared using the equals() method instead of ==.
System.out.println("Result .... " +a==b);
String Result is appended with 'a' and then compares with b so it provides false. (Result .... a == b) which is false.
Follow this link to understand precedence of operators in java and this.
Operator + has more precedence than == operator.
try adding brackets, you will see the diff. Bracket is evaluated separately.
public static void main(String[] args) {
String a = "abc";
String b = "abc";
System.out.println("Result .... " + (a == b)); // false
System.out.println(a == b); // true}
}
output
Result .... true
true
This question already has answers here:
How do I compare strings in Java?
(23 answers)
Closed 9 years ago.
I have this code which I cannot understand. In the beginning you can see two identical Strings, and when I compare them with use of operator == it says it is true, same as equals() method, but when I create two identical strings during runtime operator == says false. Why is this happening ?
Does it mean that when I hardcode identical strings they are placed in the same position in the memory and both references point to it? I found similar question, but there were no explicit answer.
public class StringTesting {
public static void main(String[] args){
String string1 = "hello"; //\
// } same place in the memory ?
String string2 = "hello"; ///
System.out.println(string1 == string2); //true
System.out.println(string1.equals(string2)); //true
String string3 = "hey";
String string4 = "he";
System.out.println(string3 == string4); //false
System.out.println(string3.equals(string4)); //false
string4 += "y";
System.out.println(string3 == string4); //false ????
System.out.println(string3.equals(string4)); //true
System.out.println(string3 + " " + string4); //hey hey
}
}
The following compound assignment operator:
string4 += "y";
performs String concatenation at runtime. Since the value of string4 is evaluated at runtime only. And String concatenation done at runtime creates a new object.
From JLS Section 3.10.5 (See towards the end of this section):
Strings computed by concatenation at run time are newly created and therefore distinct.
However if you perform concatenation of two string literals, it won't create a different objects. So the following code will return true:
"he" + "y" == "hey";
That JLS section contains code segment for various string concatenation example:
String hello = "Hello",
String lo = "lo";
System.out.print((hello == "Hello") + " "); // true
System.out.print((Other.hello == hello) + " "); // true
System.out.print((other.Other.hello == hello) + " ");// true
System.out.print((hello == ("Hel" + "lo")) + " "); // true
System.out.print((hello == ("Hel" + lo)) + " "); // false
System.out.println(hello == ("Hel" + lo).intern()); // true
string4 += "y"; creates a new object.
String literals however are placed in the same place in memory as an optimization (this is called string interning).
string1, string2, and string3 are all string constants. i.e., they appear as constant pool entries in the .class file. In Java, string constants are interned.
string4 is a new string, created by taking the string constant "he" and then appending "y". Therefore, it's not a string constant, and is not interned.
That is why string3 != string4.
Here's the problem. This code:
String a = "0000";
System.out.println(a);
char[] b = a.toCharArray();
System.out.println(b);
returns
0000
0000
But this code:
String a = "0000";
System.out.println("String a: " + a);
char[] b = a.toCharArray();
System.out.println("char[] b: " + b);
returns
String a: 0000
char[] b: [C#56e5b723
What in the world is going on? Seems there should be a simple enough solution, but I can't seem to figure it out.
When you say
System.out.println(b);
It results in a call to print(char[] s) then println()
The JavaDoc for print(char[] s) says:
Print an array of characters. The characters are converted into bytes
according to the platform's default character encoding, and these
bytes are written in exactly the manner of the write(int) method.
So it performs a byte-by-byte print out.
When you say
System.out.println("char[] b: " + b);
It results in a call to print(String), and so what you're actually doing is appending to a String an Object which invokes toString() on the Object -- this, as with all Object by default, and in the case of an Array, prints the value of the reference (the memory address).
You could do:
System.out.println("char[] b: " + new String(b));
Note that this is "wrong" in the sense that you're not paying any mind to encoding and are using the system default. Learn about encoding sooner rather than later.
Use
System.out.println("char[] b: " + Arrays.toString(b));
The gibrish you get is the Class name followed by the memory address of the object. Problem occurs when you try to append b with a string char[] b: in this case the char array b.toString() method is called thus [C#56e5b723 is printed.
[ indicates that it is an array
C indicates the class in this case char
#56e5b723 indicates the memory location
System.out.println("char[] b: " + b);
This is just like
System.out.println(("char[] b: " + b.toString());
You can look up "Object.toString()"
An array's toString() method (which is what's called when you do "..." + b) is only meant to give debugging output. There isn't a special case where a char[]'s toString() will give you the original string - arrays of all types have the same toString() implementation.
If you want to get the original string from the char array, use:
String a2 = new String(b);
Use
3:e row!
Scanner input = new Scanner(System.in);
char[] txt = input.next().toCharArray();
System.out.println((char[])txt);
private void print(char[] arr) {
try {
PrintStream stream
= new PrintStream(System.out);
stream.println(arr);
stream.flush();
} catch (Exception e) {
e.printStackTrace();
}
}