为什么Java整数文字的默认类型是int而不是long?

时间:2013-02-05 02:13:50

标签: java integer literals

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

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

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

其次,在使用Long包装类时,程序员必须始终使用this SO question中所述的long文字符号。

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

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

7 个答案:

答案 0 :(得分:7)

此行为是设计 1 ,并在JLS: Java Language Specification中编纂。

首先,请注意, widening相关,这就是(有效)integer-literal被提升为long值的原因。相反,这与int literal

的规范有关
  

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

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


1 我不在推测为什么以这种方式工作,而像C#这样的语言有不同的规则。

答案 1 :(得分:3)

速度

只使用您需要的尺寸,您就可以提高效率。对于从-2 ^ 31到2 ^ 31的数字,int是合适的。如果你使用int就足够了,那么你的代码会变慢。例如,此代码在我的机器上以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;
  }

}

答案 2 :(得分:2)

int默认文字的一个可能原因是使用lont可能导致难以检测多线程应用程序中的错误,如JLS 17.7 Non-atomic Treatment of double and long中所述。

  

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

答案 3 :(得分:1)

我认为你是对的,今天long会更好。早在1995年,long可能太长而无法成为默认值。

答案 4 :(得分:0)

对于

Long x = 250;

那不行。 Java使用Autoboxing,它从Object代表类自动转换为基本类型。至于其他的,int只是使用的主要数字类型。多头,至少对于我最常使用它们来说,仅用于日期和时间。另一方面,整数用于其他所有内容。

如果你真的想进入细节,我相信这会让你的摇摇晃晃更多:

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

在这种情况下,当涉及小数时,double取优先级。

答案 5 :(得分:0)

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

答案 6 :(得分: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中,不同大小的数字文字具有不同的语义。如果将int乘以常数128,则int必须不大于16,777,215,否则将发生溢出。如果将int与常量128L相乘,则结果可能只存储在可接受long的某个位置。