在Java中将字节转换为int的最优雅方式

时间:2011-02-02 08:29:11

标签: java

示例代码:

int a = 255;
byte b = (byte) a;
int c = b & 0xff; // Here be dragons
System.out.println(a);
System.out.println(b);
System.out.println(c);

因此我们从255的整数值开始,将其转换为一个字节(变为-1),然后使用魔术公式将其转换回int。预期的输出是:

255
-1
255

我想知道这个a & 0xff是否是进行此转化的最佳方式。例如,checkstyle抱怨在这个地方使用幻数,并且忽略此检查的值不是一个好主意,因为在其他地方255可能真的是一个应该避免的幻数。而且我自己为这样的东西定义常量非常烦人。所以我想知道JRE中是否有一种标准方法来代替这种转换?或者可能是已定义的具有最高无符号字节值的常量(类似于Byte.MAX_VALUE,这是最高的有符号值)

所以要保持简短:如何在不使用幻数的情况下将字节转换为int?

好的,到目前为止,提到了以下可能性:

  • 继续使用& 0xff并忽略checkstyle中的幻数255。缺点:其他可能在某些其他范围(不是位操作)中使用此数字的地方也不会被检查。优点:简短易读。
  • 为它定义自己的常量,然后使用& SomeConsts.MAX_UNSIGNED_BYTE_VALUE之类的代码。缺点:如果我需要在不同的类中,那么我必须为这个darn常量定义我自己的常量类。优势:这里没有神奇的数字。
  • 做一些像b & ((1 << Byte.SIZE) - 1)这样聪明的数学运算。编译器输出很可能是相同的,因为它被优化为常量值。缺点:代码相当多,难以阅读。优点:只要1未被定义为幻数(checkstyle默认忽略它),我们这里没有幻数,我们不需要定义自定义常量。当字节有一天被重新定义为16位(开玩笑)时它仍然有效,因为Byte.SIZE将是16而不是8。

还有更多想法吗?也许其他一些聪明的逐位操作比上面的操作短,只使用0和1之类的数字?

5 个答案:

答案 0 :(得分:18)

是进行转换的标准方式。如果你想摆脱checkstyle投诉,尝试定义一个常量,它可能会有所帮助:

 public final static int MASK = 0xff;

BTW - 请记住,它仍然是自定义转换。 byte是一种已签名的数据类型,因此byte永远不会保留值255。一个字节可以存储位模式1111 1111,但这表示整数值-1

所以实际上你正在进行位操作 - 位操作总是需要一些幻数。


BTW-2:是的,有一个Byte.MAX_VALUE常数,但这是 - 因为byte已签名 - 定义为2 7 -1(= 127)。所以它对你的情况没有帮助。 -1需要一个字节常量。

答案 1 :(得分:10)

忽略checkstyle。 0xFF 不是一个幻数。如果为它定义一个常量,则常量 是一个魔术常量,这比0xFF本身更难理解。在最近几个世纪受过教育的每个程序员都应该更熟悉0xFF而不是他的女朋友,如果有的话。

我们应该写这样的代码吗?

for(int i = Math.ZERO; ... )

答案 2 :(得分:4)

答案 3 :(得分:2)

我为此写了一个方法

public static int unsigned(byte x) {
    return int (x & 0xFF);
}

也为short和int参数重载(其中int扩展为long)。

而不是0xFF你可以使用Byte.MAX_VALUE + Byte.MAX_VALUE + 1来保持FindBug关闭,但我认为它是一个混淆。并且很容易弄错(先前的版本)。

答案 4 :(得分:1)

Java 8提供Byte.toUnsignedIntByte.toUnsignedLong(可能是非常大的字节)方法:

byte b = (byte)255;
int c = Byte.toUnsignedInt(b); // 255
long asLong = Byte.toUnsignedLong(b); // 255
相关问题