12

byte 型または short 型の変数を宣言し、これらに対して算術演算を実行しようとすると、「型の不一致: int を short に変換できません」(または、対応する「型の不一致: int を byte に変換できません」) というエラーが表示されます。

byte a = 23;
byte b = 34;
byte c = a + b;

この例では、コンパイル エラーは 3 行目にあります。

4

4 に答える 4

11

算術演算子は任意の数値型で動作するように定義されていますが、Java 言語仕様 (5.6.2 Binary Numeric Promotion) に従って、型 byte および short のオペランドは、演算子に渡される前に自動的に int に変換されます。

byte 型または short 型の変数に対して算術演算を実行するには、式を括弧で囲み (その中で演算は int 型として実行されます)、結果を目的の型にキャストする必要があります。

バイト a = 23;
バイト b = 34;
バイト c = (バイト) (a + b);

次に、本当の Java の専門家への質問を次に示します。なぜですか。型 byte と short は完全に細かい数値型です。Java がこれらの型に対する直接算術演算を許可しないのはなぜですか? (そもそも int に変換する明らかな理由がないため、答えは「精度の低下」ではありません。)

更新: jrudolph は、こ​​の動作が JVM で使用可能な操作に基づいていること、具体的には、フルワード演算子とダブルワード演算子のみが実装されていることを示唆しています。したがって、bytes と short を操作するには、int に変換する必要があります。

于 2008-09-17T09:16:38.410 に答える
7

フォローアップの質問への回答は次のとおりです。

タイプ byte および short のオペランドは、演算子に渡される前に自動的に int に昇格されます

したがって、あなたの例でaは、両方とも+ 演算子に渡される前ににb変換されます。2 つの を一緒intに追加した結果もです。それを値に割り当てようとすると、精度が失われる可能性があるため、エラーが発生します。結果を明示的にキャストすることで、コンパイラに「自分が何をしているのか知っている」と伝えています。intintintbyte

于 2008-09-17T09:26:49.167 に答える
2

問題は、JVM がサポートするスタック値は、ワード サイズとダブル ワード サイズの 2 種類だけだと思います。

次に、スタック上のワードサイズの整数で機能する操作が 1 つだけ必要であると判断したのでしょう。そのため、バイトコード レベルでは iadd や imul などしかありません (バイトとショートの演算子はありません)。

したがって、これらの操作の結果として int 値が得られ、Java はこれをより小さな byte および short データ型に安全に戻すことができません。そのため、キャストして値をバイト/ショートに絞り込む必要があります。

しかし、最終的にはあなたの言うとおりです。たとえば、この動作は int の動作と一致しません。2 つの int を問題なく追加でき、結果がオーバーフローしてもエラーは発生しません。

于 2008-09-17T09:34:00.507 に答える
1

Java言語は、算術演算子の引数を常にint、long、float、またはdoubleにプロモートします。したがって、次の式を取ります。

a + b

ここで、aとbはバイト型です。これは次の略記です。

(int)a + (int)b

この式はint型です。バイト変数にint値を割り当てるときにエラーを出すことは明らかに理にかなっています。

なぜ言語はこのように定義されるのでしょうか?aが60、bが70であるとすると、a+bは-126-整数オーバーフローです。intになると予想されたより複雑な式の一部として、これは難しいバグになる可能性があります。バイトおよびショートからアレイへのストレージ、ファイル形式/ネットワークプロトコルの定数、およびパズルの使用を制限します。

JavaPolis 2007からの興味深い記録があります。JamesGoslingは、符号なし演算がいかに複雑であるか(そして、なぜJavaにないのか)について例を挙げています。Josh Blochは、彼の例は通常の符号付き算術でも間違った例を示していると指摘しています。わかりやすい算術演算には、任意精度が必要です。

于 2008-09-17T10:15:20.563 に答える