85

我有以下代码...

int Val=-32768;
String Hex=Integer.toHexString(Val);

这相当于ffff8000

int FirstAttempt=Integer.parseInt(Hex,16); // Error "Invalid Int"
int SecondAttempt=Integer.decode("0x"+Hex);  // Error "Invalid Int"

因此,最初,它将值 -32768 转换为十六进制字符串 ffff8000,但随后无法将十六进制字符串转换回整数。

它按.Net我的预期工作,并且returns -32768.

我知道我可以编写自己的小方法来自己转换它,但我只是想知道我是否遗漏了什么,或者这是否真的是一个错误?

4

10 回答 10

79
int val = -32768;
String hex = Integer.toHexString(val);

int parsedResult = (int) Long.parseLong(hex, 16);
System.out.println(parsedResult);

这就是你可以做到的。

它不能按您的方式工作的原因:Integer.parseInt采用带符号的 int,而toHexString产生无符号的结果。因此,如果您插入高于 的0x7FFFFFF内容,则会自动抛出错误。如果您将其解析为long,它仍将被签名。但是当你将它转换回 int 时,它会溢出到正确的值。

于 2012-08-17T12:12:00.473 回答
51

它溢出,因为数字是负数。

试试这个,它会工作:

int n = (int) Long.parseLong("ffff8000", 16);
于 2012-08-17T12:12:51.487 回答
30
  • int到十六进制:

    Integer.toHexString(intValue);
    
  • 十六进制到int

    Integer.valueOf(hexString, 16).intValue();
    

您可能还想使用long代替int(如果值不符合int界限):

  • 十六进制到long

    Long.valueOf(hexString, 16).longValue()
    
  • long到十六进制

    Long.toHexString(longValue)
    
于 2012-08-17T12:10:26.963 回答
11

值得一提的是,Java 8 有这些方法,Integer.parseUnsignedInt并且Long.parseUnsignedLong可以满足您的需求,具体来说:

Integer.parseUnsignedInt("ffff8000",16) == -32768

这个名字有点令人困惑,因为它从十六进制字符串中解析一个有符号整数,但它确实有效。

于 2016-03-04T19:09:38.227 回答
7

尝试使用 BigInteger 类,它可以工作。

int Val=-32768;
String Hex=Integer.toHexString(Val);

//int FirstAttempt=Integer.parseInt(Hex,16); // Error "Invalid Int"
//int SecondAttempt=Integer.decode("0x"+Hex);  // Error "Invalid Int"
BigInteger i = new BigInteger(Hex,16);
System.out.println(i.intValue());
于 2012-08-17T12:16:02.057 回答
6

由于 Integer.toHexString(byte/integer) 在您尝试转换有符号字节(如 UTF-16 解码字符)时不起作用,因此您必须使用:

Integer.toString(byte/integer, 16);

或者

String.format("%02X", byte/integer);

反向你可以使用

Integer.parseInt(hexString, 16);
于 2017-06-06T11:44:11.123 回答
3

Java的parseInt方法实际上是一堆吃“假”十六进制的代码:如果你想翻译-32768,你应该把绝对值转换成十六进制,然后在字符串前面加上'-'。

有一个 Integer.java 文件示例:

public static int parseInt(String s, int radix)

描述非常明确:

* Parses the string argument as a signed integer in the radix 
* specified by the second argument. The characters in the string 
...
...
* parseInt("0", 10) returns 0
* parseInt("473", 10) returns 473
* parseInt("-0", 10) returns 0
* parseInt("-FF", 16) returns -255
于 2012-08-17T12:16:15.807 回答
2

使用Integer.toHexString(...)是一个很好的答案。不过个人比较喜欢用String.format(...)

试试这个样本作为测试。

byte[] values = new byte[64];
Arrays.fill(values, (byte)8);  //Fills array with 8 just for test
String valuesStr = "";
for(int i = 0; i < values.length; i++)
    valuesStr += String.format("0x%02x", values[i] & 0xff) + " ";
valuesStr.trim();
于 2017-02-09T17:25:24.770 回答
2

下面的代码可以工作:

int a=-32768;
String a1=Integer.toHexString(a);
int parsedResult=(int)Long.parseLong(a1,16);
System.out.println("Parsed Value is " +parsedResult);
于 2019-02-23T15:13:01.423 回答
1

呵呵,好奇。我认为这是一个“故意的错误”,可以这么说。

根本原因是 Integer 类的编写方式。基本上, parseInt 针对正数进行了“优化”。当它解析字符串时,它会累积地构建结果,但会被否定。然后它翻转最终结果的符号。

例子:

66 = 0x42

解析为:

4*(-1) = -4
-4 * 16 = -64 (hex 4 parsed)

-64 - 2 = -66 (hex 2 parsed)

return -66 * (-1) = 66

现在,让我们看一下您的示例 FFFF8000

16*(-1) = -16 (first F parsed)
-16*16 = -256 

-256 - 16 = -272 (second F parsed)
-272 * 16 = -4352 

-4352 - 16 = -4368 (third F parsed)
-4352 * 16 = -69888

-69888 - 16 = -69904 (forth F parsed)
-69904 * 16 = -1118464 

-1118464 - 8 = -1118472 (8 parsed)
-1118464 * 16 = -17895552 

-17895552 - 0 = -17895552 (first 0 parsed)
Here it blows up since -17895552 < -Integer.MAX_VALUE / 16 (-134217728). 
Attempting to execute the next logical step in the chain (-17895552 * 16)
would cause an integer overflow error.

编辑(添加):为了使 parseInt() 能够“一致地”为 -Integer.MAX_VALUE <= n <= Integer.MAX_VALUE 工作,他们必须在达到 -Integer.MAX_VALUE 时实现逻辑“旋转”累积结果,从整数范围的最大值开始并从那里继续向下。他们为什么不这样做,必须先询问 Josh Bloch 或最初实施它的人。这可能只是一个优化。

然而,

Hex=Integer.toHexString(Integer.MAX_VALUE);
System.out.println(Hex);
System.out.println(Integer.parseInt(Hex.toUpperCase(), 16));

工作得很好,正是因为这个原因。在 Integer 的源代码中,您可以找到此评论。

// Accumulating negatively avoids surprises near MAX_VALUE
于 2012-08-17T13:01:20.913 回答