Java Integer.valueOf 为范围内的有效数字生成 NumberFormatException

Java Integer.valueOf produces NumberFormatException for valid number within range

在Java,我打电话:

String chunkSizeAsString = responseString.split(DOUBLE_NEW_LINE)[1]
    .split(SINGLE_NEW_LINE)[0];
System.out.println("Trying to get integer value of '" + chunkSizeAsString + "'");
Integer chunkSize = Integer.valueOf(chunkSizeAsString, 16); // this is line 109

并得到输出:

Trying to get integer value of '8d'
Exception in thread "Thread-2" java.lang.NumberFormatException: For input string: "8d"
    at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
    at java.lang.Integer.parseInt(Integer.java:481)
    at java.lang.Integer.valueOf(Integer.java:556)
    at ProxyWorker.handleRequest(ProxyWorker.java:109)
    at ProxyWorker.run(ProxyWorker.java:41)
    at java.lang.Thread.run(Thread.java:745)

所以基本上,我打电话给 Integer.valueOf("8d", 16) 并收到一个 NumberFormatException。我见过很多例子,其中 OP 忘记指定正确的基数,或者结果数字超出了 Integer、Long 等的范围。但是 0x8d = 141,这在 Integer 的范围内很舒服。

所以我的问题是,为什么会发生这种情况,我该如何解决?

N.B。如您所见,我正在通过一个异常的解析得到 chunkSizeAsString ("8d"),并且怀疑可能涉及不可见的字符。我已经使用第 109 行上方的以下添加项检查了 here, and "\p{C}" as mentioned here 中提到的“\u200e”和“\u200f”:

chunkSizeAsString = chunkSizeAsString.replaceAll("\u200e", "");
chunkSizeAsString = chunkSizeAsString.replaceAll("\u200f", "");
chunkSizeAsString = chunkSizeAsString.replaceAll("[^\p{Print}]", ""); 

但这并没有改变输出。

编辑: 我正在使用 jdk1.7.0_7,供应商是 'Oracle Corporation'。 谢谢 fge

编辑 2: 将 jdk 更新为 1.7u79 并意识到我需要从我正在 运行 和测试的服务器获取 java 供应商,而不是我的家庭开发环境:

java version "1.7.0_79"

OpenJDK Runtime Environment (fedora-2.5.5.0.fc20-x86_64 u79-b14)

OpenJDK 64-Bit Server VM (build 24.79-b02, mixed mode)

编辑 3: 根据建议,我做了一些完整性测试:

.valueOf 在下面使用 .parseInt,你可以做 int chunkSize = Integer.parseInt(chunkSizeAsString, 16);

阅读所有这些评论后,这里唯一有用的建议可能是 - 调试。不用担心,按 F7(或其他)进入 Integer.valueOf() 的实现,非常简单,您将立即 看看哪里出了问题。

在尝试对此进行了一定程度的调试之后,并且考虑到您的更新和堆栈跟踪(您在工作线程上的事实),我相信您在某种程度上将调试尝试与多线程问题。

将您的代码更改为:

private final AtomicInteger attemptCounter = new AtomicInteger(0);

void whateverYourMethodIsCalled(String responseString) {
    int attemptId = attemptCounter.incrementAndGet();
    System.out.format("Beginning attempt: %d%n", attemptId);
    String chunkSizeAsString = responseString.split(DOUBLE_NEW_LINE)[1]
        .split(SINGLE_NEW_LINE)[0];
    System.out.format("In attempt %d, trying to get integer value of '%s', which is length %d%n",
         attemptId, chunkSizeAsString, chunkSizeAsString.length());
    Integer chunkSize = Integer.valueOf(chunkSizeAsString, 16); // this is line 109
    System.out.format("Ending attempt: %d%n", attemptId);
}

最有可能发生的情况是,您第一次尝试工作正常,通过了调试用例,然后在稍后处理的 String 中抛出了错误。


对评论的回应:似乎正在发生的事情是,最初的提问者正在处理大量数据和大量案例。在一个特定的案例中,他得到了不可见的字符,但那不是问题发生的 第一次 时间,他混淆了问题与哪个特定案例是那个抛出问题。通过隔离产生问题的解析数据,@Tait 能够准确地调试/解析导致问题的原因,而不会被误报案例所抛弃。