在 Java 中从字节转换为 int

Posted

技术标签:

【中文标题】在 Java 中从字节转换为 int【英文标题】:Converting from byte to int in Java 【发布时间】:2012-03-23 19:16:51 【问题描述】:

我生成了一个安全随机数,并将其值放入一个字节中。这是我的代码。

SecureRandom ranGen = new SecureRandom();
byte[] rno = new byte[4]; 
ranGen.nextBytes(rno);
int i = rno[0].intValue();

但我收到一个错误:

 byte cannot be dereferenced

【问题讨论】:

字节和字节是有区别的。后者是一个支持.intValue() 方法的对象。第一个是原始字节值,只需将其分配为int i = rno[0]; 另见***.com/questions/2383265/convert-4-bytes-to-int 【参考方案1】:

您的数组包含 byte 原语,但您正试图在它们上调用方法。

您不需要做任何明确的事情来将byte 转换为int,只需:

int i=rno[0];

...因为它不是一个沮丧的人。

请注意,byte-to-int 转换的默认行为是保留值的符号(请记住,byte 在 Java 中是有符号类型)。比如:

byte b1 = -100;
int i1 = b1;
System.out.println(i1); // -100

如果您认为 byte 是无符号 (156) 而不是有符号 (-100),那么从 Java 8 开始就有 Byte.toUnsignedInt

byte b2 = -100; // Or `= (byte)156;`
int = Byte.toUnsignedInt(b2);
System.out.println(i2); // 156

在 Java 8 之前,要获得 int 中的等效值,您需要屏蔽符号位:

byte b2 = -100; // Or `= (byte)156;`
int i2 = (b2 & 0xFF);
System.out.println(i2); // 156

仅出于完整性考虑 #1:如果您确实出于某种原因想要使用Byte 的各种方法(您不需要在这里),您可以使用boxing conversion:

Byte b = rno[0]; // Boxing conversion converts `byte` to `Byte`
int i = b.intValue();

或者Byte constructor:

Byte b = new Byte(rno[0]);
int i = b.intValue();

但同样,你在这里不需要那个。


仅出于完整性考虑 #2:如果 是向下转换(例如,如果您试图将 int 转换为 byte),那么您只需要转换: p>

int i;
byte b;

i = 5;
b = (byte)i;

这向编译器保证您知道这是一个向下转换,因此您不会收到“可能丢失精度”错误。

【讨论】:

使用 Byte 构造函数不是一个好主意。改用Byte b = rno[0]; @xehpuk:我应该提到拳击转换,现在就完成了。 为什么在这种情况下装箱转换优于 Byte 构造函数?据我了解,拳击转换最终会以任何方式使用 Byte 构造函数吗?我的理解有误吗? @user3772575:是的。 Boxing 将使用Byte.valueOf,而不是new Byte(),以避免分配一个新的实例,如果已经存在一个用于该字节值的实例; more here。 (规范doesn't actually say that,但这就是它的作用。你可以通过查看字节码来判断。) 上次我签入的Java 8 Byte 类提供了一个名为toUnsignedInt(byte) 的静态方法。这应该有助于更轻松地转换并且代码更具可读性。【参考方案2】:
byte b = (byte)0xC8;
int v1 = b;       // v1 is -56 (0xFFFFFFC8)
int v2 = b & 0xFF // v2 is 200 (0x000000C8)

大多数时候 v2 是您真正需要的方式。

【讨论】:

是因为32位机器生成了长0xffffffc8,谢谢。 这是正确的答案,v2 几乎总是你想要的。在没有& 0xff 的情况下将字节隐式转换为 int 是 Java 中错误的来源。 这并不是因为“Java 中的错误”隐式转换。这是由于开发人员的误解。 Java 的字节原语只支持 -128 到 127 之间的值。如果有人试图将一个无符号值(如 0xC8)填充到其中,它可以用一堆前导值翻转(由于二进制补码符号)。类似地,对于这个问题,一个完整的位空间可以设置一个符号位,并且一个数字提升也会这样做。 Java 实际上是在后台进行数值转换,according to the JLS,这意味着无论如何,两个操作数都被转换为 int 基元。 不是 Java 中的错误,而是用 Java 编写的用户代码中的错误 :) 大多数程序员没有意识到字节是用 Java 签名的,坦率地说,他们将字节视为在Java 规范,但他们这样做是为了与其他整数类型保持一致,因为它们都没有无符号版本。将短裤转换为整数也会出现同样的问题,因为人们通常也没有意识到短裤是有签名的。 (尽管使用字节触发符号扩展错误更容易,因为值的范围非常有限。)人们确实希望对 int 和 long 进行签名。【参考方案3】:

如果您想将 4 个字节组合成一个 int,您需要这样做

int i= (rno[0]<<24)&0xff000000|
       (rno[1]<<16)&0x00ff0000|
       (rno[2]<< 8)&0x0000ff00|
       (rno[3]<< 0)&0x000000ff;

我使用了 3 个特殊运算符 | 是按位逻辑 OR &amp; 是逻辑 AND 而 &lt;&lt; 是左移

本质上,我通过将字节移位并将它们组合在一起,将 4 个 8 位字节组合成一个 32 位 int

我还确保任何标志推广都不会影响&amp; 0xff的结果

【讨论】:

我愿意 (rno[0]&0x000000ff) @ingyhere 您的“替代”建议不正确!见盛.W的回答。由于符号扩展,您几乎总是需要 (b & 0xff) 将字节转换为 int,而不是 ((int) b) 或等效的隐式转换。 You got me @LukeHutchison ...我评论中的第二个仅适用于 Java 字节原语范围内的无符号值(正空间)(最多 127 个)。 有符号值的正数范围不是无符号值,它仍然有'+'的符号 :) 字节和短整数和整数和长整数在Java中是有符号的,没有无符号版本! 【参考方案4】:

原始数据类型(如字节)在java中没有方法,但可以直接做:

int i=rno[0];

【讨论】:

不,它是Byte.intValue,而Byte 是一个类,byte 是一个原始数据类型。 这个答案不完整。见盛.W的回答。您几乎总是需要执行(b &amp; 0xff)byte 转换为int,而不是((int) b) 或等效的隐式转换int i = b;,因为高位符号扩展-设置字节。忘记这样做是错误的常见来源。【参考方案5】:

字节被透明地转换为整数。

随便说说

int i= rno[0];

【讨论】:

但请注意,符号是保留的,这并不总是您想要的(Java 没有无符号字节)【参考方案6】:

我以为会是:

byte b = (byte)255;
int i = b &255;

【讨论】:

【参考方案7】:

int b = Byte.toUnsignedInt(a);

【讨论】:

正如目前所写,您的答案尚不清楚。请edit 添加其他详细信息,以帮助其他人了解这如何解决所提出的问题。你可以找到更多关于如何写好答案的信息in the help center。

以上是关于在 Java 中从字节转换为 int的主要内容,如果未能解决你的问题,请参考以下文章

解释类型转换如何在 C 中从 int 到 short 的位级别工作

Java - 将 Int 转换为字节 - 奇怪的结果

Java bytebuffer 将三个字节转换为 int

JAVA中int强制转换byte

将 int 转换为字节 - Java 和 Actionscript 中的不同结果

Java 将 4 个字节转换为 int