[英]Why isn't BigInteger a primitive
如果您使用BigInteger
(或BigDecimal
)并希望对它们执行算术运算,则必须使用方法add
或subtract
。 这听起来不错,直到你意识到这一点
i += d + p + y;
对于BigInteger
会这样写:
i = i.add(d.add(p.add(y)));
正如您所看到的,第一行阅读起来要容易一些。 如果Java允许运算符重载但是没有,这可以解决,所以这引出了一个问题:
为什么BigInteger
不是原始类型,因此它可以利用与其他原始类型相同的运算符?
那是因为BigInteger
实际上并不是任何接近原始的东西。 它使用数组和一些其他字段实现,各种操作包括复杂操作。 例如,这里是add
的实现:
public BigInteger add(BigInteger val) {
if (val.signum == 0)
return this;
if (signum == 0)
return val;
if (val.signum == signum)
return new BigInteger(add(mag, val.mag), signum);
int cmp = compareMagnitude(val);
if (cmp == 0)
return ZERO;
int[] resultMag = (cmp > 0 ? subtract(mag, val.mag)
: subtract(val.mag, mag));
resultMag = trustedStripLeadingZeroInts(resultMag);
return new BigInteger(resultMag, cmp == signum ? 1 : -1);
}
Java中的基元是通常由主机的CPU直接实现的类型。 例如,每台现代计算机都有一个用于整数加法的机器语言指令。 因此,它在JVM中也可以有非常简单的字节代码。
像BigInteger
这样的复杂类型通常不能以这种方式处理,也不能将其转换为简单的字节代码。 它不可能是原始的。
所以你的问题可能是“为什么没有运算符在Java中重载”。 嗯,这是语言哲学的一部分。
为什么不做一个例外,比如String
? 因为它不仅仅是一个例外的运算符。 您需要对运算符*
, /
, +
, -
, <<
, ^
等进行例外处理。 并且你仍然会在对象本身中进行一些操作(比如在Java中没有运算符表示的pow
),对于基元来说,这些操作由专业类(如Math
)处理。
从根本上说,因为“原始”的非正式含义是它的数据可以直接用单个CPU指令处理 。 换句话说,它们是原语,因为它们适合32或64位字,这是CPU使用的数据架构,因此它们可以明确地存储在寄存器中 。
因此您的CPU可以进行以下操作:
ADD REGISTER_3 REGISTER_2 REGISTER_1 ;;; REGISTER_3 = REGISTER_1 + REGISTER_2
可以占用任意大量存储器的BigInteger不能存储在单个REGISTER中,并且需要执行多个指令来进行简单求和。
这就是为什么它们不可能是原始类型,现在它们实际上是具有方法和字段的对象,比简单的基元类型复杂得多。
注意:我之所以称之为非正式的原因是因为Java设计人员最终可以将“Java原始类型”定义为他们想要的任何东西,他们拥有这个词,但这是模糊地使用这个词。
int
和boolean
和char
不是原语,因此您可以利用+
和/
等运算符。 由于历史原因,它们是原始的,其中最大的是性能。
在Java中,原语被定义为那些不是完全成熟的对象。 为什么要创建这些不寻常的结构(然后将它们重新实现为正确的对象,如后面的Integer
)? 主要用于性能:对象上的操作比原始类型上的操作慢(并且)。 (正如其他答案所提到的,硬件支持使这些操作更快,但我不同意硬件支持是原语的“基本属性”。)
因此,有些类型接受了“特殊处理”(并作为原语实现),而其他类型则没有。 可以这样想:即使广受欢迎的String
不是原始类型,为什么BigInteger
会是?
这是因为原始类型有大小限制。 例如,int是32位,long是64位。 因此,如果您创建int类型的变量,JVM会为堆栈分配32位内存。 但至于BigInteger,它“理论上”没有大小限制。 意思是它的大小可以任意增长。 因此,无法知道其大小并在堆栈上为其分配固定的内存块。 因此,它被分配在堆上,如果需要,JVM总是可以增加大小。
原始类型通常是由处理器体系结构定义的历史类型。 这就是为什么字节是8位,短是16位,int是32位,长是64位。 也许当有更多的128位架构时,会创建一个额外的原语......但我看不出有足够的驱动器...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.