在Java中是否有一种方法来声明无符号整型?

或者这个问题也可以是这样的: Java中与unsigned等价的是什么?

只是为了告诉你上下文,我正在查看Java的String.hashcode()的实现。我想测试如果整数是32 unsigned int,碰撞的可能性。


当前回答

这里有很好的答案,但我没有看到任何逐位操作的演示。正如Visser(目前接受的答案)所说,Java默认为整数加符号(Java 8有无符号整数,但我从未使用过它们)。废话不多说,我们开始吧……

RFC 868使用实例

如果需要向IO写入无符号整数会发生什么?实际示例是当您想根据RFC 868输出时间时。这需要一个32位的大端序无符号整数,用于编码从12:00 A.M.开始的秒数1900年1月1日。怎么编码呢?

创建自己的32位无符号整数,如下所示:

声明一个4字节(32位)的字节数组

Byte my32BitUnsignedInteger[] = new Byte[4] // represents the time (s)

This initializes the array, see Are byte arrays initialised to zero in Java?. Now you have to fill each byte in the array with information in the big-endian order (or little-endian if you want to wreck havoc). Assuming you have a long containing the time (long integers are 64 bits long in Java) called secondsSince1900 (Which only utilizes the first 32 bits worth, and you‘ve handled the fact that Date references 12:00 A.M. January 1, 1970), then you can use the logical AND to extract bits from it and shift those bits into positions (digits) that will not be ignored when coersed into a Byte, and in big-endian order.

my32BitUnsignedInteger[0] = (byte) ((secondsSince1900 & 0x00000000FF000000L) >> 24); // first byte of array contains highest significant bits, then shift these extracted FF bits to first two positions in preparation for coersion to Byte (which only adopts the first 8 bits)
my32BitUnsignedInteger[1] = (byte) ((secondsSince1900 & 0x0000000000FF0000L) >> 16);
my32BitUnsignedInteger[2] = (byte) ((secondsSince1900 & 0x000000000000FF00L) >> 8);
my32BitUnsignedInteger[3] = (byte) ((secondsSince1900 & 0x00000000000000FFL); // no shift needed

我们的my32BitUnsignedInteger现在等价于一个符合RCF 868标准的32位无符号大端整数。是的,长数据类型是有符号的,但是我们忽略了这个事实,因为我们假设secondsSince1900只使用了低32位)。由于将long强制转换为字节,所有高于2^7(十六进制中的前两位)的位将被忽略。

参考资料:Java网络编程,第4版。

其他回答

对于无符号数字,您可以使用这些类从Guava库:

UnsignedInteger UnsignedLong

它们支持各种操作:

+ - 次 国防部 除以

目前似乎缺少的是字节移位操作符。如果需要,可以从Java中使用BigInteger。

这里有很好的答案,但我没有看到任何逐位操作的演示。正如Visser(目前接受的答案)所说,Java默认为整数加符号(Java 8有无符号整数,但我从未使用过它们)。废话不多说,我们开始吧……

RFC 868使用实例

如果需要向IO写入无符号整数会发生什么?实际示例是当您想根据RFC 868输出时间时。这需要一个32位的大端序无符号整数,用于编码从12:00 A.M.开始的秒数1900年1月1日。怎么编码呢?

创建自己的32位无符号整数,如下所示:

声明一个4字节(32位)的字节数组

Byte my32BitUnsignedInteger[] = new Byte[4] // represents the time (s)

This initializes the array, see Are byte arrays initialised to zero in Java?. Now you have to fill each byte in the array with information in the big-endian order (or little-endian if you want to wreck havoc). Assuming you have a long containing the time (long integers are 64 bits long in Java) called secondsSince1900 (Which only utilizes the first 32 bits worth, and you‘ve handled the fact that Date references 12:00 A.M. January 1, 1970), then you can use the logical AND to extract bits from it and shift those bits into positions (digits) that will not be ignored when coersed into a Byte, and in big-endian order.

my32BitUnsignedInteger[0] = (byte) ((secondsSince1900 & 0x00000000FF000000L) >> 24); // first byte of array contains highest significant bits, then shift these extracted FF bits to first two positions in preparation for coersion to Byte (which only adopts the first 8 bits)
my32BitUnsignedInteger[1] = (byte) ((secondsSince1900 & 0x0000000000FF0000L) >> 16);
my32BitUnsignedInteger[2] = (byte) ((secondsSince1900 & 0x000000000000FF00L) >> 8);
my32BitUnsignedInteger[3] = (byte) ((secondsSince1900 & 0x00000000000000FFL); // no shift needed

我们的my32BitUnsignedInteger现在等价于一个符合RCF 868标准的32位无符号大端整数。是的,长数据类型是有符号的,但是我们忽略了这个事实,因为我们假设secondsSince1900只使用了低32位)。由于将long强制转换为字节,所有高于2^7(十六进制中的前两位)的位将被忽略。

参考资料:Java网络编程,第4版。

我们需要无符号数字来在jOOQ中建模MySQL的无符号TINYINT, SMALLINT, INT, BIGINT,这就是为什么我们创建了jOOU,这是一个在Java中为无符号整数提供包装器类型的极简库。例子:

import static org.joou.Unsigned.*;

// and then...
UByte    b = ubyte(1);
UShort   s = ushort(1);
UInteger i = uint(1);
ULong    l = ulong(1);

所有这些类型都扩展了java.lang.Number,并且可以转换为更高阶的原语类型和BigInteger。希望这能有所帮助。

(免责声明:我为这些库背后的公司工作)

只是做了这段代码,它转换了“这个”。Altura "从负数到正数。希望这能帮助到需要帮助的人

       if(this.altura < 0){    

                        String aux = Integer.toString(this.altura);
                        char aux2[] = aux.toCharArray();
                        aux = "";
                        for(int con = 1; con < aux2.length; con++){
                            aux += aux2[con];
                        }
                        this.altura = Integer.parseInt(aux);
                        System.out.println("New Value: " + this.altura);
                    }

int中的值是有符号还是无符号取决于位是如何解释的——Java将位解释为有符号值(它没有无符号原语)。

如果你有一个int,你想解释为unsigned值(例如,你从DataInputStream读取一个int,你知道应该解释为unsigned值),那么你可以做下面的技巧。

int fourBytesIJustRead = someObject.getInt();
long unsignedValue = fourBytesIJustRead & 0xffffffffL;

注意,重要的是十六进制字面值是一个长字面值,而不是int字面值-因此'L'在末尾。