last revised: Sep./12th/2002
前節で変数の宣言と初期化についてまとめましたが、本節では異なる型同士の変換について見てみましょう。
同じ型の変数同士は代入出来ます。
double p = 3.1415; double circle = p;
この例では、変数 p
には数(リテラル)が代入されており、変数 circle
には変数 p
が代入されています。このとき、 circle
には、 p
に代入されている値が代入されることになります。変数に変数を代入するときは、右辺の変数が保持する値が、左辺の変数にコピーされると考えて良いでしょう。
基本データ型変数同士の代入では、右辺の変数の値が、左辺の変数にコピーされます。このとき、変数を別の型の変数に代入するときには、型変換が必要です。
型には大きさがあります。下図の矢印の方向に型のサイズは大きくなります。
byte -> short -> int -> long -> float -> double char ->
小さい型を大きい型に代入するときは自動的に型変換されます(拡張変換)。
int i = 10; float f = i; // int 型は float 型に代入可能 char c = 'a'; int i = c; // char 型は int 型に代入可能
例えば、byte 型は short, int, long, float, double 型に代入可能です。char 型は int, long, float, double 型に代入可能です。
逆に、大きい型を小さい型に代入するときは、演算精度の低下が起こるため、自動型変換はされません。明示的な型変換であるキャストが必要です(縮小変換)。
VarTest.java
:
class VarTest {
public static void main(String[] args) {
int i = 10;
short s;
s = i; // Error!
}
}
C:\>cd java C:\Java>javac VarTest.java VarTest.java:5: 精度が落ちている可能性 出現: int 要求: short s = i; // Error! ^ エラー 1 個 C:\Java>
例えば、double 型は byte 型に自動型変換されません。 int 型は char 型や short 型に自動型変換されません。一般に、拡張型変換以外は自動型変換されません。
リテラルにも型があり、その代入に対しても型チェックが行われます。リテラルの型は、簡単に言うと次のようになります。
リテラルの変数への代入も、変数同士の代入とほぼ同じです。次の例は拡張型変換なので、自動型変換されます。
int i = 'c'; // char 型は int 型に代入可能 float d = 10L; // long 型は float 型に代入可能
ただ一点だけ異なり、整数リテラルの整数型への代入時には、縮小型変換でも自動的に型変換されます。すなわち、次のコードは問題を生じません。
byte b = 10; // 10 は符号付整数リテラルなので int 型
このように整数が自動的に縮小型変換されるのは、リテラルに限ったことです。変数同士の代入の場合は、以下のコードは誤りです。
int i = 10; byte b = i; // コンパイルエラー
一つの式中に異なる型が混在するときも、自動的な型変換が起こります。型が自動的に変換される際の順番は、代入時の型変換と同じで、小さい型が大きい型に自動型変換されて演算されます。
char
, byte
, short
は int
型に合わせられる(整数拡張)VarTest.java
:
class VarTest {
public static void main(String[] args) {
int i = 100;
double d = 3.14;
// (int × double) の結果は double だと解釈される
System.out.println(i * d);
}
}
C:\Java>javac VarTest.java C:\Java>java VarTest 314.0 C:\Java>
演算時の型変換でも整数型は特別扱いされており、整数型は式中で最低でも int 型に昇格 (promote) されるので、次のコードは間違いです。
byte b1 = 10, b2 = 5; byte b3 = b1 * b2; // コンパイルエラー!
よく間違える例が次のものです。次のコードは3つとも同じ結果・・・にはなりません。
int i = 1988; double d1 = i * 105/100; double d2 = i * 1.05; // => 正しい結果 double d3 = i / 100 * 105;
d1 は 2087.0 、 d2 は 2087.4 、 d3 は 1995.0 となります。d1 の式中には int 型しか現れていないので、算術昇格の規則上、一切の型変換が発生しません。最後に d1 に代入するときだけ double 型に昇格します。d2 の式中には double 型が含まれています。二項演算子の演算対象の型が大きいほうに自動型変換されるので、式の結果は double 型になります。最後の d3 は今回のテーマとは異なりますが、「割ってから掛けるよりも、掛けてから割ったほうが良い」という例です。最初に i / 100 が計算されて、 19.88 -> 19 となり、これに 105 を掛けているので結果はとてもみすぼらしくなっています。