Java将int转换为hex,然后再返回

我有以下代码…

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转换成一个hexstringffff8000,但它不能将hexstring转换回整数。

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

我知道我自己可以自己编写一些小的方法来转换,但是我只是想知道我是否错过了一些东西,或者这真的是一个错误?

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

试试这个,它会工作:

 int n = (int) Long.parseLong("ffff8000", 16); 
 int val = -32768; String hex = Integer.toHexString(val); int parsedResult = (int) Long.parseLong(hex, 16); System.out.println(parsedResult); 

这就是你如何做到的。

之所以没有按照你的方式工作: Integer.parseInt需要一个带符号的int,而toHexString会产生一个无符号的结果。 所以如果你插入高于0x7FFFFFF东西,就会自动抛出一个错误。 如果你parsing它,但是它仍然会被签名。 但是当你把它转换回int时,它会溢出到正确的值。

  • int到hex:

     Integer.toHexString(intValue); 
  • hex到int

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

你可能也想使用long而不是int (如果该值不符合int范围):

  • hex为long

     Long.valueOf(hexString, 16).longValue() 
  • long到hex

     Long.toHexString(longValue) 

尝试使用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()); 

值得一提的是,Java 8拥有Integer.parseUnsignedIntLong.parseUnsignedLong方法,可以完成您想要的function,具体如下:

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

这个名字有点令人困惑,因为它从一个hexstring中parsing了一个有符号的整数,但是它完成了工作。

你应该知道,Java的parseInt方法实际上是一堆吃“假”hex的代码:如果你想翻译-32768,你应该把绝对值转换成hex,然后用“ – ”作为前缀。

有一个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 

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

其根本原因在于如何编写Integer类。 基本上,parseInt是正数的“优化”。 当它parsingstring时,它累积地build立结果,但是否定。 然后翻转最终结果的标志。

例:

66 = 0x42

parsing如下:

 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的源代码中你可以find这个评论。

 // Accumulating negatively avoids surprises near MAX_VALUE 

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

试试这个样本作为一个testing。

 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(); 

由于Integer.toHexString(字节/整数)在您尝试转换签名字节(如UTF-16解码字符)时无法使用:

 Integer.toString(byte/integer, 16); 

要么

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

反向可以使用

 Integer.parseInt(hexString, 16);