String valueOf vs concatenation with empty string
public void foo(){
int intVar = 5;
String strVar = intVar+"";
}
This approach uses StringBuilder to create resultant String
public void foo();
Code:
0: iconst_5
1: istore_1
2: new #2; //class java/lang/StringBuilder
5: dup
6: invokespecial #3; //Method java/lang/StringBuilder."<init>":()V
9: iload_1
10: invokevirtual #4; //Method java/lang/StringBuilder.append:(I)Ljava/lan
g/StringBuilder;
13: ldc #5; //String
15: invokevirtual #6; //Method java/lang/StringBuilder.append:(Ljava/lang/
String;)Ljava/lang/StringBuilder;
18: invokevirtual #7; //Method java/lang/StringBuilder.toString:()Ljava/la
ng/String;
21: astore_2
22: return
public void bar(){
int intVar = 5;
String strVar = String.valueOf(intVar);
}
This approach invokes simply a static method of String
to get the String version of int
public void bar();
Code:
0: iconst_5
1: istore_1
2: iload_1
3: invokestatic #8; //Method java/lang/String.valueOf:(I)Ljava/lang/Stri
ng;
6: astore_2
7: return
which in turn calls Integer.toString()
String.valueOf(someVar) vs ( + someVar)
When you do ""
that is not going to create an Object. It is going to create a String literal. There is a differenc(How can a string be initialized using " "?) actually.
Coming to your actual question,
From String concatenation docs
The Java language provides special support for the string concatenation operator ( + ), and for conversion of other objects to strings. String concatenation is implemented through the StringBuilder(or StringBuffer) class and its append method.
So unnecissarly you are creating StringBuilder object and then that is giving another String object.
However valueOf directly give you a String object. Just go for it.
Besides the performance, just think generally. Why you concatenating with empty string, when actually you want to convert the int to String :)
Why is String concatenation faster than String.valueOf for converting an Integer to a String?
As you've mentioned, HotSpot JVM has -XX:+OptimizeStringConcat
optimization that recognizes StringBuilder pattern and replaces it with highly tuned hand-written IR graph, while String.valueOf()
relies on general compiler optimizations.
I've found the following key differences by analyzing the generated assembly code:
- Optimized concat does not zero
char[]
array created for the result string, while the array created byInteger.toString
is cleared after allocation just like any other regular object. - Optimized concat translates digits to chars by simple addition of '0' constant, while
Integer.getChars
uses table lookup with the related array bounds check etc.
There are other minor differences in the implementation of PhaseStringOpts::int_getChars
vs. Integer.getChars
, but I guess they are not that significant for performance.
BTW, if you take a bigger number (e.g. 1234567890), the performance difference will be negligible because of an extra loop in Integer.getChars
that converts two digits at once.
String Concatenation - valueOf or not
When we concatenate strings, the compiler actually translates it to StringBuffer.append().
The underlying implementations for StringBuffer.append(int) and String.valueOf(int) both eventually end up calling Integer.getChars(int,int,char[]) except that in case of String.valueOf()
, there is a call to Integer.toString(int)
first.
To conclude, for the given scenario, directly concatenating would be the way to go. But if you intend to be conscious about memory, then use string-builder to concatenate values first and then log it.
Why concatenate strings with an empty value before returning the value?
One is a String
, the other is char
. It's useful to always be dealing with a String
, rather than having to check if it's a char
.
java type-conversion String.valueOf( ) vs variable +
In Java the strings have the special operator + which is concatenation. If the operands of the concatenation are not strings their respective .toString method is called, and if it is the value is null the "null" string is concatenated. Most modern JITs or even compilers might decide to use a stringbuilder. So the only danger here is that you create extra objects which get discarded. Additionally, this code might be less readible or more confusing.
Is concatenating with an empty string to do a string conversion really that bad?
Your arguments are good; this is one of the more expressive areas of the Java language, and the "" +
idiom seems well entrenched, as you discovered.
See String concatenation in the JLS. An expression like
"" + c1 + c2
is equivalent to
new StringBuffer().append(new Character(c1).toString())
.append(new Character(c2).toString()).toString()
except that all of the intermediate objects are not necessary (so efficiency is not a motive). The spec says that an implementation can use the StringBuffer
or not. Since this feature is built into the language, I see no reason to use the more verbose form, especially in an already verbose language.
Add an empty string vs toString - why is it bad?
String s = "" + 123; // bad
String t = Integer.toString(456);
Will be compiled to:
String s = "123";
String t = Integer.toString(456);
so: "" +123 is obvious slightly better! Checked with JAD
public static void main(String args[])
{
// 0 0:ldc1 #16 <String "123">
// 1 2:astore_1
// 2 3:sipush 456
// 3 6:invokestatic #18 <Method String Integer.toString(int)>
// 4 9:astore_2
// 5 10:getstatic #24 <Field PrintStream System.out>
// 6 13:new #30 <Class StringBuilder>
// 7 16:dup
// 8 17:aload_1
// 9 18:invokestatic #32 <Method String String.valueOf(Object)>
// 10 21:invokespecial #38 <Method void StringBuilder(String)>
// 11 24:aload_2
// 12 25:invokevirtual #41 <Method StringBuilder StringBuilder.append(String)>
// 13 28:invokevirtual #45 <Method String StringBuilder.toString()>
// 14 31:invokevirtual #48 <Method void PrintStream.println(String)>
// 15 34:return
}
EDIT:
For non-constant values:
int i = 123;
String s = (new StringBuilder()).append(i).toString();
String t = Integer.toString(i);
System.out.println((new StringBuilder(String.valueOf(s))).append(t).toString());
public static void main(String args[])
{
// 0 0:bipush 123
// 1 2:istore_1
// 2 3:new #16 <Class StringBuilder>
// 3 6:dup
// 4 7:invokespecial #18 <Method void StringBuilder()>
// 5 10:iload_1
// 6 11:invokevirtual #19 <Method StringBuilder StringBuilder.append(int)>
// 7 14:invokevirtual #23 <Method String StringBuilder.toString()>
// 8 17:astore_2
// 9 18:iload_1
// 10 19:invokestatic #27 <Method String Integer.toString(int)>
// 11 22:astore_3
// 12 23:getstatic #32 <Field PrintStream System.out>
// 13 26:new #16 <Class StringBuilder>
// 14 29:dup
// 15 30:aload_2
// 16 31:invokestatic #38 <Method String String.valueOf(Object)>
// 17 34:invokespecial #44 <Method void StringBuilder(String)>
// 18 37:aload_3
// 19 38:invokevirtual #47 <Method StringBuilder StringBuilder.append(String)>
// 20 41:invokevirtual #23 <Method String StringBuilder.toString()>
// 21 44:invokevirtual #50 <Method void PrintStream.println(String)>
// 22 47:return
}
How can an empty string plus an object equal a number
You are creating an object, v
, and overriding its valueOf()
method to return the integer 5. If an object does not have an explicit valueOf()
method defined, then valueOf()
returns the object itself. All built-in core objects in JavaScript override this method to return the appropriate value. For example, doing the following:
x = 5;
console.log(x)
is really doing:
console.log(x.valueOf()) // log the return value of x.valueOf()
You can read more about valueOf()
here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/valueOf
If you are asking about why the addition (+) operator returns an arithmetic addition (calling v.valueOf()) instead of concatenation, you need to refer to the ECAMScript specification for the answer. Section 11.6.1 talks about the addition operator. Here is the relevant bit:
- Let lprim be ToPrimitive(lval).
- Let rprim be ToPrimitive(rval).
- If Type(lprim) is String or Type(rprim) is String, then Return the String that is the result of concatenating ToString(lprim) followed by ToString(rprim)
- Return the result of applying the addition operation to ToNumber(lprim) and ToNumber(rprim).
It looks like the operands should be resolved into string types before number types, so your expression ''+v
should call v.toString()
first, and thus return foo
, right?
Actually, no. Because in step 5 and 6, both operands are resolved into their primitives first, and this resolution is done without "hint". When there is no hint passed to ToPrimitive, Objects return their default values, which is the return of the valueOf()
method. See section 9.1 for how Objects resolve into their primitives.
difference between String.valueOf(int) , `+` string operator and Integer.toString(int)
For the example you have given, the answer will really depend on the type of 'integer' you are using.
loadCity(countryName , countryId + "");
For an Integer
object this is equivelent to :
loadCity(countryName, countryId.toString() + "");
Whereas for an int
primitive, this code is equivelent to :
loadCity(countryName, String.valueOf(countryId) + "");
In either case, as ArjunShankar pointed out there is a good chance that the compiler has optimised your code anyway. So if your question is 'do I go back and refactor all my code?', then I would say 'don't sweat the small stuff'. But in the future use a more conventional approach to avoid the down votes.
Related Topics
Unit Testing with Mockito for Constructors
Byte Array to Short Array and Back Again in Java
Using Spring Resttemplate in Generic Method with Generic Parameter
How to Remove Accents from a Unicode String
Spring Web MVC - Validate Individual Request Params
What Is the Time Complexity Performance of Hashset.Contains() in Java
How to Test Abstract Class in Java with Junit
Java: Bufferedimage to Byte Array and Back
Why Functional Interfaces in Java 8 Have One Abstract Method
Enable Partial Compilation in Intellij Idea
Whats the Use of Saying <? Extends Someobject> Instead of <Someobject>
How to Determine the Ip of My Router/Gateway in Java
How to Securely Store Encryption Keys in Java
What Is an Instance Variable in Java
Getting Java.Lang.Reflect.Invocationtargetexception While Adding a Button to Layout
Differences Between Runtime/Checked/Unchecked/Error/Exception
How Can "This" of the Outer Class Be Accessed from an Inner Class