変数と自動型変換

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;	// コンパイルエラー

演算時の型変換

一つの式中に異なる型が混在するときも、自動的な型変換が起こります。型が自動的に変換される際の順番は、代入時の型変換と同じで、小さい型が大きい型に自動型変換されて演算されます。

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 を掛けているので結果はとてもみすぼらしくなっています。



Copyright © 2001-2002 SUGAI, Manabu. All Rights Reserved.