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

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

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

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

包含这些的缺点是什么?


当前回答

作为处理过无符号算术的人,我可以向您保证,在Java中确实没有必要使用无符号数字。

以C语言为例。让我们这样写:

unsigned int num = -7;
printf("%d", num);

你能猜到上面印的是什么吗?

-7

哇!无符号整数是负的!完全正确。没有真正的正整数。无符号整数只是一个n字节(取决于C语言中的体系结构)的值,它不为符号分配MSB。它不检查分配或读取的数字的实际符号。

其他回答

在“C”规范中,有一些因实用主义原因而被Java抛弃的珍宝,但随着开发人员的需求(闭包等),它们正在慢慢地回归。

我提到第一个是因为它和这个讨论有关;指针值对无符号整数算术的坚持。并且,与这个主题相关的是,在Java的Signed世界中维护Unsigned语义的困难。

我猜如果有人让Dennis Ritchie的另一个自我来建议Gosling的设计团队,他会建议给Signed's一个“无穷大的零”,这样所有的地址偏移请求都会先加上他们的algeaic RING SIZE来消除负值。

这样,向数组抛出的任何偏移量都不会生成SEGFAULT。例如,在一个封装类中,我称之为RingArray的双精度对象需要unsigned行为-在“自旋转循环”上下文中:

// ...
// Housekeeping state variable
long entrycount;     // A sequence number
int cycle;           // Number of loops cycled
int size;            // Active size of the array because size<modulus during cycle 0
int modulus;         // Maximal size of the array

// Ring state variables
private int head;   // The 'head' of the Ring
private int tail;   // The ring iterator 'cursor'
// tail may get the current cursor position
// and head gets the old tail value
// there are other semantic variations possible

// The Array state variable
double [] darray;    // The array of doubles

// somewhere in constructor
public RingArray(int modulus) {
    super();
    this.modulus = modulus;
    tail =  head =  cycle = 0;
    darray = new double[modulus];
// ...
}
// ...
double getElementAt(int offset){
    return darray[(tail+modulus+offset%modulus)%modulus];
}
//  remember, the above is treating steady-state where size==modulus
// ...

上面的RingArray永远不会从负索引中“获得”,即使恶意请求者试图这样做。记住,还有许多合法的请求用于请求先前的(负的)索引值。

注意:外层%模数去掉了对合法请求的引用,而内部%模数掩盖了明显的恶意,因为负数比-模数更负。如果这将出现在Java +..9 || 8+…+ spec,那么问题将真正成为一个“程序员不能“自我旋转”的错误”。

我相信所谓的Java unsigned int“缺陷”可以用上面的一行程序来弥补。

PS:只是为了给上面的RingArray管理提供上下文,这里有一个候选的'set'操作来匹配上面的'get'元素操作:

void addElement(long entrycount,double value){ // to be called only by the keeper of entrycount
    this.entrycount= entrycount;
    cycle = (int)entrycount/modulus;
    if(cycle==0){                       // start-up is when the ring is being populated the first time around
        size = (int)entrycount;         // during start-up, size is less than modulus so use modulo size arithmetic
        tail = (int)entrycount%size;    //  during start-up
    }
    else {
        size = modulus;
        head = tail;
        tail = (int)entrycount%modulus; //  after start-up
    }
    darray[head] = value;               //  always overwrite old tail
}

我听说它们将在接近最初的Java发行版时被包含。Oak是Java的前身,在一些规范文档中提到了使用值。不幸的是,这些都没有被引入Java语言。据任何人所知,可能由于时间限制,它们没有得到实施。

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

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

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

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

DC

在JDK8中,它确实提供了一些支持。

尽管有Gosling的担忧,但我们仍然可能看到Java对unsigned类型的完全支持。

我能想到一个不幸的副作用。在java嵌入式数据库中,使用32位id字段可以拥有的id数量是2^31,而不是2^32(~ 20亿,而不是~ 40亿)。