首页 > 解决方案 > Java通过添加一个空字符串将int变量转换为String?

问题描述

addFormDataPart调用的第二个参数应该是一个字符串。

 int privacyLevel = 0;
 builder.addFormDataPart("privacy",privacyLevel);

但是,由于privacyLevel 是一个整数,所以需要将其转换为String。

在此处输入图像描述
在教程中,他通过在privacyLevel 末尾添加一个空字符串来进行转换:

builder.addFormDataPart("privacy",privacyLevel+"");

我发现这是一种将 int 转换为字符串的不寻常方式。我所做的所有研究都指向了传统的转换方法。
那么有人对此有解释吗?这甚至是一种“好习惯”吗?

标签: javaandroid-studio

解决方案


您还可以使用适当的工具: Integer.toString(int): 这可能更容易阅读,因为它清楚地表明了您想要Stringint.

int privacyLevel = 0;
builder.addFormDataPart("privacy", Integer.toString(privacyLevel));

当您使用:

builder.addFormDataPart("privacy", "" + privacyLevel);

您正在从""and创建一个新的 String Integer.toString(privacyLevel),但在编译时或运行时可能会有一些优化:

  • 编译器可以检测到""并直接使用Integer.toString(privacyLevel)
  • 编译器可以+通过方法替换操作String::concat。所述方法可能String在自身为空时返回另一个,或者在另一个 String为空时返回自身(在openjdk 8u232中,该方法实际上是检查其他的长度并且总是执行连接)。

现在,看看编译器做了什么,这里有一个简单的代码,它没有什么特别之处:

class Foobar {
  public static void main(String[] args) {
    int n = 1;
    String s = n + "";
  }
}

如果你调用javap -p Foobar.class,你可以看到编译器做了什么(Java 11.0.6,Java 8 使用 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

仅使用Integer.toString更改invokedynamicinvokestatic

3: invokestatic  #2                  // Method java/lang/Integer.toString:(I)Ljava/lang/String

在这种情况下,编译器不会尝试变得智能并且不会优化"" + int.

如果您阅读 的 Javadoc java.lang.invoke.StringConcatFactory.makeConcatWithConstants(Lookup, String, MethodType, String, Object...),它会引用JLS 15.18.1JLS 5.1.11

JLS 15.18.1解释了来自String + Not a String的连接操作:

如果只有一个操作数表达式是字符串类型,则对另一个操作数执行字符串转换(第 5.1.11 节)以在运行时生成字符串。

JLS 5.1.11解释了如何将 an转换intString

原始类型 T 的值 x 首先被转换为引用值,就好像通过将其作为参数提供给适当的类实例创建表达式(第 15.9 节):

If T is byte, short, or int, then use new Integer(x).

要回答您的问题:

我发现这是一种将 int 转换为字符串的不寻常方式。我所做的所有研究都指向了传统的转换方法。那么有人对此有解释吗?这甚至是一种“好习惯”吗?

如果 String 位于数字之后而不是之前(如 中"privacyLevel: " + privacyLevel),那么在您的情况下有什么不寻常之处,但鉴于JLS 15.18.1这并不奇怪。

我不能说这是一个很好的做法,即使它是相对的,但我会说它是为不太老的事实而诞生的遗留Integer.toString做法(我不记得它是在 Java 5 还是 6 中添加的)并且更简单的方法是做n + ""or "" + n

我个人会赞成Integer.toString,因为我觉得n + ""很丑。由于转换的复杂性,它在性能方面也可能更好。幸运的是,对于您或我的回答,有人做了JMH 基准测试

最后但并非最不重要的一点是,如果您坚持使用连接,结果将取决于执行实际转换的编译器版本:

  • 您正在使用 Android Studio,适用于 vanilla Java 的内容可能并不完全适用于此。
  • Java 8 使用 aStringBuilder来生成一个 int' 字符串。
  • Java 11 的使用invokedynamic和很多(对我来说)更难解释的东西,但我认为它完成了它的工作并且表现得也比StringBuilder.
  • Integer.toString似乎在较新的热点 JVM 中进行了优化(它@HotSpotIntrinsicCandidate在 Java 13 中进行了注释)。

推荐阅读