在 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 &
是逻辑 AND 而 <<
是左移
本质上,我通过将字节移位并将它们组合在一起,将 4 个 8 位字节组合成一个 32 位 int
我还确保任何标志推广都不会影响& 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 & 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 的位级别工作