如果您使用BigInteger
(或BigDecimal
)并希望对其进行算术运算,则必须使用方法add
或subtract
。这听起来不错,直到你意识到这一点
i += d + p + y;
对于BigInteger
:,会像这样写出来
i = i.add(d.add(p.add(y)));
正如您所看到的,第一行更容易阅读。这可以解决,如果Java允许运算符重载但它没有,所以这引出了一个问题:
为什么不是BigInteger
原始类型,因此它可以利用与其他原始类型相同的运算符?
答案 0 :(得分:16)
那是因为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
那样例外?因为它不仅仅是一个例外的运算符。您需要为运营商*
,/
,+
,-
,<<
,^
等制作例外情况。并且你仍然会在对象本身中有一些操作(比如pow
,它不是由Java中的运算符表示),对于基元来说,这些操作由专业类(如Math
)处理。
答案 1 :(得分:5)
从根本上说,因为&#34;原始&#34;的非正式含义。它的数据是可以直接使用单个CPU instruction处理的。换句话说,它们是原语,因为它们适合32或64位字,这是CPU使用的数据架构,因此它们可以明确地存储在registers中。
因此您的CPU可以执行以下操作:
ADD REGISTER_3 REGISTER_2 REGISTER_1 ;;; REGISTER_3 = REGISTER_1 + REGISTER_2
可以占用任意大量内存的BigInteger无法存储在单个REGISTER中,需要执行多条指令才能生成简单的总和。
这就是为什么不可能一个原始类型,现在它们实际上是具有方法和字段的对象,比简单的原始类型复杂得多。
注意:我之所以称之为非正式,是因为最终Java设计人员可以定义一个&#34; Java原始类型&#34;作为他们想要的任何东西,他们都拥有这个词,但是这个含义是模糊地使用了这个词。
答案 2 :(得分:2)
int
和boolean
以及char
不是原语,因此您可以利用+
和/
等运算符。由于历史原因,它们是原始的,其中最大的是性能。
在Java中,原语被定义为那些不是完全成熟的对象。为什么要创建这些不寻常的结构(然后将它们重新实现为适当的对象,如Integer
,稍后)?主要用于性能:对象上的操作比原始类型上的操作慢(并且)。 (正如其他答案所提到的,硬件支持使这些操作更快,但我不同意硬件支持是原语的“基本属性”。)
所以有些类型接受了“特殊处理”(并被实现为原语),而其他类型则没有。可以这样想:即使广受欢迎的String
不是原始类型,为什么BigInteger
会是?
答案 3 :(得分:1)
这是因为原始类型有大小限制。例如,int是32位,long是64位。因此,如果您创建int类型的变量,JVM会为堆栈分配32位内存。但至于BigInteger,它“理论上”没有大小限制。意思是它的大小可以任意增长。因此,无法知道其大小并在堆栈上为其分配固定的内存块。因此,它被分配在堆上,如果需要,JVM总是可以增加大小。
答案 4 :(得分:0)
原始类型通常是由处理器体系结构定义的历史类型。这就是为什么字节是8位,短是16位,int是32位,长是64位。也许当有更多的128位架构时,会创建一个额外的原语......但我看不出有足够的驱动器...