Java负int到十六进制和后退失败

Max*_*ler 8 java parsing hex signed decimal

public class Main3 {
    public static void main(String[] args) {
        Integer min = Integer.MIN_VALUE;
        String minHex = Integer.toHexString(Integer.MIN_VALUE);

        System.out.println(min + " " + minHex);
        System.out.println(Integer.parseInt(minHex, 16));
    }
}
Run Code Online (Sandbox Code Playgroud)

-2147483648 80000000
Exception in thread "main" java.lang.NumberFormatException: For input string: "80000000"
    at java.lang.NumberFormatException.forInputString(NumberFormatException.java:48)
    at java.lang.Integer.parseInt(Integer.java:459)
    at Main3.main(Main3.java:7)
Run Code Online (Sandbox Code Playgroud)

这是怎么回事?

小智 12

据记载,它将Integer.toHexString整数的字符串表示形式返回为无符号值 - 同时Integer.parseInt采用带符号的int.如果你使用,Integer.toString(value, 16)你会得到你想要的.


Ala*_*ore 12

这总是令我恼火的事情.如果使用十六进制文字初始化int,则可以使用最大范围的正值0xFFFFFF; 任何大于0x7FFFFF真的都是负值.这对于位掩码和其他操作非常方便,您只关心位的位置,而不是它们的含义.

但是,如果使用Integer.parseInt()将字符串转换为整数,"0x7FFFFFFF"则将大于的值视为错误.可能有一个很好的理由为什么他们这样做,但它仍然令人沮丧.

最简单的解决方法是使用Long.parseLong()代替,然后将结果转换为int.

int n = (int)Long.parseLong(s, 16);
Run Code Online (Sandbox Code Playgroud)

当然,如果您确定该数字将在该范围内,您应该只这样做Integer.MIN_VALUE..Integer.MAX_VALUE.


Syl*_*oux 6

根据文档,toHexString返回"整数参数的字符串表示形式为基数为16 的无符号整数".

因此,正确的反向操作可能Integer.parseUnsignedInt是作为Java 8的一部分引入的:

public class Main3 {
    public static void main(String[] args) {
        Integer min = Integer.MIN_VALUE;
        String minHex = Integer.toHexString(Integer.MIN_VALUE);

        System.out.println(min + " " + minHex);
        System.out.println(Integer.parseUnsignedInt(minHex, 16));
    }
Run Code Online (Sandbox Code Playgroud)