yan*_*olo 3 java bit-manipulation operators operator-precedence
我很难理解一些代码,这些代码显示了如何将Java中的double转换为byte []的示例,反之亦然.
以下是用于将double转换为byte []的代码:
public static byte [] doubleToByteArray (double numDouble)
{
byte [] arrayByte = new byte [8];
long numLong;
// Takes the double and sticks it into a long, without changing it
numLong = Double.doubleToRawLongBits(numDouble);
// Then we need to isolate each byte
// The casting of byte (byte), captures only the 8 rightmost bytes
arrayByte[0] = (byte)(numLong >>> 56);
arrayByte[1] = (byte)(numLong >>> 48);
arrayByte[2] = (byte)(numLong >>> 40);
arrayByte[3] = (byte)(numLong >>> 32);
arrayByte[4] = (byte)(numLong >>> 24);
arrayByte[5] = (byte)(numLong >>> 16);
arrayByte[6] = (byte)(numLong >>> 8);
arrayByte[7] = (byte)numLong;
for (int i = 0; i < arrayByte.length; i++) {
System.out.println("arrayByte[" + i + "] = " + arrayByte[i]);
}
return arrayByte;
}
Run Code Online (Sandbox Code Playgroud)
这里是用于将byte []转换回double的代码:
public static double byteArrayToDouble (byte [] arrayByte)
{
double numDouble;
long numLong;
// When putting byte into long, java also adds the sign
// However, we don't want to put bits that are not from the orignal value
//
// The rightmost bits left unaltered because we "and" them with a 1
// The left bits become 0 because we "and" them with a 0
//
// We are applying a "mask" (& 0x00 ... FFL)
// 0 & 0 = 0
// 0 & 1 = 0
// 1 & 0 = 0
// 1 & 1 = 1
//
// So, the expression will put byte in the long (puts it into the right most position)
// Then we apply mask to remove the sign applied by java
// Then we move the byte into its position (shift left 56 bits, then 48 bits, etc.)
// We end up with 8 longs, that each have a byte set up in the appropriate position
// By doing an | with each one of them, we combine them all into the orignal long
//
// Then we use Double.longBitsToDouble, to convert the long bytes into double.
numLong = (((long)arrayByte[0] & 0x00000000000000FFL) << 56) | (((long)arrayByte[1] & 0x00000000000000FFL) << 48) |
(((long)arrayByte[2] & 0x00000000000000FFL) << 40) | (((long)arrayByte[3] & 0x00000000000000FFL) << 32) |
(((long)arrayByte[4] & 0x00000000000000FFL) << 24) | (((long)arrayByte[5] & 0x00000000000000FFL) << 16) |
(((long)arrayByte[6] & 0x00000000000000FFL) << 8) | ((long)arrayByte[7] & 0x00000000000000FFL);
numDouble = Double.longBitsToDouble(numLong);
return numDouble;
}
Run Code Online (Sandbox Code Playgroud)
好的,这是我不太了解的部分.
((long)arrayByte[0] & 0x00000000000000FFL) << 56
Run Code Online (Sandbox Code Playgroud)
似乎演员在实际的按位操作之前发生,因为作者说
表达式将字节放在long [...]然后我们应用mask来删除java应用的符号
为什么字节在实际转换之前被转换为很长时间?操作不应该像这样吗?
(((long)arrayByte[0]) & 0x00000000000000FFL) << 56
Run Code Online (Sandbox Code Playgroud)
还是有其他我不明白的东西?
这是由于运算符优先级和关联性在Java中的工作原理.1
遗憾的是,Oracle Java Tutorial只提供了部分概述,Java语言规范也没有太大的帮助,因为它主要通过声明:向读者解释运算符优先级.
运算符之间的优先级由语法产生的层次结构管理.
通常,表达式从左到右进行评估.在运营商优先级方面,下表2 适用:
?????????????????????????????????????????????????????????????????
? Level ? Operator ? Description ? Associativity ?
?????????????????????????????????????????????????????????????????
? 16 ? [] ? access array element ? left to right ?
? ? . ? access object member ? ?
? ? () ? parentheses ? ?
?????????????????????????????????????????????????????????????????
? 15 ? ++ ? unary post-increment ? not associative ?
? ? -- ? unary post-decrement ? ?
?????????????????????????????????????????????????????????????????
? 14 ? ++ ? unary pre-increment ? right to left ?
? ? -- ? unary pre-decrement ? ?
? ? + ? unary plus ? ?
? ? - ? unary minus ? ?
? ? ! ? unary logical NOT ? ?
? ? ~ ? unary bitwise NOT ? ?
?????????????????????????????????????????????????????????????????
? 13 ? () ? cast ? right to left ?
? ? new ? object creation ? ?
?????????????????????????????????????????????????????????????????
? 12 ? * ? multiplicative ? left to right ?
? ? / ? ? ?
? ? % ? ? ?
?????????????????????????????????????????????????????????????????
? 11 ? + - ? additive ? left to right ?
? ? + ? string concatenation ? ?
?????????????????????????????????????????????????????????????????
? 10 ? << >> ? shift ? left to right ?
? ? >>> ? ? ?
?????????????????????????????????????????????????????????????????
? 9 ? < <= ? relational ? not associative ?
? ? > >= ? ? ?
? ? instanceof ? ? ?
?????????????????????????????????????????????????????????????????
? 8 ? == ? equality ? left to right ?
? ? != ? ? ?
?????????????????????????????????????????????????????????????????
? 7 ? & ? bitwise AND ? left to right ?
?????????????????????????????????????????????????????????????????
? 6 ? ^ ? bitwise XOR ? left to right ?
?????????????????????????????????????????????????????????????????
? 5 ? | ? bitwise OR ? left to right ?
?????????????????????????????????????????????????????????????????
? 4 ? && ? logical AND ? left to right ?
?????????????????????????????????????????????????????????????????
? 3 ? || ? logical OR ? left to right ?
?????????????????????????????????????????????????????????????????
? 2 ? ?: ? ternary ? right to left ?
?????????????????????????????????????????????????????????????????
? 1 ? = += -= ? assignment ? right to left ?
? ? *= /= %= ? ? ?
? ? &= ^= |= ? ? ?
? ? <<= >>= >>>= ? ? ?
?????????????????????????????????????????????????????????????????
Run Code Online (Sandbox Code Playgroud)
对于您的特定问题,这意味着不需要在转换操作周围放置额外的括号,因为转换运算符的优先级()高于按位AND &运算符的优先级(级别13与级别7).
1我写这篇文章是一个规范的答案,用于解决有关Java中运算符优先级和关联性的问题.我找到了许多现有的答案,给出了部分信息,但我找不到一个概述完整优先级和关联表的人.
2运算符优先级和关联表从https://introcs.cs.princeton.edu/java/11precedence/转载.