16

なぜ Java 整数リテラルのデフォルトがintではなく なのか混乱していますlong。これは不必要な混乱を招くようです。

まず、プログラマは、最大サイズ (2147483647)longを超える値を a に割り当てるときに、特別な構文 (リテラルに "L" を追加する) を採用する必要があります。int

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

次に、ラッパー クラスを使用する場合、プログラマーはこの SO questionLongで説明されているように、常にlongリテラル表記を使用する必要があります。

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

int第三に、リテラルから「より狭い」データ型への暗黙的な変換(shortおよびbyte) が (私が知っている) すべての状況でうまく機能することを考えると、単純にすべての整数リテラルを型longにすることが明らかな解決策だったようです...そうです? これにより、特殊な場合に整数リテラルに "L" を追加するこの奇妙なシステムの必要性が完全になくなるのではないでしょうか?

4

7 に答える 7

8

この動作は仕様1によるものであり、 JLS: Java 言語仕様で成文化されています。

まず、これは(有効な) 整数リテラルが long 値に昇格される理由である拡大とは関係がないことに注意してください。代わりに、これはint リテラルの仕様そのものに関連しています。

16 進数、8 進数、または 2 進数の 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デフォルトのリテラルである考えられる理由の 1 つは、JLS 17.7 非アトミック処理の double および long でlont指定されているように、使用するとマルチスレッド アプリケーションでエラーを検出するのが困難になる可能性があることです。

Java プログラミング言語のメモリ モデルの目的上、不揮発性の long または double 値への 1 回の書き込みは、2 つの個別の書き込み (32 ビットの半分ごとに 1 回) として扱われます。これにより、スレッドが 1 つの書き込みから 64 ビット値の最初の 32 ビットを参照し、別の書き込みから 2 番目の 32 ビットを参照する状況が発生する可能性があります。

于 2013-02-05T03:09:55.050 に答える
1

私はあなたが正しいと思います、long今日はより良いデフォルトになるでしょう。1995年にlongは、おそらく長すぎてデフォルトにはなりませんでした。

于 2013-02-05T02:27:02.213 に答える
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 では、異なるサイズの数値リテラルは異なるセマンティクスを持ちます。intanに定数 128 を掛ける場合、intは 16,777,215 を超えてはならず、さもないとオーバーフローが発生します。intに定数を掛ける128Lと、結果は を受け入れることができる場所にのみ格納されlongます。

于 2013-02-05T03:54:33.730 に答える
0

のために

Long x = 250;

それはうまくいきません。Java は、オブジェクト代表クラスからプリミティブ型に自動的にキャストするオートボクシングを使用します。他のものに関しては、int は使用される主要な数値型です。long は、少なくとも私が最も頻繁に使用する目的では、日付と時刻のみに使用されます。一方、整数はデフォルトで他のすべてに使用されます。

あなたが本当に詳細に入りたいのなら、これはあなたのジミーをもっとざわめかせると確信しています:

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

この場合も、10 進数が含まれる場合は double が優先されます。

于 2013-02-05T02:17:16.970 に答える