16

我很困惑为什么 Java 整数文字默认为int而不是long. 这似乎造成了不必要的混乱。

long首先,它要求程序员在为超过最大int大小 (2147483647)的 a 赋值时采用特殊语法(将“L”附加到文字)。

long x = 2147483647; // Compiles
long y = 2147483648; // Does not compile
long z = 2147483648L; // Compiles

其次,在使用Long包装类时,程序员必须始终使用这个 SO questionlong中解释的文字表示法。

Long x = 250; // Does not compile
Long y = 250L; // Compiles

第三,考虑到从int文字到“较窄”数据类型 (shortbyte) 的隐式转换在所有情况下都可以正常工作(据我所知),似乎简单地使所有整数文字类型long成为明显的解决方案......对? 这难道不会完全消除在特殊情况下将“L”附加到整数文字的奇怪系统的需要吗?

4

7 回答 7

8

此行为是设计1并编入JLS: Java Language Specification

首先,请注意,这与扩展无关,这就是为什么(有效)整数文字被提升为长值的原因。相反,这与int literal的规范有关:

如果十六进制、八进制或二进制 int 文字不适合 32 位,则会出现编译时错误。

最小和最大的有符号 32 位整数值分别为 -2147483648 和 2147483647。


1我不在乎推测它为什么会这样工作,并且像 C# 这样的语言有不同的规则。

于 2013-02-05T03:14:28.273 回答
3

速度

仅使用所需的大小即可提高效率。int 适用于从 -2^31 到 2^31 的数字。如果在 int 就足够的地方使用 long ,则会减慢代码速度。例如,这段代码在我的机器上运行时间为 7.116 秒。通过将其切换为使用 int,我将机器上的运行时间减少到 3.74 秒:

public class Problem005 {

  private static boolean isDivisibleByAll(long n, long ceiling) {
    for (long i = 1; i < ceiling; i++)
      if (n % i != 0)
        return false;
    return true;
  }

  public static long findSmallestMultiple (long ceiling) {
    long number = 1;
    while (!isDivisibleByAll(number, ceiling))
      number++;
    return number;
  }

}

public class Stopwatch {
  private final long start;

  public Stopwatch() {
    start = System.currentTimeMillis();
  }

  public double elapsedTime() {
    long now = System.currentTimeMillis();
    return (now - start) / 1000.0;
  }

}

public class Main {

  public static void main(String[] args) {

    Stopwatch stopwatch005 = new Stopwatch();

    long highestMultiple = 20;
    long findSmallestMultipleOutput = findSmallestMultiple(highestMultiple);
    double findSmallestMultipleTime = stopwatch005.elapsedTime();
    System.out.println("Problem #005");
    System.out.println("============");
    System.out.print("The multiple of the numbers 1-" + highestMultiple + " is = ");
    System.out.print(findSmallestMultipleOutput);
    System.out.println(" with a time of " + findSmallestMultipleTime + " seconds.\n ");
  }   
}

改为使用 int:

public class Problem005 {

  private static boolean isDivisibleByAll(int n, int ceiling) {
    for (int i = 1; i < ceiling; i++)
      if (n % i != 0)
        return false;
    return true;
  }

  public static int findSmallestMultiple (int ceiling) {
    int number = 1;
    while (!isDivisibleByAll(number, ceiling))
      number++;
    return number;
  }

}
于 2013-02-05T02:30:16.117 回答
2

默认文字的可能原因之一int是使用lont可能会导致难以检测到多线程应用程序中的错误,如JLS 17.7 非原子处理 double 和 long中所述。

出于 Java 编程语言内存模型的目的,对非易失性long 或 double 值的单次写入被视为两次单独的写入:每个 32 位一半。这可能导致线程从一次写入中看到 64 位值的前 32 位,而从另一次写入中看到后 32 位。

于 2013-02-05T03:09:55.050 回答
1

我认为你是对的,long今天会是一个更好的默认值。回到 1995 年,long可能太长而不能成为默认值。

于 2013-02-05T02:27:02.213 回答
0

为了

Long x = 250;

那是行不通的。Java 使用自动装箱,它自动从对象代表类转换为原始类型。至于其他的,int 只是使用的主要数字类型。至少对于我最常使用它们的用途而言,Long 仅用于日期和时间。另一方面,整数默认用于其他所有内容。

如果你真的想了解细节,我相信这会让你的吉米更加沙沙作响:

float pi = 3.14; // Does not compile.
float pi = 3.14F; // Compiles

同样在这种情况下,当涉及小数时,双精度优先。

于 2013-02-05T02:17:16.970 回答
0

我认为使 int 文字不需要类型指示的原因是 int 旨在成为普通的整数类型。同样,double 是普通的浮点类型。这个想法似乎是通过默认为最常见的类型来限制需要类型指示的文字数量。

于 2013-02-05T02:22:31.253 回答
0

如果中间结果是用最长的整数类型计算的,那么语言可能会要求所有不会溢出的整数算术,就好像它们是一样的。在这样的语言中,如果以 L 开头的变量是 64 位,以 W 开头的是 32 位,而以 H 开头的是 16 位,表达式如下

L1 = W1*W2;
W3 = (W1+W2) >> 1

将以这样的方式进行评估以避免溢出,但是像这样的表达式

W4 = W1+W2

将使用 32 位数学进行评估(因为即使中间结果被评估为 32 位,分配给 W4 也会发生任何溢出),以及类似的表达式

W5 = (H1*H2) >> 1

可以评估为 32 位,因为结果不能溢出 32 位值。

这种语言在大多数情况下可能非常有效,因为编译器通常不难确定每个子表达式的最大相关整数大小。在这样的语言中,数字文字是“long”还是“int”并不重要,因为编译器会对它的数值更感兴趣。

然而,在 Java 中,不同大小的数字文字具有不同的语义。如果将 an 乘以int常数 128,则int必须不大于 16,777,215,否则将发生溢出。如果将 乘以int一个常数128L,则结果可能只存储在可以接受 的某个地方long

于 2013-02-05T03:54:33.730 回答