web-dev-qa-db-ja.com

なぜJavaの+ =、 - =、* =、/ =複合代入演算子はキャストを必要としないのですか?

今日まで、私はそのように考えていました:

i += j;

ただの近道でした:

i = i + j;

しかしこれを試してみると:

int i = 5;
long j = 8;

i = i + j;はコンパイルされませんが、i += j;は正常にコンパイルされます。

それは実際にはi += j;がこのi = (type of i) (i + j)のようなものへの近道であることを意味しますか?

3464
Honza Brabec

これらの質問と同様に、JLSが答えを持っています。この場合 §15.26.2複合代入演算子 。抜粋:

E1 op= E2という形式の複合代入式は、E1 = (T)((E1) op (E2))と同じです。ここで、Tは、E1の型です。ただし、E1は1回だけ評価されます。

§15.26.2 から引用された例

[...]次のコードは正しいです。

short x = 3;
x += 4.6;

xの値は7になります。

short x = 3;
x = (short)(x + 4.6);

言い換えれば、あなたの仮定は正しいです。

2339
Lukas Eder

このキャストの良い例は* =または/ =を使うことです

byte b = 10;
b *= 5.7;
System.out.println(b); // prints 57

または

byte b = 100;
b /= 2.5;
System.out.println(b); // prints 40

または

char ch = '0';
ch *= 1.1;
System.out.println(ch); // prints '4'

または

char ch = 'A';
ch *= 1.5;
System.out.println(ch); // prints 'a'
464
Peter Lawrey

とても良い質問です。 Java言語仕様 はあなたの提案を裏付けるものです。

たとえば、次のコードは正しいです。

short x = 3;
x += 4.6;

xの値は7になります。

short x = 3;
x = (short)(x + 4.6);
241
Thirler

はい、

基本的に書くとき

i += l; 

コンパイラはこれを次のように変換します。

i = (int)(i + l);

.classファイルのコードを確認しました。

知っておくと良いこと

179
Umesh Awasthi

i = i + lの場合はlongからintexplicitlyにキャストする必要があります。そうするとコンパイルされ正しい出力が得られます。好き

i = i + (int)l;

または

i = (int)((long)i + l); // this is what happens in case of += , dont need (long) casting since upper casting is done implicitly.

しかし+=の場合、演算子は暗黙のうちに右変数の型から左変数の型への型キャストを行うので明示的に型変換する必要はないので、うまく動作します。

90
dku.rajkumar

ここでの問題は型キャストです。

Intとlongを追加すると、

  1. Intオブジェクトはlongにキャストされ、両方が追加されてlongオブジェクトになります。
  2. しかし、長いオブジェクトは暗黙的にint型にキャストすることはできません。だから、あなたは明示的にそれをしなければなりません。

しかし+=は型キャストをするような方法でコード化されています。 i=(int)(i+m)

61

Javaでは、代入操作の右側にある式の型が代入の左側にある変数の型に安全に昇格できるときに、型変換が自動的に行われます。したがって、安全に割り当てることができます。

  byte  - > short  - > int  - > long  - > float  - > double 

同じことが逆にはうまくいきません。たとえば、longをintに自動的に変換することはできません。最初のものが2番目のものより多くの記憶域を必要とし、その結果情報が失われる可能性があるためです。そのような変換を強制するためには、明示的な変換を実行しなければなりません。
タイプ - 変換

52
tinker_fairy

時々、そのような質問は面接で尋ねられることができます。

たとえば、次のように書きます。

int a = 2;
long b = 3;
a = a + b;

自動型キャストはありません。 C++では上記のコードをコンパイルしてもエラーは発生しませんが、JavaではIncompatible type exceptionのようなものになります。

それを避けるために、あなたはこのようにあなたのコードを書かなければなりません:

int a = 2;
long b = 3;
a += b;// No compilation error or any exception due to the auto typecasting
43
Stopfan

主な違いは、a = a + bではタイプキャストが行われないため、コンパイラはタイプキャストではないと怒っていることです。しかしa += bを使うと、本当にしていることはbaと互換性のある型に型変換することです。もしそうなら

int a=5;
long b=10;
a+=b;
System.out.println(a);

あなたが本当にやっているのは、

int a=5;
long b=10;
a=a+(int)b;
System.out.println(a);
22
takra

ここで微妙な点...

jがdoubleでiがintの場合、i+jには暗黙の型キャストがあります。 Java _ always _ は、それらの間に演算があると整数を倍精度に変換します。

iが整数でjがdoubleであるi+=jを明確にすると、

i = <int>(<double>i + j)

参照してください: この暗黙的キャストの説明

わかりやすくするために、この場合はj(int)にタイプキャストすることをお勧めします。

11
Gabe Nones

Java言語仕様 E1 op= E2E1 = (T) ((E1) op (E2))と同等であると定義します。ここでTE1の型で、E1は1回評価されます

それは技術的な答えですが、なぜそれがケースなのか疑問に思うかもしれません。では、次のプログラムを考えてみましょう。

public class PlusEquals {
    public static void main(String[] args) {
        byte a = 1;
        byte b = 2;
        a = a + b;
        System.out.println(a);
    }
}

このプログラムは何を印刷しますか?

あなたは3を推測しましたか?残念ながら、このプログラムはコンパイルされません。どうして?まあ、Java にバイトを追加するとint を返すように定義されていることが起こります。これは、Java仮想マシンがバイトコードを節約するためのバイト操作を定義していないためです(結局、整数操作を使用するのが言語で公開されている実装の詳細です)。

しかし、a = a + bが機能しない場合、a += bE1 += E2に定義されていると、E1 = E1 + E2はバイトに対して機能しません。前の例が示すように、それは確かに当てはまるでしょう。 +=演算子をバイトとショートに対して機能させるためのハックとして、暗黙のキャストが含まれています。それほど大したことではありませんが、Java 1.0の作業の間は、最初に言語をリリースすることに焦点が当てられていました。現在、後方互換性のため、Java 1.0で導入されたこのハックは削除できませんでした。

0
Konrad Borowski