java - Java通过添加一个空字符串将int变量转换为String?
问题描述
addFormDataPart调用的第二个参数应该是一个字符串。
int privacyLevel = 0;
builder.addFormDataPart("privacy",privacyLevel);
但是,由于privacyLevel 是一个整数,所以需要将其转换为String。
在教程中,他通过在privacyLevel 末尾添加一个空字符串来进行转换:
builder.addFormDataPart("privacy",privacyLevel+"");
我发现这是一种将 int 转换为字符串的不寻常方式。我所做的所有研究都指向了传统的转换方法。
那么有人对此有解释吗?这甚至是一种“好习惯”吗?
解决方案
您还可以使用适当的工具: Integer.toString(int)
: 这可能更容易阅读,因为它清楚地表明了您想要String
从int
.
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
更改invokedynamic
为invokestatic
:
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.1和JLS 5.1.11。
JLS 15.18.1解释了来自String + Not a String的连接操作:
如果只有一个操作数表达式是字符串类型,则对另一个操作数执行字符串转换(第 5.1.11 节)以在运行时生成字符串。
JLS 5.1.11解释了如何将 an转换int
为String
:
原始类型 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 使用 a
StringBuilder
来生成一个 int' 字符串。 - Java 11 的使用
invokedynamic
和很多(对我来说)更难解释的东西,但我认为它完成了它的工作并且表现得也比StringBuilder
. Integer.toString
似乎在较新的热点 JVM 中进行了优化(它@HotSpotIntrinsicCandidate
在 Java 13 中进行了注释)。
推荐阅读
- sql - 计算来自多个表的连接数
- arrays - 将链接二叉树转换为基于数组的二叉树
- c# - Unity 没有将组件变量识别为组件
- javascript - React Native中通过axios上传图片
- ruby-on-rails - Ruby on Rails 帮助了解如何查找方法的来源
- laravel - 如何在 yajra 数据表 laravel 中添加操作列
- ethereum - 如何从 Truffle 控制台与 OpenZeppelin 代理合约进行交互?
- reactjs - React useEffect 从数据库中获取数据但没有及时在组件中使用
- gatling - Gatling 脚本工作正常,但打印 jldLagartoDOMBuilderTagVisitor - Unclosed tag closed:
- c - 分配字符串与分配结构的字段