78

shortJavaのプリミティブ型について質問があります。JDK 1.6 を使用しています。

私が以下を持っている場合:

short a = 2;
short b = 3;
short c = a + b;

コンパイラはコンパイルしたくありません-「intからshortに変換できません」と表示され、にキャストすることを提案しているためshort、次のようになります。

short c = (short) (a + b);

本当にうまくいきます。しかし、私の質問は、なぜキャストする必要があるのですか? a と b の値の範囲はshort- 短い値の範囲は {-32,768, 32767} です。また、操作を実行したいときにキャストする必要があります -、*、/ (他はチェックしていません)。

プリミティブ型に対して同じことを行う場合int、aa+bb を にキャストする必要はありませんint。以下はうまくいきます:

int aa = 2;
int bb = 3;
int cc = aa +bb;

short 型の 2 つの変数を追加する必要があるクラスを設計しているときに、これを発見しました。コンパイラは、キャストを行うように要求しました。type の 2 つの変数でこれを行う場合int、キャストする必要はありません。

ちょっとした注意: プリミティブ型でも同じことが起こりbyteます。したがって、これは機能します:

byte a = 2;
byte b = 3;
byte c = (byte) (a + b);

しかし、これはそうではありません:

byte a = 2;
byte b = 3;
byte c = a + b;

longfloatdouble、およびについては、intキャストする必要はありません。shortと のbyte値のみ。

4

11 に答える 11

64

短い C#で説明されているように(ただし、Java などの他の言語コンパイラについても)

short から int、long、float、double、または decimal への事前定義された暗黙的な変換があります。

ストレージ サイズが大きい非リテラル数値型を暗黙的に short 型に変換することはできません (整数型のストレージ サイズについては、整数型の表を参照してください)。たとえば、次の 2 つの短い変数 x と y について考えてみましょう。

short x = 5, y = 12;

次の代入ステートメントでは、代入演算子の右側の算術式がデフォルトで int に評価されるため、コンパイル エラーが発生します。

short z = x + y;   // Error: no conversion from int to short

この問題を解決するには、キャストを使用します。

short z = (short)(x + y);   // OK: explicit conversion

ただし、次のステートメントを使用することは可能ですが、宛先変数のストレージ サイズが同じか、それより大きくなっています。

int m = x + y;
long n = x + y;

良いフォローアップの質問は次のとおりです。

「代入演算子の右側の算術式がデフォルトで int に評価されるのはなぜですか」 ?

最初の答えは次の場所にあります。

整数定数の折りたたみの分類と正式な検証

Java 言語仕様では、整数の表現方法と整数算術式の評価方法が厳密に定義されています。このプログラミング言語はインターネット上の分散アプリケーションで使用するように設計されているため、これは Java の重要な特性です。Java プログラムは、それを実行するターゲット マシンに関係なく、同じ結果を生成する必要があります。

対照的に、C (および広く使用されている命令型およびオブジェクト指向プログラミング言語の大部分) は、よりずさんで、多くの重要な特性が未解決のままです。この不正確な言語仕様の背後にある意図は明らかです。同じ C プログラムは、ターゲット プロセッサに組み込まれた算術演算を使用してソース プログラムの整数演算をインスタンス化することにより、16 ビット、32 ビット、さらには 64 ビット アーキテクチャで実行されることになっています。これにより、使用可能なマシン操作を直接使用できるため、コードがはるかに効率的になります。整数計算が「十分に小さい」数値のみを扱う限り、矛盾は発生しません。

この意味で、C 整数演算は、プログラミング言語の仕様によって正確に定義されていないが、ターゲット マシンを決定することによってのみ完全にインスタンス化されるプレースホルダーです。

Java は、整数の表現方法と整数演算の計算方法を正確に定義します。

      Java Integers
--------------------------
Signed         |  Unsigned
--------------------------
long  (64-bit) |
int   (32-bit) |
short (16-bit) |  char (16-bit)
byte  (8-bit)  |

Char は唯一の符号なし整数型です。\u0000その値は からまで\uffff、つまり 0 から 2 16 -1までのUnicode 文字を表します。

整数演算子に long 型のオペランドがある場合、もう一方のオペランドも long 型に変換されます。それ以外の場合、演算は int 型のオペランドに対して実行され、必要に応じて短いオペランドは int に変換されます。変換規則は正確に指定されています。

[Electronic Notes in Theoretical Computer Science 82 No. 2 (2003)
Blesner-Blech-COCV 2003: Sabine GLESNER , Jan Olaf BLECH,
Fakultät für Informatik,
Universität Karlsruhe
Karlsruhe, Germany]

于 2009-01-25T14:42:31.167 に答える
17

編集:さて、Javaであることがわかりました...

Java 言語仕様のセクション 4.2.2 には、次のように記載されています。

Java プログラミング言語には、整数値に作用する多数の演算子が用意されています。

