データには整数型、文字型、小数型、論理型などの種類があります。
例えば、整数を扱うなら、short型・int型・long型のいずれか、文字を扱うならchar型といった具合に、用途に合わせて様々な型が用意されています。
それは裏を返せば、型をしっかりと使い分ける必要があるということです。
最近のプログラミング言語は型を意識しなくても良いものもありますが、Javaでは型を厳格に使い分ける必要があり、どのようなルールがあるのか押さえておかなければなりません。
そこで今回の記事では、データ型についてのルールと型変換という仕組みについて解説していきます。
代入演算子の型に関するルール
代入において、代入する値の型と代入先の変数の型は必ず同じである必要があります。
代入する値の型とは異なる型となる変数への代入は原則できません。
もし、異なる型への代入を行おうとしたら、以下のようなコンパイルエラーとなります。
Sample01.java:10: エラー: 不適合な型: 精度が失われる可能性があるlongからintへの変換
代入はあくまで同じ型の変数どうしで行う処理である点に十分に注意しなければなりません。
算術演算子の型に関するルール
算術演算子においても代入とまったく同じことが言えます。
算術演算ができるのは同じ型どうしの変数であり、下図のように異なる型どうしでの演算は原則できません。
しかし、なぜできないのでしょうか。
例えば上図の例であれば、型は異なりますが、同じ整数です。「5 + 6」の結果であれば、int型の変数にも十分に収まる大きさであり、エラーとならないような感じもします。
その答えは、異なる型どうしの演算では、ビットが合わないためです。
int型は32ビット(4バイト)、long型は64ビット(8バイト)です。それを2進数で表すと以下のようになります。
上図のようにint型とlong型ではビット数が異なるため、演算できないというわけです。
正確に言うと、不足している部分を暗黙的に0埋めで補完して演算できるケースもありますが、ややこしくなるので「原則できない」という覚え方をしておくことをおすすめします。
データの型変換
Javaはデータ型を厳格に扱いますが、小さなサイズの型を大きなサイズの型にすることは不可能ではありません。
なぜなら、不足している部分を0埋めしてあげれば良いだけだからです。
上図のようにしてやることで値が変わることなくint型がlong型になります。
では、大きなサイズの型を小さなサイズの型にすることはできるのでしょうか。
その答えとしては「できない」というのが正しいです。なぜなら、long型からint型へ変換する例で考えてみると、64桁の値を32桁に削ってやらないといけないからです。
桁を削るということは値が変わってしまうこともあるということなので、できないというのはイメージできると思います。
しかし、そうは言っても、ソースコードを書く我々が削ってしまっても問題ないから強制的に型変換したいというケースは意外とあります。
そんなときに使うのが「キャスト」です。
キャストは、下記サンプルコードのように、変換したい型をカッコでくくることで行えます。
long a = 1;
int b = (int) a;
long型変数aの値をint型変数bに代入しているわけですが、その際、「(int)」によりint型にキャストしています。
このようにキャストをすることでコンパイルエラーにはならなくなります。
キャストのことを「明示的な型変換」とも言います。
まとめ
本記事冒頭で記したとおり、最近のプログラミング言語は型を意識しなくても良いものが多くあります。
それら言語では、言語仕様により自動的に型変換してくれているから実現できていることであり、本来は扱うデータの種類は何なのかを示す「型」を意識しなければなりません。
Javaは型について、厳格であり、ルールをしっかりと守らなければなりません。
もし、ソースコードを記述するプログラマーがこの型変換は問題ないと言えるのであれば、キャストを行ってやれば、明示的な型変換が可能というわけです。
キャストを使う場面というのは多くありますので、しっかり覚えておきましょう。