今日まで、私はそのように考えていました:
i += j;
ただの近道でした:
i = i + j;
しかしこれを試してみると:
int i = 5;
long j = 8;
i = i + j;
はコンパイルされませんが、i += j;
は正常にコンパイルされます。
それは実際にはi += j;
がこのi = (type of i) (i + j)
のようなものへの近道であることを意味しますか?
これらの質問と同様に、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);
言い換えれば、あなたの仮定は正しいです。
このキャストの良い例は* =または/ =を使うことです
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'
とても良い質問です。 Java言語仕様 はあなたの提案を裏付けるものです。
たとえば、次のコードは正しいです。
short x = 3; x += 4.6;
xの値は7になります。
short x = 3; x = (short)(x + 4.6);
はい、
基本的に書くとき
i += l;
コンパイラはこれを次のように変換します。
i = (int)(i + l);
.class
ファイルのコードを確認しました。
知っておくと良いこと
i = i + l
の場合はlong
からint
explicitly
にキャストする必要があります。そうするとコンパイルされ正しい出力が得られます。好き
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.
しかし+=
の場合、演算子は暗黙のうちに右変数の型から左変数の型への型キャストを行うので明示的に型変換する必要はないので、うまく動作します。
ここでの問題は型キャストです。
Intとlongを追加すると、
しかし+=
は型キャストをするような方法でコード化されています。 i=(int)(i+m)
Javaでは、代入操作の右側にある式の型が代入の左側にある変数の型に安全に昇格できるときに、型変換が自動的に行われます。したがって、安全に割り当てることができます。
byte - > short - > int - > long - > float - > double
同じことが逆にはうまくいきません。たとえば、longをintに自動的に変換することはできません。最初のものが2番目のものより多くの記憶域を必要とし、その結果情報が失われる可能性があるためです。そのような変換を強制するためには、明示的な変換を実行しなければなりません。
タイプ - 変換
時々、そのような質問は面接で尋ねられることができます。
たとえば、次のように書きます。
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
主な違いは、a = a + b
ではタイプキャストが行われないため、コンパイラはタイプキャストではないと怒っていることです。しかしa += b
を使うと、本当にしていることはb
をa
と互換性のある型に型変換することです。もしそうなら
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);
ここで微妙な点...
j
がdoubleでi
がintの場合、i+j
には暗黙の型キャストがあります。 Java _ always _ は、それらの間に演算があると整数を倍精度に変換します。
i
が整数でj
がdoubleであるi+=j
を明確にすると、
i = <int>(<double>i + j)
参照してください: この暗黙的キャストの説明
わかりやすくするために、この場合はj
を(int)
にタイプキャストすることをお勧めします。
Java言語仕様 E1 op= E2
がE1 = (T) ((E1) op (E2))
と同等であると定義します。ここでT
はE1
の型で、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 += b
がE1 += E2
に定義されていると、E1 = E1 + E2
はバイトに対して機能しません。前の例が示すように、それは確かに当てはまるでしょう。 +=
演算子をバイトとショートに対して機能させるためのハックとして、暗黙のキャストが含まれています。それほど大したことではありませんが、Java 1.0の作業の間は、最初に言語をリリースすることに焦点が当てられていました。現在、後方互換性のため、Java 1.0で導入されたこのハックは削除できませんでした。