是否有用于无符号数类型包装器的Java库?
是否有用于无符号数类型包装器的Java库?
显然,Java本身不支持原生的无符号数类型,而且这种情况不会很快发生改变(从2002年开始的评论)。然而,在处理数据库(如MySQL)时,偶尔可能会用到它们。关于如何模拟无符号数的问题有很多。例如:
所有这些问题都描述了如何实现。但是是否有任何库能够完全实现对UByte、UShort、UInteger、ULong等适当包装器的支持呢?最好是这些包装器能够扩展java.lang.Number并提供类似于java.math.BigInteger的算术API。
正如在这份文档中所示,涉及到很多要考虑的问题,也有很多可能出错的地方(如如何位移、如何乘法等),所以我不想自己去做。此外,我也不想仅仅使用更高的类型(如使用Short代替Byte等)。我希望保留8位、16位、32位、64位数字的概念,以便与数据库等进行最佳交互。
更新:
在你回答之前!请考虑到我知道所有的解决方法,但我真的非常希望有这4种类型,具备以上的属性。也许已经有人做过了,所以我才会提问。无需提醒我解决方法。
没有人按你所希望的方式创建这些包装器的原因有几个:
1. 性能
2. 垃圾回收开销
3. 没有自动装箱/拆箱
4. 糟糕/无用的接口
5. 存在更简单的处理方法
前四点可以通过一个小的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资源。
即使是简单的算术运算也很难写或阅读。
出于相同的原因,没有人使用有符号的包装器类型进行算术运算。
如果使用下一个更大的有符号类型进行计算并截断上部分,所有这些都是不必要的:
long x=42, y, m=5, t=18 y = (x*m + t) & 0xFFFFFFFF;
在Java和数据库之间的传输也可以使用下一个更大的有符号类型完成。由于JDBC不会创建这些无符号的包装器类型,你必须自己完成这个过程,然后将数据转换为无符号的包装器。
我自己进行了一些CPU密集型的数据处理和处理二进制协议。在这些场合,我希望也有无符号数据类型。但是用包装类型在Java中模拟它们比直接处理每个单独的情况更麻烦。
我同意,当二进制协议使用无符号64位整数时,情况确实变得“丑陋”..你好,BigInteger 🙁
你说得很对。另一方面,有时你确实需要BigInteger和/或BigDecimal。那么你别无选择,只能使用那个冗长的API。出于同样的原因,如果你确实需要UInteger,为什么不使用它(如果它可用的话)?如果你追求速度,你仍然可以自己进行计算...我目前正在评估是否要在jooq.org中使用这样的包装器,或者是否有其他方法...在我的情况下,速度可能不是个问题。
你知道你仍然可以使用BigInteger包装器(对于64位无符号)和下一个更大的值进行算术运算,并告诉数据库正确存储值吗?我相当确定你至少可以对某些数据库这样做。
:我了解到很多解决方法。我只是真的想要一个可以通信有多少位的包装器。在数据库术语中,BigInteger最适合n>19的DECIMAL(n,0)。对我来说,这与无符号长整型的语义不同...
在这种情况下,不要重新实现算术运算,只需在包装器中存储一个简单的int bitsize;值(或仅为每种类型编写包装器)。然后为所有重要的数据库实现“如何在DB Y中存储bitsize X的值”的逻辑(不知道这是否标准化?),就完成了。如果性能不重要,编写抽象基类是简单的。有趣的部分在于DB通信。
:不那么有趣:-)JDBC的PreparedStatement.setString()和ResultSet.getString()可以用于至少12个数据库...我已经实现了简单的包装器。只是想知道是否有人已经在之前完成了...
我没有考虑字符串-因为每次访问时都需要解析,所以性能特性很差,并且存储时(恭喜,你刚刚将4字节值转换为20字节)变得更糟(假设在数据库中使用UTF-16编码的字符串,这是经常使用的方法)。
:那只是JDBC(Java)。然后,驱动程序会将字符串转换回DB的int unsigned,例如。我认为现代JVM可以处理奇怪的字符串解析。但也许,我可以将无符号版本的值作为int,long等传递...
你不需要一个完整的无符号类型的类,因为对于有符号和无符号类型,基本操作(如加法、减法、非扩展乘法和所有位操作,除了右移)是相同的。对于剩下的操作,你可以编写一个函数来处理。这不是一些实用方法的问题,而是关于一个真正的包装类型。可以在方法签名中使用它,以明确表示该值是无符号的,如果混用有符号和无符号将会得到编译器错误。如果你只是需要帮助方法-那正是我回答的第二部分。
在我需要在jOOQ中使用这个功能时,我没有找到类似的东西,所以我自己开发了一个开源库,我称之为jOOU(U代表Unsigned):
我知道有些人可能认为这是多余的,但我真的很想要那些包装器精确地包装其他编程语言中称为ubyte
、ushort
、uint
、ulong
的类型。希望随着Valhalla的到来,这些包装器可以变成值类型。
当然,对算术/位操作实现的贡献非常受欢迎!