Java 为什么不是';本原

Java 为什么不是';本原,java,biginteger,primitive,Java,Biginteger,Primitive,如果使用BigInteger(或BigDecimal)并希望对其执行算术运算,则必须使用方法add或subtract。这听起来不错,直到你意识到 i += d + p + y; 对于biginger,将这样编写: i = i.add(d.add(p.add(y))); 正如你所看到的,读第一行稍微容易一些。如果Java允许运算符重载,但不允许,则可以解决此问题,因此这就引出了一个问题: 为什么biginger不是一个基本类型,因此它可以利用与其他基本类型相同的运算符?int和boolea

如果使用
BigInteger
(或
BigDecimal
)并希望对其执行算术运算,则必须使用方法
add
subtract
。这听起来不错,直到你意识到

 i += d + p + y;
对于
biginger
,将这样编写:

 i = i.add(d.add(p.add(y)));
正如你所看到的,读第一行稍微容易一些。如果Java允许运算符重载,但不允许,则可以解决此问题,因此这就引出了一个问题:


为什么
biginger
不是一个基本类型,因此它可以利用与其他基本类型相同的运算符?

int
boolean
char
不是基本类型,因此可以利用
+
//code>等运算符。由于历史原因,他们是原始人,其中最大的原因是表演

在Java中,原语被定义为那些不是成熟对象的东西。为什么要创建这些不寻常的结构(然后将它们重新实现为适当的对象,如
Integer
?主要是为了性能:对象上的操作比基元类型上的操作慢(现在也慢)。(正如其他答案所提到的,硬件支持使这些操作更快,但我不同意硬件支持是原语的“基本属性”。)


因此,一些类型接受“特殊处理”(并作为原语实现),而其他类型则没有。这样想:如果即使广受欢迎的
String
也不是基元类型,为什么
biginger
会是基元类型?

基元类型通常是处理器体系结构定义的历史类型。这就是为什么字节是8位,短是16位,int是32位,长是64位。也许当有更多的128位体系结构时,会创建一个额外的基元…但我看不出有足够的驱动器用于此…

这是因为
biginger
实际上并不是任何接近基元的东西。它是使用数组和一些附加字段实现的,各种操作包括复杂的操作。例如,下面是
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中也可以有非常简单的字节码

biginger
这样的复杂类型通常不能用这种方式处理,也不能转换为简单的字节码。它不能是原语


因此,您的问题可能是“为什么Java中没有运算符重载”。这是语言哲学的一部分



为什么不做个例外,比如
String
?因为不只是一个操作符例外。基本上,您需要为操作符
*
/
+
-
做一个例外,因为“primitive”的非正式含义是,它是可以直接用单个。换句话说,它们是原语,因为它们适合32位或64位字,这是CPU使用的数据体系结构,因此它们可以明确地存储在内存中

因此,您的CPU可以执行以下操作:

ADD REGISTER_3 REGISTER_2 REGISTER_1     ;;; REGISTER_3 = REGISTER_1 + REGISTER_2
可以占用任意大内存的BigInteger不能存储在单个寄存器中,它需要执行多个指令来进行简单的求和

这就是为什么它们不可能是基元类型,而现在它们实际上是带有方法和字段的对象,这是一种比简单基元类型复杂得多的结构


注意:我之所以称之为非正式的,是因为Java设计者最终可以定义一个“Java基元类型”作为他们想要的任何东西,他们拥有这个词,然而这只是模糊地同意使用这个词。

这是因为基元类型有一个大小限制。例如,int是32位,long是64位。因此,如果创建int类型的变量,JVM会在堆栈上为其分配32位内存。但对于BigInteger,它“理论上”没有大小限制。这意味着它可以任意增长。因此,无法知道其大小并在堆栈上为其分配固定的内存块。因此,它被分配到堆上,JVM总是可以在需要时增加大小

这个问题可能更适合这个网站。你的问题可以归结为为什么Java不支持操作符重载?这是对Java当前设计的质疑,我们可能知道也可能不知道确切的答案。原语是CPU支持直接操作的变量,使用
biginger
,情况并非如此。这是一个支持大(如果必须的话真的很大)数字的操作的类,这样的操作需要相当多的管理。因为它是一个类,而且Java不支持运算符重载,所以您需要使用它的方法,而不是与原语一起使用的简单算术运算符。@Havenard,+1表示CPU支持。@LuigImendoza Java可以支持BigInteger作为原语类型,即使没有运算符重载。问题是为什么不支持它作为一个基本类型。字节码的一个重要意义。值得注意的是,在其他语言(如JavaScript)中,字符串被视为基本类型——“基本类型”的概念相当不稳定,并且在某种程度上依赖于语言。尽管需要在各种库中提供支持,但将BigInteger作为基本类型仍然是可行的。我认为这样做没有任何技术障碍。即使缺乏CPU支持也不是一个论据:您必须记住,早期的CPU模拟了浮点运算,但仍然受到C等语言的支持。“请记住,字符串在Java语言规范中已经有一个特殊的位置”如何防止BigInteger或任何其他语言具有相同的特殊位置