Java优先级-强制转换和按位运算符 [英] Java Precedence - Casting and Bitwise Operators

查看:80
本文介绍了Java优先级-强制转换和按位运算符的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我很难理解一些代码,该代码显示了一个示例,该示例如何将Java中的double转换为byte [],反之亦然.

I am having a hard time understanding some code that shows an example how a double in Java could be transformed into a byte[] and vice versa.

以下是用于将双精度型转换为字节[]的代码:

Here is the code being used to transform a double into a 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;
}

这是用于将byte []转换为double的代码:

And here is the code being used to tranform the byte[] back to a 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;
}

好的,这是我不太了解的部分.

Okay, and here is the part I don't quite get.

((long)arrayByte[0] & 0x00000000000000FFL) << 56

似乎强制转换发生在实际的按位运算之前,因为作者说过

It seems as though the casting happens before the actual bitwise operation, because the author says that

表达式将把字节放在长[...]处,然后应用掩码以删除java施加的符号

the expression will put byte in the long [...] Then we apply mask to remove the sign applied by java

为什么该字节在实际转换之前就转换了很长时间?操作不应该与此相似吗?

How come the byte is being transformed into a long before it being actually casted? Shouldn't the operation resemble this?

(((long)arrayByte[0]) & 0x00000000000000FFL) << 56

或者还有其他我不理解的东西吗?

Or is there something else I don't understand?

推荐答案

这是由于运算符优先级和关联性在Java中是如何工作的. 1

This is due to how operator precedence and associativity works in Java.1

不幸的是, Oracle Java教程仅提供了部分概述,以及 Java语言规范也不大有帮助,因为它主要是通过指出以下内容来让操作员将运算符的优先级留给读者:

Unfortunately, the Oracle Java Tutorial provides only a partial overview, and the Java Language Specification is not of great help either, as it mostly leaves the exercise of figuring out operator precedence to the reader by stating:

运算符之间的优先级由语法产生的层次结构管理.

Precedence among operators is managed by a hierarchy of grammar productions.

通常,表达式是从左到右计算的.就运算符优先级而言,下表 2 适用:

In general, expressions are evaluated from left to right. In terms of operator precedence, the following table2 applies:

╔═══════╦══════════════╦══════════════════════╦═════════════════╗
║ 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   ║
║       ║ *= /= %=     ║                      ║                 ║
║       ║ &= ^= |=     ║                      ║                 ║
║       ║ <<= >>= >>>= ║                      ║                 ║
╚═══════╩══════════════╩══════════════════════╩═════════════════╝

对于您的特定问题,这意味着无需在强制转换操作周围放置任何括号,因为强制转换操作符()的优先级高于按位与&运算符的优先级(13级与7级).

For your specific question, this means that no extra parentheses need to be placed around the cast operation, as the precedence of the cast operator () is higher than that of the bitwise AND & operator (level 13 vs. level 7).

1 我将其写为规范答案,以解决有关Java中的运算符优先级和关联性的问题.我发现了很多现有的给出部分信息的答案,但找不到完整的优先级和关联性表概述的答案.
2 运算符优先级和关联表摘录自 https://introcs. cs.princeton.edu/java/11precedence/.

1 I wrote this up as a canonical answer to address questions about operator precedence and associativity in Java. I found a lot of existing answers that gave partial information, but I couldn't find one that gave an overview of the complete precedence and associativity table.
2 Operator precedence and associativiy table reproduced from https://introcs.cs.princeton.edu/java/11precedence/.

这篇关于Java优先级-强制转换和按位运算符的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