【Java】数値リテラルの暗黙的な型変換についてまとめてみた

Java SilverとJava Goldの試験勉強の中で、数値リテラルの暗黙的な型変換につまづいたのでまとめました。特にJava SilverやJava Goldを獲得したいと思っている方に、おすすめの記事です。
目次
より大きな数字を扱う型へは暗黙的に変換される
Javaには、数値を扱えるプリミティブ型がいくつかあります。これらの違いは扱える数値の範囲です。このとき、より大きな数字を扱う型への変換は暗黙的に行われます。
例えば、以下はコンパイルを通ります。byte型よりも、short型の方がより広い範囲の整数を扱えるからです。
“`Java
byte numByte = 1;
short numShort = numByte;
“`
逆に、より大きな数字を扱う型からより小さな数字を扱う型への変換は自動では行われません。コンパイルエラーが発生します。たとえ数値そのものが有効範囲の中であっても、です。あくまで型で判定される点に注意しましょう。
“`Java
short numShort = 1;
byte numByte = numShort; //エラー: 不適合な型: 精度が失われる可能性があるshortからbyteへの変換
“`
小数の場合は、float型からdouble型への変換は自動で行われますが、その逆はコンパイルエラーが発生します。
“`Java
//以下はできる
float numFloatA = 1.0F;
double numDoubleA = numFloatA;
//以下はできない
double numDoubleB = 1.0;
float numFloatB = numDoubleB; //エラー: 不適合な型: 精度が失われる可能性があるdoubleからfloatへの変換
“`
余談ですが、float型の変数に数値を代入する場合、数値の末尾に「F」をつける必要があります。小数点のある数値リテラルは、デフォルトではdouble型として扱われるためです。
また、float型とdouble型を使った計算の結果はdouble型になります。
型の違う数字で計算した場合は、より大きな数字を扱える型に変換される
型の違う数字同士で計算した場合は、より大きな数字を扱える型に変換されます。したがって、以下はコンパイルエラーになります。long型とbyte型の計算結果を、int型の変数に入れようとしているためです。
“`Java
short numShort = 1;
byte numByte = 1;
long numLong = 1;
int numInt = numByte + numLong; //エラー: 不適合な型: 精度が失われる可能性があるlongからintへの変換
“`
整数を扱う型から小数を扱う型へは暗黙的に変換できる
double型など小数を扱う型から、int型など整数を扱う型への変換は暗黙的に行われます。整数と小数で精度が高いのは後者であるためでしょう。
したがって、以下はコンパイルを通ります。
“`Java
int numInt = 1;
double numDouble = numInt;
System.out.println(numDouble); //「1.0」が表示される。
“`
なお、整数と小数の計算結果の型は、その小数の型に合わせられます。例えば、int型の変数とfloat型の変数を足した結果はfloat型になります。
プリミティブ型と対応するラッパークラスは相互に変換できる
プリミティブ型には、それぞれ対応するラッパークラスがあります。例えばint型に対応するのはIntegerクラスで、double型に対応するのはDoubleクラスです。
そして対応する型同士なら、相互に自動で型変換されます。
ラッパークラスを箱(box)と見立てて、プリミティブ型を入れることをオートボクシング、その逆をアンボクシングといいます。
例えば、以下はどちらもコンパイルを通ります。
“`Java
int numInt = 1;
Integer numInteger = numInt; //int型の変数をIntger型の変数に入れる
int numIntNew = numInteger; //Integer型の変数をint型の変数に入れる
“`
ボクシング、アンボクシングとその他の暗黙的な型変換は同時には実行されない
注意点として、ボクシング、アンボクシングとその他の暗黙的な型変換は同時には実行されません。コンパイルエラーが発生します。
具体的には、以下ができません。
- ラッパークラス同士の直接の型変換
- あるプリミティブ型から別のプリミティブ型のラッパークラスへの直接の型変換
したがって、以下のように段階を踏んで変換する必要があります。
“`Java
//以下はできる
Integer numIntegerB = 1;
int numIntB = numIntegerB;
double numDoubleB = numIntB;
Double numWrapDoubleB = numDoubleB;
System.out.println(numWrapDoubleB);
//以下はできない
Integer numIntegerA = 1;
Double numWrapDoubleA = numIntegerA; //エラー: 不適合な型: IntegerをDoubleに変換できません
“`
まとめ
この記事では、Javaの暗黙的な型変換について書きました。数値リテラルやそれが入っている変数を扱うときは、その数値リテラルや変数が現在どの型に入っていてどの型への変換が行われようとしているのか、注意しましょう。