【问题标题】:How is primitive type int actually converted to a String?原始类型 int 是如何实际转换为 String 的?
【发布时间】:2016-06-08 12:40:43
【问题描述】:

首先,我的问题是关于原始类型 int 如何能够在不是 Object 的情况下转换为 String,因此没有 toString() 方法来获取 String 值。

我很清楚您如何能够在 Java 中看似将原始类型 int 的变量“转换”为 String。我使用的最简单的方法是:

int x = 5;
String y = "" + x;

这很好用,但是我的问题如下:

由于原始类型 int 不是对象,因此没有任何方法,例如 toString() 方法,据我所知,为了获得变量的 String 值...值如何没有这种基本方法识别的变量?

【问题讨论】:

  • 这在自动装箱存在之前就已经成为可能。它只是内置在我想说的语言中。
  • 那么一个 int 是否被转换为一个 Integer 对象,该对象具有 toString() 方法使其能够通过自动装箱被识别为字符串?
  • 见 rgettman 的回答。它已转换,但严格来说不是自动装箱。

标签: java string int tostring


【解决方案1】:

这称为字符串转换JLS, Section 5.1.11,声明:

任何类型都可以通过字符串转换转换为String类型。

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

(其他类型)

  • 如果 T 是 byteshortint,则使用 new Integer(x)

然后通过字符串转换将这个引用值转换为String类型。

现在只需要考虑参考值:

  • 如果引用为null,则将其转换为字符串"null"(四个ASCII字符null)。

  • 否则,转换就像调用被引用对象的toString 方法一样执行,不带参数;但是如果调用toString方法的结果是null,则使用字符串"null"

所以,int 被转换为Integer,不是通过装箱转换,而是通过new Integer(x),然后调用toString()

从技术上讲,这不是拳击转换;字符串转换自 Java 诞生以来就一直在该语言中,在 Java 1.5 中添加了装箱转换。

【讨论】:

  • 实际上,JLS 描述的确切逻辑并不适用。相反,字符串转换 是通过调用String.valueOf() 来实现的,它具有处理原始值的重载。该实现实际上并没有创建Integer 的实例,这没关系,因为结果 与它具有的相同。
  • @Andreas JLS 确实声明“好像”,所以从技术上讲,不需要创建新的Integer,但有什么证明它正在生成您在回答中声明的调用?
  • 嗯,是的,我似乎找不到任何String.valueOf() 用于字符串转换 的示例,尽管这些方法正在将字符串转换为规范。 JLS 中的所有示例都用于字符串连接。至于那个,反汇编字节码就是使用StringBuilder.append()的证明。
  • 查看valueOf(int)的调用者,发现它们被PrintStreamPrintWriterprint(int)方法所使用,这是有道理的。
【解决方案2】:

您可以将valueOf 方法用于静态字符串 用于原始类型,例如int、double、float。一些代码:

int intValue  = 25;
String s = String.valueOf(intValue);

【讨论】:

  • 我知道 String 对象的 valueOf() 方法。我的问题是由于缺少 toString() 方法,原始类型 int 的值如何被识别。不过感谢您的回复。
  • @Nathangrad 被String.valueOf()的重载识别,当值为int时表示valueOf(int)。在您列出的情况下 ("" + x),它被 StringBuilder.append() 的重载识别,即 append(int)
  • @Andreas 你是否暗示当我在 String 旁边使用诸如 int 之类的原始类型以获取它的 String 值时隐含 StringBuilder.append() 方法?
  • @Nathangrad 我是说"" + x 被编译器转换为new StringBuilder().append("").append(x).toString()。如果您使用javap -c Xxx.class 反汇编字节码,您会看到。这就是 Java 编译器实现字符串连接的方式。
  • @Andreas 不管编译器转换成什么,x的值仍然需要通过StringBuilder.append()方法来获取。我试图了解如何从方法中检索 x 的值,而无需对其调用 toString() 方法,因为它不是对象。
【解决方案3】:

一般来说,int 值通过调用以下两种方法之一转换为String

对于其他原始值,使用这些方法的相应重载。

StringBuilder.append()

表达式"" + x被编译器实现为:

new StringBuilder().append("").append(x).toString()

x 声明为int,这意味着将调用采用int 参数的append() 的重载。

append(int) 的源代码 (Java 1.8.0_65) 是:

@Override
public StringBuilder append(int i) {
    super.append(i);
    return this;
}

super 调用导致:

public AbstractStringBuilder append(int i) {
    if (i == Integer.MIN_VALUE) {
        append("-2147483648");
        return this;
    }
    int appendedLength = (i < 0) ? Integer.stringSize(-i) + 1
                                 : Integer.stringSize(i);
    int spaceNeeded = count + appendedLength;
    ensureCapacityInternal(spaceNeeded);
    Integer.getChars(i, spaceNeeded, value);
    count = spaceNeeded;
    return this;
}

String.valueOf()

在不使用字符串连接的情况下将值转换为字符串时,通常通过调用String.valueOf() 来完成。对于 int 值,这意味着 valueOf(int)

public static String valueOf(int i) {
    return Integer.toString(i);
}

Integer.toString() 调用是:

public static String toString(int i) {
    if (i == Integer.MIN_VALUE)
        return "-2147483648";
    int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i);
    char[] buf = new char[size];
    getChars(i, size, buf);
    return new String(buf, true);
}

Integer.getChars()

如您所见,两者都是通过实际调用包私有方法 Integer.getChars(int i, int index, char[] buf) 来实现的。

它们实际上都没有创建Integer 的实例,尽管 JLS 暗示它会这样做。

【讨论】:

    猜你喜欢
    • 2013-06-19
    • 2012-12-06
    • 2022-01-11
    • 1970-01-01
    • 2016-05-20
    • 1970-01-01
    • 1970-01-01
    • 2011-08-20
    相关资源
    最近更新 更多