Javaプログラミングにおける型変換とは、データ型を別の型に変換することだ。
このページではJavaの型変換の方法について、サンプルプログラムをいくつかご用意し解説した。参考にしていただければ幸いだ。
Javaにおける型変換とは
Javaの型変換とは、データの型を別の型へ変換することである。例えばint型の値を持つ変数の型を、計算精度を上げるためにdouble型に変換して計算を行うということがある。int型のままで割り算を繰り返し行うと、小数点以下の値が失われていくこと起こる可能性があるからである。
精度を求められる計算をするためには、どのような場合に型変換するべきか、型変換がどのように数値に影響を与えるかをあらかじめ理解しておくことは重要である。
このような型変換には大きく分けて次のようは種類がある。
- ワイドニング変換(Widening conversion)
- ナローイング変換(Narrowing conversion)
では、それらをひとつひとつ見ていこう。
ワイドニング変換(大きな型に小さな型を代入)
プリミティブ型に対する19の変換は、ワイドニング・プリミティブ変換と呼ばれる。これは、大きな型(より大きな数値を扱える型)に、小さな型(より小さな数値しか扱えない型)を代入する変換である。この場合は、そのままの値が代入される。
19の変換とは具体的に以下の変換である。
型 |
変換の方向 |
short |
int |
long |
float |
double |
byte |
→ |
○ |
○ |
○ |
○ |
○ |
short |
→ |
|
○ |
○ |
○ |
○ |
char |
→ |
|
○ |
○ |
○ |
○ |
int |
→ |
|
|
○ |
○ |
○ |
long |
→ |
|
|
|
○ |
○ |
float |
→ |
|
|
|
|
○ |
変換による値の正確さ
ワイドニング・プリミティブ変換では、次の場合に数値が正確に変換される。
- 整数型 → 他の整数型
- byte、shortもしくはchar型 → 浮動小数点型
- int型 → double型
逆に、数値が正確に変換されないのは次の場合である。これは、変換によって情報のある部分が失われるためである。
- int型 → float型
- long型 → float型
- long型 → double型
- float型→ double型
では、実際のプログラムで確認してみよう。
正確な値の型変換サンプルプログラム
このサンプルプログラムは、値を正確に代入することができる型変換を示している。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
public class WideningPrimitiveConversion { public static void main(String[] args) { byte byteMaxValue = Byte.MAX_VALUE;//[1] short shortMaxValue = Short.MAX_VALUE;//[2] int intMaxValue = Integer.MAX_VALUE;//[3] short shortFromByteValue = byteMaxValue;//[4] System.out.println("[5] byte -> short = " + byteMaxValue + " -> " +shortFromByteValue); float floatFromShortValue = shortMaxValue;//[6] System.out.println("[7] short -> float = " + shortMaxValue + " -> " + floatFromShortValue); int intFromShortValue = shortMaxValue;//[8] System.out.println("[9] ahort -> int = " + shortMaxValue + " -> " + intFromShortValue); long longFromIntValue = intMaxValue;//[10] System.out.println("[11] int -> long = " + intMaxValue + " -> " + longFromIntValue); double doubleFromIntValue = intMaxValue;//[12] System.out.println("[13] doubleFromIntValue= " + intMaxValue + " -> " + doubleFromIntValue); } } |
実行結果
1 2 3 4 5 |
[5] byte -> short = 127 -> 127 [7] short -> float = 32767 -> 32767.0 [9] ahort -> int = 32767 -> 32767 [11] int -> long = 2147483647 -> 2147483647 [13] int -> double = 2147483647 -> 2.147483647E9 |
サンプルプログラムの説明
それでは簡単にプログラムの解説をしてゆこう。
- [1] byte型の変数byteMaxValueの宣言をし、最大値MAX_VALUEを代入する。
- [2] short型の変数shortMaxValueの宣言をし、最大値MAX_VALUEを代入する。
- [3] int型の変数intMaxValueの宣言をし、最大値MAX_VALUEを代入する。
- [4] short型の変数shortFromByteValueの宣言をし、byteMaxValueを代入する。
- [5] [4]の代入による値の変化を表示する。
- [6] float型の変数floatFromShortValueの宣言をし、shortMaxValueを代入する。
- [7] [6]の代入による値の変化を表示する。
- [8] int型の変数intFromShortValueの宣言をし、shortMaxValueを代入する。
- [9] [8]の代入による値の変化を表示する。
- [10] long型の変数longFromIntValueの宣言をし、intMaxValueを代入する。
- [11] [10]の代入による値の変化を表示する。
- [12] double型の変数doubleFromIntValueの宣言をし、intMaxValueを代入する。
- [13] [12]の代入による値の変化を表示する。
正確に代入されない型変換サンプルプログラム
このサンプルプログラムは、値を正確に代入することができない型変換を示している。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
public class WideningPrimitiveConversionOfLostInformation { public static void main(String[] args) { int intMaxValue = Integer.MAX_VALUE;//[1] long longMaxValue = Long.MAX_VALUE;//[2] float floatMaxValue = Float.MAX_VALUE;//[3] float floatFromIntMaxValue = intMaxValue;//[4] System.out.println("[5] int -> float = " + intMaxValue + " -> " + floatFromIntMaxValue); float floatFromLongMaxValue = longMaxValue;//[6] System.out.println("[7] long -> float = " + longMaxValue + " -> " + floatFromLongMaxValue); double doubleFromLongMaxValue = longMaxValue;//[8] System.out.println("[9] long -> double = " + longMaxValue + " -> " + doubleFromLongMaxValue); double doubleFromFloatMaxValue = floatMaxValue;//[10] System.out.println("[11] float -> double = " + floatMaxValue + " -> " + doubleFromFloatMaxValue); } } |
実行結果
1 2 3 4 |
[5] int -> float = 2147483647 -> 2.14748365E9 [7] long -> float = 9223372036854775807 -> 9.223372E18 [9] long -> double = 9223372036854775807 -> 9.223372036854776E18 [11] float -> double = 3.4028235E38 -> 3.4028234663852886E38 |
サンプルプログラムの説明
簡単にプログラムの解説をしてゆこう。
- [1] int型の変数intMaxValueの宣言をし、最大値MAX_VALUEを代入する。
- [2] long型の変数longMaxValueの宣言をし、最大値MAX_VALUEを代入する。
- [3] float型の変数floatMaxValueの宣言をし、最大値MAX_VALUEを代入する。
- [4] float型の変数floatFromIntMaxValueの宣言をし、intMaxValueを代入する。
- [5] [4]の代入による値の変化を表示する。
- [6] float型の変数floatFromLongMaxValueの宣言をし、longMaxValueを代入する。
- [7] [6]の代入による値の変化を表示する。
- [8] double型の変数doubleFromLongMaxValueの宣言をし、longMaxValueを代入する。
- [9] [8]の代入による値の変化を表示する。
- [10] double型の変数doubleFromFloatMaxValueの宣言をし、floatMaxValueを代入する。
- [11] [10]の代入による値の変化を表示する。
ナローイング変換(小さな型に大きな型を代入)
プリミティブ型に対する22の変換は、ナローイング・プリミティブ変換と呼ばれる。これは、小さな型に大きな型を代入する変換である。そのまま代入できないので、キャスト演算子を使って変換する型を指定する。
書き方の基本は簡単だ。
新しい型の変数 = (新しい型)変数名;
例えばdouble型の変数の値をint型の変数bにキャストを使って変換すると、コードは次のようになる。
double a = 12.3;
int b = (int) a;
以下の表は、22のナローイング・プリミティブ変換を具体的に示したものである。
型 |
変換の方向 |
byte |
short |
char |
int |
long |
float |
short |
→ |
○ |
|
○ |
|
|
|
char |
→ |
○ |
○ |
|
|
|
|
int |
→ |
○ |
○ |
○ |
|
|
|
long |
→ |
○ |
○ |
○ |
○ |
|
|
float |
→ |
○ |
○ |
○ |
○ |
○ |
|
double |
→ |
○ |
○ |
○ |
○ |
○ |
○ |
ナローイング・プリミティブ変換は、数値全体の大きさ、精度、範囲についての情報を失う可能性がある。
では、どのように変換が行われるかをみてみよう。
符号付整数から整数型への変換
符号付整数の整数型へのナローイング変換は、変換後の型が持つn個のビット数分だけビットの値がコピーされる。このとき、コピーされるのは最下位からのビットの並びであり、他はみな捨てられる。数値の大きさについての情報を失う可能性に加えて、この変換結果の値は返還前の値の符号と異なるかもしれない。
サンプルプログラム
このサンプルプログラムは、int型からbyte型やshort型への変換によって上位のビットが失われることを示している。
1 2 3 4 5 6 7 8 9 10 11 12 |
public class NarrowingPrimitiveConversionIntegerToInteger { public static void main(String[] args) { int intValue = 0x12345678;//[1] byte byteValue = (byte)intValue;//[2] System.out.print("[3] int -> byte = 0x" + Integer.toHexString(intValue)); System.out.println(" -> 0x" + Integer.toHexString(byteValue)); short shortValue = (short)intValue;//[4] System.out.print("[5] int -> short = 0x" + Integer.toHexString(intValue)); System.out.println(" -> 0x" + Integer.toHexString(shortValue)); } } |
実行結果
1 2 |
[3] int -> byte = 0x12345678 -> 0x78 [5] int -> short = 0x12345678 -> 0x56787 |
サンプルプログラムの説明
それでは簡単にプログラムの解説をしていこう。
- [1] int型の変数intValueの宣言をし、0x12345678を代入する。
- [2] byte型の変数byteValueの宣言をし、intValueをbyte型でキャストして代入する。
- [3] [2]の代入による値の変化を表示する。
- [4] short型の変数shortValueの宣言をし、intValueをshort型でキャストして代入する。
- [5] [4]の代入による値の変化を表示する。
char型から整数型への変換
char型から整数型へのナローイング変換も、前のセクションの「符号付整数」同様にビットがコピーされる。また、この変換は数値の大きさについての情報を失う可能性に加えて、たとえchar型が16bitの符号無し整数値を表すとしても、結果の値がマイナスの数値になるかもしれない。
サンプルプログラム
このサンプルプログラムは、「A」の文字コード0x0410と「イ」の文字コード0x30A4をchar型の変数に代入し、それをナローイング変換してbyte型変数に代入している。確かに、「イ」の場合はマイナス値となる。
1 2 3 4 5 6 7 8 9 10 |
public class NarrowingPrimitiveConversionCharToByte { public static void main(String[] args) { char charAValue = 0x0410;//[1] byte byteValue = (byte)charAValue;//[2] System.out.println("[3] char -> byte = " + charAValue + " -> " + byteValue); char charIValue = 0x30A4;//[4] byteValue = (byte)charIValue;//[5] System.out.println("[6] char -> byte = " + charIValue + " -> " + byteValue); } } |
実行結果
1 2 |
[3] char -> byte = А -> 16 [6] char -> byte = イ -> -92 |
double型からfloat型への変換
doubleからfloatへのナローイング・プリミティブ変換は、IEEE754丸め込みの規則に従っている。この変換によって値の精度だけでなく範囲も失われる。結果としてゼロでないdouble型からfloat型ゼロへ、さらにはdouble型無限大からfloat型無限大になる場合がある。double型NaNはfloat型NaNへ変換され、double型無限大は同じ符号付のfloat型無限大に変換される。
サンプルプログラム
このサンプルプログラムは、double型からfloat型への変換を示している。Double型のいくつかの特殊な値、NaNや.POSITIVE_INFINITY;やNEGATIVE_INFINITYも扱っている。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
public class NarrowingPrimitiveConversionDoubleToFloat { public static void main(String[] args) { double doubleNearZeroValue = 1.2345E-58;//[1] double doubleNaNValue = Double.NaN;//[2] double doublePositiveInfinityValue = Double.POSITIVE_INFINITY;//[3] double doubleNegativeInfinityValue = Double.NEGATIVE_INFINITY;//[4] float floatValue = (float)doubleNearZeroValue;//[5] System.out.println("[6] NEAR ZERO -> float = " + doubleNearZeroValue + " -> " + floatValue); floatValue = (float)doubleNaNValue;//[7] System.out.println("[8] NaN -> float = " + doubleNaNValue + " -> " + floatValue); floatValue = (float)doublePositiveInfinityValue;//[9] System.out.println("[10] POSITIVE_INFINITY -> float = " + doublePositiveInfinityValue + " -> " + floatValue); floatValue = (float)doubleNegativeInfinityValue;//[11] System.out.println("[12] NEGATIVE_INFINITY -> float = " + doubleNegativeInfinityValue + " -> " + floatValue); } } |
実行結果
1 2 3 4 |
[6] NEAR ZERO -> float = 1.2345E-58 -> 0.0 [8] NaN -> float = NaN -> NaN [10] POSITIVE_INFINITY -> float = Infinity -> Infinity [12] NEGATIVE_INFINITY -> float = -Infinity -> -Infinity |
浮動小数点型から整数型への変換
浮動小数点型から整数型Tへのナローイング変換には2つのステップがある。最初のステップでは、浮動小数点数がlongかintに変換される。
この時、浮動小数点数がNaNであるならば、int型もしくはlong型0になる。もしそうでなければ、浮動小数点数が無限大でないならば、整数値Vに丸められ、次の変換が行われる。
- Tがlong型ならば、long型の値Vへの変換。
- Tがbyte型か、short型か、char型か、int型であればint型の値Vへの変換。
もしそうでない場合、次のふたつのケースのいずれかの変換が行われる。
- 値がとても小さい(大きなマイナス値もしくはマイナスの無限大)ならば、最初のステップの結果がint型もしくはlong型の表現可能な最小値になる。
- 値がとても大きい(大きなプラス値もしくはプラスの無限大)ならば、最初のステップの結果がint型もしくはlong型の表現可能な最大値になる。
次のステップで、long型かint型の値が最終的に目的の整数型Tに変換される。
- Tがint型もしくはlong型であるならば、変換の結果は最初のステップの結果となる。
- Tがbyte型、char型、もしくはshort型であるならば、変換の結果は最初のステップの値からT型へのナローイング変換された結果と同じとなる。
サンプルプログラム
このサンプルプログラムは、浮動小数点型から整数型への変換を示している。double型のいくつかの特殊な値、ゼロに近い値や.非常に大きい値や非常に小さい値も扱っている。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
public class NarrowingPrimitiveConversionFloatToInteger { public static void main(String[] args) { double doubleNearZero = 0.01;//[1] double double123456 = 123456.0;//[2] double doubleLargeValue = 1234567890123L;//[3] double doubleSmallValue = -1234567890123L;//[4] byte byteValue = (byte)doubleNearZero;//[5] System.out.println("[6] near zero -> byte = " + doubleNearZero + " -> " + byteValue); long longValue = (long)double123456;//[7] System.out.println("[8] 123456.0 -> long = " + double123456 + " -> " + longValue); short shortValue = (short)double123456;//[9] System.out.println("[10] 123456.0 -> short = " + double123456 + " -> " + shortValue); int intValue = (int) doubleLargeValue;//[11] System.out.println("[12] large -> int = " + doubleLargeValue + " -> " + intValue); intValue = (int) doubleSmallValue;//[13] System.out.println("[14] small -> int = " + doubleSmallValue + " -> " + intValue); } } |
実行結果
1 2 3 4 5 |
[6] near zero -> byte = 0.01 -> 0 [8] 123456.0 -> long = 123456.0 -> 123456 [10] 123456.0 -> short = 123456.0 -> -7616 [12] large -> int = 1.234567890123E12 -> 2147483647 [14] small -> int = -1.234567890123E12 -> -2147483648 |
まとめ
このページではJavaの型変換についてまとめてお伝えした。実際にサンプルプログラムを手元で動かしてみるとわかりやすいだろう。
参考にしていただければ幸いだ。
せっかくマトリクスを作っているのにサンプルプログラムが紐づいておらずどこのことを指したプログラムなのかわかりづらい。
言葉尻がちょいちょい変わった表現で読んでいて引っかかる。
~してゆこう、など。
ご指摘いただきありがとうございます。
型変換の数が多いため見づらくなっておりますが、各サンプルプログラムの実行結果である程度の判別が出来るようになっておりますので、そちらを参考にご覧頂ければと思います。
引き続き、ご愛読のほど、よろしくお願いいたします。