AG_HIHI
AG_HIHI

Reputation: 1995

Java converting int variable to String by adding an empty string?

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.

enter image description here
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

Answers (1)

NoDataFound
NoDataFound

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:

  • Compiler can detect the "" and directly use Integer.toString(privacyLevel).
  • Compiler may replace the + 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:

  • You are using Android Studio, and what apply to vanilla Java may not completely apply here.
  • Java 8 use a StringBuilder to generate an int' String.
  • Java 11 use 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

Related Questions