[...]

  • int または long 型の値になる数値演算子:
  • [...]
  • 加算演算子 + および - (§15.18)

  • 言い換えれば、C# のようなものです。加算演算子 (整数型に適用された場合) はintorになるだけです。そのため、変数longに代入するためにキャストする必要があります。short

    元の回答 (C#)

    C# では (言語を指定していないので推測しています)、プリミティブ型の加算演算子は次のとおりです。

    int operator +(int x, int y);
    uint operator +(uint x, uint y);
    long operator +(long x, long y);
    ulong operator +(ulong x, ulong y);
    float operator +(float x, float y);
    double operator +(double x, double y);
    

    これらは、C# 3.0 仕様のセクション 7.7.4 にあります。さらに、小数加算が定義されています。

    decimal operator +(decimal x, decimal y);
    

    (列挙加算、文字列連結、デリゲート結合もそこで定義されています。)

    ご覧のとおり、short operator +(short x, short y)演算子はありません。したがって、両方のオペランドが暗黙的に int に変換され、int 形式が使用されます。つまり、結果は「int」型の式であるため、キャストする必要があります。

    于 2009-01-25T14:46:09.943 に答える
    16

    C# および Java では、代入の右側の算術式はデフォルトで int に評価されます。明らかな理由から、int から short への暗黙的な変換形式がないため、short にキャストバックする必要があるのはそのためです。

    于 2009-01-25T14:41:27.347 に答える
    8

    「なぜデフォルトで int なのか」という質問に答えられていないことを考えると...

    まず、「デフォルト」は実際には適切な用語ではありません (十分に近いですが)。VonC で指摘されているように、int と long で構成される式は長い結果になります。ints/logs と double で構成される演算は、結果が double になります。コンパイラは、式の項を、結果の範囲や精度がより高い任意の型に昇格します (浮動小数点型は整数よりも範囲と精度が大きいと想定されますが、大きな long を double に変換すると精度が失われます)。

    1 つの注意点は、このプロモーションは必要な用語に対してのみ行われるということです。したがって、次の例では、部分式 5/4 は整数値のみを使用し、整数演算を使用して実行されますが、式全体には double が含まれます。結果はあなたが期待するものではありません...

    (5/4) * 1000.0
    

    では、なぜ byte と short が int に昇格されるのでしょうか? 私をバックアップするための参照がなければ、それは実用性によるものです.バイトコードの数は限られています.

    「バイトコード」は、その名前が示すように、1 バイトを使用して操作を指定します。たとえば、2 つの int を追加するiadd 。現在、205 個のオペコードが定義されており、整数演算には各タイプに18個 (つまり、integer と long の合計で 36 個) が必要ですが、変換演算子はカウントされません。

    短く、バイトごとに独自のオペコード セットがある場合は、241 になり、JVM の拡張機能が制限されます。私が言ったように、これを裏付ける参考文献はありませんが、ゴスリングらが「人々は実際にショーツをどのくらいの頻度で使用していますか?」と言ったのではないかと思います。一方、byte を int にプロモートすると、それほど素晴らしい結果にはなりません (予想される答えは 96 ですが、実際の答えは -16 です)。

    byte x = (byte)0xC0;
    System.out.println(x >> 2);
    
    于 2009-01-25T15:55:48.867 に答える
    5

    どの言語を使用していますか?

    多くの C ベースの言語には、数式が int 以上のサイズで実行されるという規則があります。このため、2 つの short を追加すると、結果は int 型になります。これにより、キャストが必要になります。

    于 2009-01-25T14:40:20.267 に答える
    2

    Java は常に、計算に少なくとも 32 ビットの値を使用します。これは、Java が導入された 1995 年に一般的だった 32 ビット アーキテクチャによるものです。CPU のレジスタ サイズは 32 ビットで、演算論理ユニットは CPU レジスタの長さの 2 つの数値を受け入れました。そのため、CPU はそのような値に合わせて最適化されました。

    これが、算術演算をサポートし、32 ビット未満のすべてのデータ型が、計算に使用するとすぐに int (32 ビット) に変換される理由です。

    要約すると、主にパフォーマンスの問題が原因であり、現在は互換性のために保持されています。

    于 2016-05-18T17:11:33.950 に答える
    1

    Java では、すべての数値式は次のようになります。

    anyPrimitive zas = 1;
    anyPrimitive bar = 3;
    ?? x = zas  + bar 
    

    x は常に、少なくとも int になるか、加算要素の 1 つが long の場合は long になります。

    しかし、いくつかの癖があります

    byte a = 1; // 1 is an int, but it won't compile if you use a variable
    a += 2; // the shortcut works even when 2 is an int
    a++; // the post and pre increment operator work
    
    于 2010-05-02T02:43:04.360 に答える
    1

    「int」より低いデータ型 (ブール値を除く) は、暗黙的に「int」に変換されます。

    あなたの場合:

    short a = 2;
    short b = 3;
    short c = a + b;
    

    (a+b) の結果は暗黙的に int に変換されます。そして今、あなたはそれを「短い」に割り当てています。そのため、エラーが発生しています。

    short,byte,char -- これらすべてについて、同じエラーが発生します。

    于 2014-09-26T10:27:24.430 に答える
    0

    まだ指摘されていないことを付け加えたいと思います。Javaは、変数(2および3)に指定した値を考慮しません...

    短いa=2; 短いb=3; 短いc=a + b;

    Javaが知る限り、これを行うことができます...

    短いa=32767; 短いb=32767; 短いc=a + b;

    これはshortの範囲外になりますが、結果がshortを超え、intを超えない可能性があるため、結果をintにオートボックス化します。基本的にほとんどの人が2,147,483,647を超える値または-2,147,483,648を下回る値をハードコーディングしないため、Intが「デフォルト」として選択されました。

    于 2009-01-30T11:29:29.177 に答える