我经常听到有人抱怨Java没有未签名的数据类型。请参阅示例this评论。我想知道这是一个什么问题?我或多或少地用Java编程了10年,从未遇到过问题。偶尔将字节转换为int时需要& 0xFF
,但我不认为这是一个问题。
由于无符号和带符号的数字用相同的位值表示,因此我能想到签名最重要的地方是:
相反,我发现我不需要考虑无符号和有符号数之间的操作以及它们之间的转换。我错过了什么?在编程语言中使用无符号类型有什么实际好处?如何让Java更好?
答案 0 :(得分:10)
偶尔将字节转换为ints a&需要0xFF,但我不认为这是一个问题。
为什么不呢? “应用按位AND和0xFF”实际上是代码试图表示的部分吗?如果没有,为什么要写它呢?我实际上发现,除了将它们从一个地方复制到另一个地方之外,几乎任何我想用字节做什么,最后需要一个掩码。我希望我的代码无懈可击;缺少无符号字节妨碍了这一点:(
此外,请考虑一个API 始终返回非负值,或仅接受非负值。使用无符号类型可以清楚地表达,无需验证。就个人而言,我认为在.NET中不使用无符号类型 more 是很遗憾的,例如对于诸如String.Length
,ICollection.Count
之类的东西等。值很自然只是非负的。
Java中缺少无符号类型是一个致命的缺陷吗?显然不是。这是一个烦恼吗?绝对
你引用的评论击中了头上的钉子:
Java缺乏无符号数据类型也不符合它。是的,您可以解决它,但它并不理想,您将使用不能正确反映基础数据的代码。
假设你 与另一个需要无符号16位整数的系统进行互操作,并且你想要表示数字65535.你声称“数据只是位,所以我看不到这里的问题“ - 但必须传递-1表示65535 是一个问题。在编写,读取和测试代码时,数据表示与其基本含义之间的任何阻抗不匹配都会引入额外的速度突发。
相反,我觉得更容易,我不需要考虑无符号和有符号数之间的操作以及它们之间的转换。
您需要考虑这些操作的唯一时间是您自然地处理两种不同类型的值 - 一种是有符号的,一种是无符号的。那时,绝对希望指出这一点。使用带符号的类型来表示自然无符号值时,应该仍然在考虑差异,但事实上你应该对它隐藏。考虑:
// This should be considered unsigned - so a value of -1 is "really" 65535
short length = /* some value */;
// This is really signed
short foo = /* some value */;
boolean result = foo < length;
假设foo
为100且length
为-1。什么是逻辑结果? length
的值代表 65535,因此逻辑foo
小于它。但是你可能会使用上面的代码并得到错误的结果。
当然,他们甚至不需要在这里代表不同的类型。它们都可以是自然无符号值,表示为有符号值,负数在逻辑上大于正数。如果您使用该语言中的无符号类型,则同样的错误也适用,并且不会成为问题。
您可能还想阅读this interview with Joshua Bloch(Google缓存,因为我相信它现在已经从java.sun.com消失了),包括:
哦,好问题......我要说的是Java平台最奇怪的事情是字节类型是签名的。我从来没有听过这个解释。这是违反直觉的,会导致各种错误。
答案 1 :(得分:2)
如果你愿意,是的,一切都是零和零。但是,您的硬件算术和逻辑单元不能以这种方式工作。如果要将位存储在有符号整数值中但执行对于有符号整数不自然的操作,则通常会浪费存储空间和处理时间。
无符号整数类型在相同的空间中存储两倍于相应有符号整数类型的非负值。因此,如果您想将带有无符号值的语言中常用的任何数据(例如通常与C一起使用的POSIX日期值(无符号秒数))接收到Java,那么通常您将需要使用更宽的整数类型比C会用。如果您正在处理许多此类值,则会浪费存储空间和获取执行时间。
答案 2 :(得分:0)
我使用无符号数据类型的时间是在我读取与图像对应的大块数据或使用openGL时。我个人更喜欢未签名,如果我知道某些东西永远不会是负面的,作为各种“安全特征”。
无符号类型对于逐位比较很有用,我很确定它们在图形中被广泛使用。