Reputation: 1995
The second argument of the addFormDataPart call should be a string.
int privacyLevel = 0;
builder.addFormDataPart("privacy",privacyLevel);
However, since privacyLevel is an integer, it needs to be converted to String.
In the tutorial, he made the conversion by adding an empty String at the end of privacyLevel:
builder.addFormDataPart("privacy",privacyLevel+"");
I found this to be an unusual way of converting an int to string. And all the research I've done pointed me to traditional methods of conversion.
So does anyone have an explanation for this?
And is this even a "good practice"?
Upvotes: 0
Views: 1001
Reputation: 11969
You can also use the proper tool: Integer.toString(int)
: this might be easier to read as it clearly show your intent on getting a String
out of your int
.
int privacyLevel = 0;
builder.addFormDataPart("privacy", Integer.toString(privacyLevel));
When you use:
builder.addFormDataPart("privacy", "" + privacyLevel);
You are creating a new String from ""
and Integer.toString(privacyLevel)
, but there might be some optimization during compile time or at runtime:
""
and directly use Integer.toString(privacyLevel)
.+
operation by the String::concat
method. Said method may return the other String
when itself is empty, or return itself when the other String
is empty (in openjdk 8u232, the method is actually checking the length of other and always perform a concatenation).Now, to see what the compiler does, here is a simple code which does nothing extraordinary:
class Foobar {
public static void main(String[] args) {
int n = 1;
String s = n + "";
}
}
If you call javap -p Foobar.class
, you can see what the compiler did (with Java 11.0.6, Java 8 use a StringBuilder
):
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: (0x0009) ACC_PUBLIC, ACC_STATIC
Code:
stack=1, locals=3, args_size=1
0: iconst_1
1: istore_1
2: iload_1
3: invokedynamic #2, 0 // InvokeDynamic #0:makeConcatWithConstants:(I)Ljava/lang/String;
8: astore_2
9: return
LineNumberTable:
line 8: 0
line 9: 2
line 10: 9
Using Integer.toString
only change the invokedynamic
to invokestatic
:
3: invokestatic #2 // Method java/lang/Integer.toString:(I)Ljava/lang/String
The compiler does not try to be intelligent in this case and don't optimize "" + int
.
If you read Javadoc of java.lang.invoke.StringConcatFactory.makeConcatWithConstants(Lookup, String, MethodType, String, Object...)
, it references JLS 15.18.1 and JLS 5.1.11.
The JLS 15.18.1 explains the concatenation operation from String + Not a String:
If only one operand expression is of type String, then string conversion (§5.1.11) is performed on the other operand to produce a string at run time.
The JLS 5.1.11 explains how to convert an int
to String
:
A value x of primitive type T is first converted to a reference value as if by giving it as an argument to an appropriate class instance creation expression (§15.9):
If T is byte, short, or int, then use new Integer(x).
To answer your question:
I found this to be an unusual way of converting an int to string. And all the research I've done pointed me to traditional methods of conversion. So does anyone have an explanation for this? And is this even a "good practice"?
What's unusual in your case if the fact the String is after the number, rather than before (as in "privacyLevel: " + privacyLevel
), but that is not strange given the JLS 15.18.1.
I could not say it is a good practice, even though it is relative, but I'd say it is legacy practice born for the fact that Integer.toString
is not so old (I can't remember if it was added in Java 5 or 6) and that the easier way was to doing n + ""
or "" + n
.
I would personally favor Integer.toString
because I find n + ""
rather ugly. It might also be better in terms of performance due to the complexity of the conversion done otherwise. Luckily for you or my answer, someone did a JMH benchmark.
Last but not least, if you stick with concatenation, the result will depends on the version of compiler which will do the actual transformation:
StringBuilder
to generate an int' String.invokedynamic
and a lot of stuff harder (for me) to explain, but I assume it does its job and perform as well, if better, than StringBuilder
.Integer.toString
seems to be optimized in newer hotspot JVM (it is annotated @HotSpotIntrinsicCandidate
in Java 13).Upvotes: 1