I'm working on code that is hardware and and math related and makes extensive use of unsigned integer values, 32- and 64-bit. Bugs have been steady and difficult to work through without any javac support. Java 8 added a few functions on the boxed Long class for division, mod, and comparisons, but while these provide run-time support, the lack of compile-time warnings for unintended mixing of the two has made me want to pull my hair out.
Does anybody know of any ways to help deal with these issues? One of the Java team members mentions possible annotation support for type checking.
So far, I prefix all unsigned variables with u_, and I even tried adding an /* unsigned */
comment before each occurance of int
or long
that should be unsigned. While these were useful, they were also extremely cluttering. It doesn't go far enough. There are just too many opportunities for mistakes.
Two of the larger problems are unwanted sign extension and mixed operations.
Something as innocuous as /* unsigned */ long u_lowmask = 0xffffffff
does not have the desired result or even just /* unsigned */ long u_widen64 = small32
ruins things with that silent extension. In other languages I can get warnings from the compiler or Lint-like static checker. Functional languages often build it into the type checking mechanism, but Java has eschewed these in favor of other solutions. There is just so many chances for a mixed comparison or operations.
Any ideas should hopefully have no runtime impact, so I can't afford wrapping unsigned in a class or bignums. Well, I might be able to wrap them in a class if I could get away with doing it without any allocation or the expense of thread locals, but this would probably make the code non-reentrant. Also Hotspot would have to be able to emit code for the wrapped unsigned integers close to simple native. (Actually, I think Hotspot is probably smart enough to get close - maybe an extra memory read and write.)
How are other people coding around this issue?