显然,Java本身并不支持无符号数字类型and that's not going to change soon(从2002年开始的评论)。但是,在使用MySQL等数据库时,它们可能会偶尔派上用场。有很多问题涉及如何模拟无符号数。例如:
所有这些都表面上描述了可以完成的方式。但是,是否有任何库实际上一直在为UByte
,UShort
,UInteger
,ULong
实现合适的包装器?优选地,那些包装器将扩展java.lang.Number
并提供类似于java.math.BigInteger
的算术API。
从this document中可以看出,有很多可以想到的,还有很多可能出错的地方(比如如何按位移位,如何繁殖等),所以我不会&#39我想自己做。另外,我不想只使用下一个更高的类型(例如Short
而不是Byte
等)。我希望保留8-bit
,16-bit
,32-bit
,64-bit
号码的概念,以便与数据库进行最佳互动。
更新:
在回答之前!考虑到我知道所有的解决方法,但我真的非常希望确切地拥有具有上述属性的4种类型。也许有人已经这样做了,这就是我问的原因。无需提醒我解决方法。
答案 0 :(得分:27)
当我在jOOQ内部需要这个功能时,我找不到类似的东西,所以我推出了自己的开源库,我称之为jOOU(U代表无符号):
我知道有些人可能会认为这有点过分,但我真的希望准确地包含其他语言称为ubyte
,ushort
,uint
,{{1 }}。希望与Valhalla一起,这些包装可以变成价值类型。
当然,非常欢迎对算术/按位操作实现的贡献!
答案 1 :(得分:20)
有些原因导致没有人以你想要的方式创建这些包装器。
前四点由小C示例证明:
unsigned int x=42, y, m=5, t=18;
y = x * m + t;
这将被翻译成:
UInteger m = new UInteger(5);
UInteger t = new UInteger(18);
UInteger x = new UInteger(42);
UInteger y = x.multiplyBy(m);
y = y.add(t);
必须创建多个包装器对象,multiplyBy
和add
将生成更多。如果以这种方式进行许多计算,这将给垃圾收集器带来相当大的负担。包装和展开也会耗尽你的CPU。
即使简单的算术也是PITA写入或读取也很明显。
出于同样的原因,NOBODY使用签名的包装器类型进行算术运算。
如果您使用下一个更大的签名类型进行计算并切断上半部分,则所有这些都是不必要的:
long x=42, y, m=5, t=18
y = (x*m + t) & 0xFFFFFFFF;
Java和数据库之间的转移也可以使用下一个最大的签名类型完成。由于JDBC不会创建这些未签名的包装器类型,因此您必须自己完成此操作才能将数据转换为未签名的包装器。
我为自己完成了一些CPU密集型数据处理并处理了二进制协议。在这些场合,我希望我也有未签名的数据类型。但是使用包装器类型在Java中模拟它们比在每个场合直接处理问题更有问题。
答案 2 :(得分:2)
在commons-primitives中使用的解决方案,用于unsignedInt数组,它传递给long作为unsigned int。你可以在这里阅读更多内容:
答案 3 :(得分:2)
// Java 8
int vInt = Integer.parseUnsignedInt("4294967295");
System.out.println(vInt); // -1
String sInt = Integer.toUnsignedString(vInt);
System.out.println(sInt); // 4294967295
long vLong = Long.parseUnsignedLong("18446744073709551615");
System.out.println(vLong); // -1
String sLong = Long.toUnsignedString(vLong);
System.out.println(sLong); // 18446744073709551615
// Guava 18.0
int vIntGu = UnsignedInts.parseUnsignedInt(UnsignedInteger.MAX_VALUE.toString());
System.out.println(vIntGu); // -1
String sIntGu = UnsignedInts.toString(vIntGu);
System.out.println(sIntGu); // 4294967295
long vLongGu = UnsignedLongs.parseUnsignedLong("18446744073709551615");
System.out.println(vLongGu); // -1
String sLongGu = UnsignedLongs.toString(vLongGu);
System.out.println(sLongGu); // 18446744073709551615
答案 4 :(得分:1)