Java优先级 - 转换和按位运算符

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)

还是有其他我不明白的东西?

Rob*_*sen 5

这是由于运算符优先级和关联性在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/转载.