Java 8中处理“无符号”整数的注释思想
我正在编写与硬件和数学相关的代码,并广泛使用32位和64位无符号整数值。没有任何javac支持,bug一直很稳定,很难解决。Java8在装箱的Long类上添加了一些用于除法、mod和比较的函数,但尽管这些函数提供了运行时支持,但由于缺少编译时警告,无法将这两个函数意外地混合在一起,这让我非常恼火
有人知道有什么方法可以帮助解决这些问题吗?Java团队的一名成员提到possible annotation support用于类型检查
到目前为止,我在所有无符号变量的前面加上u_,我甚至尝试在每次出现应无符号的int
或long
之前添加/* unsigned */
注释。虽然这些是有用的,但它们也非常杂乱。这还不够。犯错误的机会太多了
两个较大的问题是不需要的符号扩展和混合操作
像/* unsigned */ long u_lowmask = 0xffffffff
这样无害的东西没有达到预期的效果,甚至/* unsigned */ long u_widen64 = small32
用这个无声的扩展破坏了东西。在其他语言中,我可以从编译器或类似Lint的静态检查器获得警告。函数式语言通常将其构建到类型检查机制中,但Java已经避开了这些机制,转而采用其他解决方案。有太多机会进行混合比较或操作
希望任何想法都不会对运行时产生影响,所以我负担不起在类或bignums中包装unsigned。好吧,如果我不需要任何分配或线程局部变量的开销,我可能能够将它们封装在一个类中,但这可能会使代码不可重入。对于简单的热点代码,也可以将其包装为不带符号的整数。(事实上,我认为Hotspot可能足够聪明,可以靠近——可能需要额外的内存读写。)
其他人是如何围绕这个问题编码的
# 1 楼答案
编辑:截至2016年7月,Checker框架附带了您需要的大部分或全部内容:Signedness Checker,它验证有符号和无符号值的一致使用。从manual开始:
(向@MAGx2致敬,因为他注意到这个答案已经过时了。)
旧的答案如下:
我建议你调查一下Checker Framework。它使您能够定义自己的类型限定符注释,例如
@Unsigned
,然后在编译时检查代码对于这些注释的类型是否正确。如果它没有发出警告,那么您可以保证代码不会混合使用有符号和无符号值Checker框架附带了20 type-checkers,但没有用于无符号算术的框架。你需要write your own type-checker。这应该是相对简单的,因为类型检查器需要很少的特殊规则:您只是不想混合使用有符号值和无符号值
有关需要库注释的JDK方法的列表,请参阅 http://hg.openjdk.java.net/jdk8/tl/jdk/rev/71200c517524
# 2 楼答案
在检测方面,我没有对这些进行过太多的研究,但我会从this answer中查看Lint4j或其他Java lint工具
理想情况下,该工具会为
long
变量到int
值的每次赋值提供一个警告,然后您可以使用如下解决方案将每个此类赋值包装在一个静态(可内联)方法调用中(从而删除警告)对于赋值静态包装器方法,像这样的实用程序类在过去对我来说非常有效:
或者,这种样式在代码中更具可读性:
一些JUnit测试: