为什么使用 parseInt 时会警告使用 valueOf?

52

查看Integer.parseInt(String s, int radix)(Java 8,1.8.0_131)的源代码时,我发现以下注释块:

/*
* WARNING: This method may be invoked early during VM initialization
* before IntegerCache is initialized. Care must be taken to not use
* the valueOf method.
*/

虽然我理解第一部分关于IntegerCache的内容,但我不明白为什么会有关于valueOf的警告,以及在这个上下文中为什么要这样警告。

我知道valueOf()依赖于parseInt(),但我仍然不明白为什么会有这个警告。

有人能够解释一下这个注释究竟是在警告我什么(以及在哪些情况下不能使用valueOf),以及可能会发生什么问题吗?

编辑:

Integer.valueOf(int i)中的代码似乎自从下面评论中的另一个问题被问出来后已经更改了,它现在是

public static Integer valueOf(int i) {
    if (i >= IntegerCache.low && i <= IntegerCache.high)
        return IntegerCache.cache[i + (-IntegerCache.low)];
    return new Integer(i);
}

并且在此之前应该免于断言错误。


2
在Java8中,assert似乎没有被使用在Integer.valueOf()中。@Blasanka,请问您能解释一下重复投票的原因吗?或者能否指出与目标代码链接相同的代码? - baao
2个回答

54

有人能解释一下这个评论具体在警告我什么(以及不应该使用valueOf的上下文),以及可能出现什么问题吗?

Integer类创建和维护一个缓存,表示小整数值的Integer对象;默认情况下,范围为-128到127的值被覆盖(更多讨论在这里, 在这里,以及其他很多地方)。当其参数表示范围内的数字时,Integer.valueOf()将从此缓存返回一个对象。该评论警告说parseInt()不能依赖于valueOf(),因为前者可能会在该缓存填充之前被调用。

在这种情况下可能出现的错误行为没有指定,可能会因Java版本而异,但是可能的情况是会返回null或抛出异常(NullPointerException, IndexOutOfBoundsException, ...)。

无论如何,这是实现中的内部注释,而不是针对类Integer用户的注释。在任何用户代码运行时,必要的缓存初始化已经完成,并且可以完全依赖于Integer.valueOf()表现如其API文档所描述。

36

源代码(几乎)只是作为参考,javadoc中不包含该警告,因为它仅供Java本身的开发人员使用。

这可能是一个警告,因为有些问题或错误是由某些人使用valueOf方法编写parseInt方法所导致的,而在内部缓存初始化之前就可以调用parseInt方法。

换句话说,假设您没有更改Integer类,则该警告不是针对您的!


1
谢谢,顺便问一下,好问题——我之前不知道那个警告。 - user85421
如果你正在子类化 Integer,这绝对是你需要知道的事情。 - Isaac Rabinovitch
1
@IsaacRabinovitch 子类化 Integer 应该是不可能的(除非作弊),因为 Integer 类被声明为 final - user85421

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