为什么Java不支持无符号整数?

在我看来,这是一个奇怪的遗漏,因为它们允许人们编写不太可能在意外的大输入上产生溢出的代码。

此外,使用无符号整数可以是一种自我文档的形式,因为它们表明无符号整型所要保存的值永远不应该是负数。

最后,在某些情况下,无符号整数对于某些运算(如除法)更有效。

包含这些的缺点是什么?


当前回答

字里行间,我认为逻辑是这样的:

通常,Java设计人员希望简化可用的数据类型 对于日常用途,他们认为最常见的需求是有符号的数据类型 为了实现某些算法,有时需要无符号算术,但是要实现这种算法的程序员也应该具备使用有符号数据类型进行无符号算术的知识

总的来说,我认为这是一个合理的决定。我可能会:

使字节无符号,或者至少为这一数据类型提供了有符号/无符号的替代选项,可能使用不同的名称(使它有符号有利于一致性,但什么时候需要有符号字节?) 不再使用“short”(你上次使用16位符号算术是什么时候?)

不过,只要稍加修饰,对32位以内的无符号值进行运算就不会太糟糕,而且大多数人不需要无符号64位除法或比较。

其他回答

我认为Java本身就很好,添加unsigned会使它变得复杂而没有太多好处。 即使使用简化的整数模型,大多数Java程序员也不知道基本的数字类型是如何行为的——只要阅读《Java Puzzlers》一书,就能了解您可能持有的误解。

至于实用的建议:

如果你的值是任意大小,不适合int,使用long。 如果它们不适合长期使用BigInteger。 只有在需要节省空间时,才对数组使用较小的类型。 如果你正好需要64/32/16/8位,使用long/int/short/byte,不要担心符号位,除法、比较、右移和强制转换除外。

另请参阅关于“将一个随机数生成器从C移植到Java”的回答。

这是对高斯林和其他人的采访,关于简单:

Gosling: For me as a language designer, which I don't really count myself as these days, what "simple" really ended up meaning was could I expect J. Random Developer to hold the spec in his head. That definition says that, for instance, Java isn't -- and in fact a lot of these languages end up with a lot of corner cases, things that nobody really understands. Quiz any C developer about unsigned, and pretty soon you discover that almost no C developers actually understand what goes on with unsigned, what unsigned arithmetic is. Things like that made C complex. The language part of Java is, I think, pretty simple. The libraries you have to look up.

这是一个古老的问题,pat确实简单地提到了char,我只是想我应该为其他人扩展这个问题,他们将在未来的道路上看到这个问题。让我们仔细看看Java的基本类型:

字节- 8位有符号整数

短16位有符号整数

Int - 32位有符号整数

长64位有符号整数

Char - 16位字符(无符号整数)

虽然char不支持无符号算术,但它本质上可以被视为无符号整数。您必须显式地将算术运算转换回char类型,但它确实提供了一种指定无符号数字的方法。

char a = 0;
char b = 6;
a += 1;
a = (char) (a * b);
a = (char) (a + b);
a = (char) (a - 16);
b = (char) (b % 3);
b = (char) (b / a);
//a = -1; // Generates complier error, must be cast to char
System.out.println(a); // Prints ? 
System.out.println((int) a); // Prints 65532
System.out.println((short) a); // Prints -4
short c = -4;
System.out.println((int) c); // Prints -4, notice the difference with char
a *= 2;
a -= 6;
a /= 3;
a %= 7;
a++;
a--;

是的,没有对无符号整数的直接支持(显然,如果有直接支持,我就不必将大部分操作转换回char类型)。但是,肯定存在无符号基元数据类型。我也希望看到一个无符号字节,但我猜加倍内存成本,而不是使用char是一个可行的选择。


Edit

JDK8为Long和Integer提供了新的api,在将Long和int值作为无符号值处理时提供了辅助方法。

compareUnsigned divideUnsigned parseUnsignedInt parseUnsignedLong remainderUnsigned toUnsignedLong toUnsignedString

此外,Guava提供了许多帮助器方法来处理整数类型,这有助于弥补由于缺乏对无符号整数的本机支持而留下的空白。

I once took a C++ course with someone on the C++ standards committee who implied that Java made the right decision to avoid having unsigned integers because (1) most programs that use unsigned integers can do just as well with signed integers and this is more natural in terms of how people think, and (2) using unsigned integers results in lots easy to create but difficult to debug issues such as integer arithmetic overflow and losing significant bits when converting between signed and unsigned types. If you mistakenly subtract 1 from 0 using signed integers it often more quickly causes your program to crash and makes it easier to find the bug than if it wraps around to 2^32 - 1, and compilers and static analysis tools and runtime checks have to assume you know what you're doing since you chose to use unsigned arithmetic. Also, negative numbers like -1 can often represent something useful, like a field being ignored/defaulted/unset while if you were using unsigned you'd have to reserve a special value like 2^32 - 1 or something similar.

Long ago, when memory was limited and processors did not automatically operate on 64 bits at once, every bit counted a lot more, so having signed vs unsigned bytes or shorts actually mattered a lot more often and was obviously the right design decision. Today just using a signed int is more than sufficient in almost all regular programming cases, and if your program really needs to use values bigger than 2^31 - 1, you often just want a long anyway. Once you're into the territory of using longs, it's even harder to come up with a reason why you really can't get by with 2^63 - 1 positive integers. Whenever we go to 128 bit processors it'll be even less of an issue.

恕我直言,原因是他们太懒了,没有去实施/纠正这个错误。 暗示C/ c++程序员不理解unsigned,结构,联合,位标志…太荒谬了。

如果你正在和一个基本的/bash/java程序员交谈,即将开始用C语言编程,没有任何真正的语言知识,或者你只是在说你自己的想法。;)

当你每天处理文件或硬件的格式时,你会开始质疑,他们到底在想什么。

一个很好的例子是尝试使用无符号字节作为自旋转循环。 对于那些不理解最后一句话的人,你究竟是如何称自己为程序员的。

DC