这对我来说似乎是一个奇怪的疏漏,因为它允许编写的代码更不容易在意外大输入时产生溢出。
此外,使用无符号整数可以作为自我说明的形式,因为它们表明无符号整数所表示的值不应该是负数。
最后,在某些情况下,无符号整数可以更有效地进行某些操作,例如除法。
包括无符号整数有何不利之处?
这是一篇关于简洁性的与Gosling和其他人的采访:
Gosling:对我来说,作为一名语言设计师(虽然我现在并不认为自己是),“简单”真正意味着我是否可以期望J. Random Developer能够将规范记在脑中。这个定义表明,例如,Java并不是一个简单的语言——实际上,很多这样的语言最终都会有很多边角情况,没有人真正理解。询问任何C开发人员关于无符号数的问题,很快你就会发现几乎没有C开发人员真正了解无符号数以及无符号算术是什么。这些事情使得C变得复杂。Java的语言部分,我认为相当简单。你需要查找的是库。
从字里行间看,我认为这个逻辑大概是这样的:
总的来说,我觉得这是个合理的决定。可能,我会:
尽管需要一些折腾,但对于最多 32 位的无符号值的操作并不太糟糕,大多数人不需要 64 位无符号除法或比较。
short
的使用频率 - deflate/gzip/inflate算法使用16位数据,因此它们在很大程度上依赖于short... 或至少是short[]
数组[尽管它们是本地化的,但Java实现的算法处理着以太字节的数据]. 相对于int[]
而言,short[]
具有显著的优势,因为它占用的内存空间只有一半,并且更少的内存=更好的缓存属性,表现更出色。 - bestsss这是一个较旧的问题,Pat在简要提及char的同时,我认为我应该为其他将来查看此问题的人扩展一下。让我们仔细看一下Java原始类型:
byte
- 8位有符号整数
short
- 16位有符号整数
int
- 32位有符号整数
long
- 64位有符号整数
char
- 16位字符(无符号整数)
虽然char
不支持unsigned
算术运算,但它基本上可以被视为一个unsigned
整数。您需要显式地将算术操作强制转换回char
,但它为您提供了一种指定unsigned
数字的方式。
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--;
显然,Java没有直接支持无符号整数(否则,如果有直接支持,我就不必将大部分操作强制转换为char类型)。但是,肯定存在一种无符号原始数据类型。我希望也能看到无符号字节,但我想双倍的内存成本和使用char代替是一个可行的选择。
JDK8提供了新的API用于long
和int
值如同无符号值处理时提供帮助的Long
和Integer
。
compareUnsigned
divideUnsigned
parseUnsignedInt
parseUnsignedLong
remainderUnsigned
toUnsignedLong
toUnsignedString
此外,Guava 提供了许多辅助方法来执行类似于整数类型的操作,这有助于弥补缺乏本地支持的 unsigned
整数的差距。
char
太小了,无法支持 long
算术运算,例如。 - user586399Java确实有无符号类型,或者至少有一个:char是无符号的短整型。所以不管Gosling提出什么借口,为什么没有其他无符号类型,那都只是他无知的表现。
另外,短整型(Short)也经常用于多媒体中。原因是你可以在单个32位无符号长整型中放置2个样本,并向量化许多操作。对于8位数据和无符号字节,同理。你可以将4个或8个样本放入寄存器以进行向量化处理。
一旦在表达式中混合使用有符号和无符号整数,情况就变得混乱了,您可能会丢失信息。将Java限制为仅使用有符号整数确实清理了事情。虽然我有时会想念字节中的第8位,但我很高兴不必担心整个有符号/无符号业务。
static_cast
,这样做确实很混乱。 - Raedwald& 0xFF
运算只会让代码变得更加混乱。 - bit2shifthttp://skeletoncoder.blogspot.com/2006/09/java-tutorials-why-no-unsigned.html
这个人说因为C标准定义了涉及无符号和有符号整数的操作被视为无符号,这可能导致负有符号整数转换为大的无符号整数,潜在地引起错误。±26
。对于未知值的正确处理是使用某种形式的Option<TArg>
,其中 Some(25) - None
将返回 None
。 - Be Brave Be Like Ukraine我认为Java目前的状态很好,添加无符号整数将会使它变得更复杂,收益并不大。即使采用简化的整数模型,大多数Java程序员也不知道基本数字类型的行为 - 只需阅读Java Puzzlers这本书,就能看到你可能持有的一些误解。
至于实际建议:
如果你的值具有任意大小并且不适合int
,请使用long
。如果它们不适合long
,请使用BigInteger
。
仅在需要节省空间时才使用较小的类型来处理数组。
如果你需要精确的64/32/16/8位,请使用long
/int
/short
/byte
,并停止担心符号位,除了除法、比较、右移和强制类型转换之外。
另请参阅关于“从C到Java移植随机数生成器”的此答案。
>>
和无符号的 >>>
。左移操作没有问题。 - starblue>>>
对于 short
和 byte
不起作用。例如,(byte)0xff>>>1
的结果是 0x7fffffff
而不是 0x7f
。另一个例子:byte b=(byte)0xff; b>>>=1;
的结果将是 b==(byte)0xff
。当然,你可以使用 b=(byte)(b & 0xff >> 1);
但这会增加一次操作(按位与)。 - CITBL我知道这篇文章已经很老了,但是对于你的兴趣,从Java 8开始,你可以使用int
数据类型来表示无符号32位整数,它的最小值为0,最大值为232−1。使用Integer
类将int
数据类型用作无符号整数,并且像compareUnsigned()
、divideUnsigned()
等静态方法已被添加到Integer
类中,以支持无符号整数的算术运算。
在JDK8中,它确实支持了一些无符号类型。
尽管Gosling有所担忧,但我们可能会看到Java对无符号类型的完全支持。