原始类型int是如何转换为字符串的?

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

我很清楚在Java中如何看似地将原始类型int变量转换为String。我使用最简单的方法是:
int x = 5;
String y = "" + x;

这很有效,但我的问题是:

由于原始类型int不是对象,因此没有任何方法,如toString()方法,而我所知道的是需要该方法才能获取变量的String值...那么在没有这个基本方法的情况下,如何识别变量的值呢?

1
这在自动装箱出现之前就已经是可能的了。我想这只是内置于语言中的。 - Pierre Henry
所以,一个 int 被转换成了一个 Integer 对象,该对象具有 toString() 方法,通过自动装箱可以将其识别为 String? - Nathangrad
1
请参考rgettman的回答。它已经被转换了,但严格来说并不是自动装箱。 - Pierre Henry
3个回答

11
这被称为字符串转换。JLS, Section 5.1.11指出:
任何类型都可以通过字符串转换转换为类型String。
原始类型T的值x首先被转换为引用值,就好像将其作为参数给适当的类实例创建表达式(§15.9)一样:
(其他类型)
然后,该引用值通过字符串转换转换为类型String。
现在只需要考虑引用值:
如果引用为 null,则会转换为字符串"null"(四个ASCII字符null)。否则,转换将按照调用无参数的引用对象的toString方法来执行。但是,如果调用toString方法的结果为null,则使用字符串"null"代替。
因此,int被转换为Integer,而不是通过装箱转换,而是通过new Integer(x),然后在其上调用toString()
从技术上讲,这不是装箱转换;字符串转换自Java语言发布之初就存在,在Java 1.5中添加了装箱转换。

实际上,JLS 描述的精确逻辑并没有被应用。相反,字符串转换是通过调用String.valueOf() 实现的,它有过载来处理原始值。该实现实际上并不创建Integer的实例,这是可以的,因为结果与实际上创建实例时一样。 - Andreas
@Andreas,JLS确实指出“好像”,所以在技术上并不需要创建新的Integer,但是有什么证据证明它正在生成你在答案中提到的调用呢? - rgettman
嗯,是的,我似乎找不到任何关于String.valueOf()用于字符串转换的例子,尽管这些方法实现了规范中的字符串转换。在JLS中所有的例子都是关于字符串拼接的。就字符串拼接而言,反汇编字节码可以证明使用了StringBuilder.append() - Andreas
检查 valueOf(int) 的调用者,发现它们被 PrintStreamPrintWriterprint(int) 方法使用,这是有道理的。 - Andreas

4
一般来说,将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;
}
< p > < code >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);
}
< p > 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)来完成这个操作的。

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


1

您可以使用valueOf方法将原始类型(如int、double、float)转换为静态字符串。以下是一些代码示例:

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

我知道String对象的valueOf()方法的价值。我的问题是,由于缺少toString()方法,如何识别原始类型int的值。但是感谢您的回复。 - Nathangrad
@Nathangrad е®ғиў«String.valueOf()зҡ„йҮҚиҪҪжүҖиҜҶеҲ«пјҢиҝҷж„Ҹе‘ізқҖеҪ“еҖјдёәintж—¶дҪҝз”ЁvalueOf(int)гҖӮеңЁжӮЁеҲ—еҮәзҡ„жғ…еҶө("" + x)дёӯпјҢе®ғиў«StringBuilder.append()зҡ„йҮҚиҪҪжүҖиҜҶеҲ«пјҢиҝҷж„Ҹе‘ізқҖдҪҝз”Ёappend(int)гҖӮ - Andreas
@Andreas,您是在暗示当我使用原始类型(如int)与字符串一起使用以获取其字符串值时,StringBuilder.append()方法是隐含的吗? - Nathangrad
1
@Nathangrad 我的意思是 "" + x 会被编译器转换为 new StringBuilder().append("").append(x).toString()。如果你使用 javap -c Xxx.class 来反汇编字节码,你就会看到这个过程。这就是 Java 编译器实现字符串拼接的方式。 - Andreas
@Andreas 无论编译器将其转换为什么,x的值仍然需要通过StringBuilder.append()方法获取。我试图理解如何从方法中检索x的值,而不必调用toString()方法,因为它不是一个对象。 - Nathangrad
@Nathangrad,正在调用toString()方法或其他类似的代码。请参见我的答案以获取更多详细信息。 - Andreas

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接