Javaの変数の型は基本型と参照型に分類されます。
基本型は8種類しかありません。8種類すべてが予約語(Java文法の根幹に関わる語)になっています、ここで暗記してしまいましょう。8種類の基本型とは以下の通りです。
以下では、変数について前置きした後、これら 4グループひとつひとつについて詳細を記述します。
なお、参照型はオブジェクト指向と絡む話になってくるので、後の章で解説します。
変数というのは変わりゆく可能性のある数のこと。基本型変数とは、おおよそ数学の x とか a とかそういうものを想定して頂ければ良いと思います。より具体的なイメージとしては、「名前のついた箱」という感じです。
もし、以下のような記述のところをプログラムが実行した場合には、
// 変数の宣言 int a; double b; boolean c;
以下のように、変数(名前のついた箱)が 3つ生成されます。
int, double, booleanと言った型の違いによって、変数(箱)に入れられる値の種類は変わってきます。ただ、基本的には、基本型の変数は「名前のついた箱」と捉えて頂いて問題ありません(参照型の世界は全然違うので、このことは意外と重要です)。
なお、この時点で、変数の値(箱の中身)は未定義という特殊な状態になっています。変数に値を代入するまでは、未定義状態となっています(例えば、自動的に 0に初期化される訳ではありません)。
それぞれの変数に、3, 6.5, trueを代入しようとすると、記述は以下のようになります。
// 変数の宣言 int a; double b; boolean c; // 値の代入 a = 3; b = 6.5; c = true;
以下のように、変数にそれぞれの値が代入されます。
なお、「=」については後で記述しますが、「等しい」という意味ではありません。「=」の右側に記述した数字なり数式の演算結果を「=」の左側に記述した変数に「代入する」という意味です。したがって、左右を逆にするとビルドエラーになります。
// 値の代入 3 = a; // ビルドエラー
変数の宣言と、初期化(値の代入)を同時に行うことができます。先のプログラムと以下のプログラムは事実上同じです。
// 変数の宣言と初期化 int a = 3; double b = 6.5; boolean c = true;
世の中に、状態が 2つしか取りえないものって結構あります。ONか OFFか、賛成か反対か。booleanはそういう 2つの状態を管理するための基本型です。読み方は「ブーリアン」です。「旗が立っているか倒れているか」という表現がよく使われた歴史的経緯上、booleanをフラグということもあります。
boolean型がとることができる値は、true(真)か false(偽)のどちらかです(ただし、boolean型の変数を宣言してから値を代入するまでの間は、他の基本型変数と同様に未定義という特殊な状態になっています)。この trueと falseは予約語ではないですが、予約語に準じた特別な語句となっています。
boolean型変数に値を代入するプログラムは以下。
D101/D101.java
/** * boolean型変数を利用します。 */ public class D101 { /** * メインメソッド * @param args 引数 */ public static void main(String[] args) { boolean a = true; boolean b = false; // 代入値の確認 System.out.println("変数 aの値は" + a); System.out.println("変数 bの値は" + b); } }
実行結果は以下の通り。
変数 aの値はtrue 変数 bの値はfalse
変数 a, bにそれぞれ true, falseが格納されていることが分かります。
ここで注意することは、true, falseは文字列ではないこと。つまり、二重引用符のついた "true"や "false"ではありません。真偽値を格納していることに注意してください。実行結果についても、結果的として「true」と「false」という文字列で表現されているだけで、変数 a, bにはあくまでも true(真), false(偽)が格納されていることに注意してください。
boolean型は、縁の下の力持ち的な存在かもしれません。この先の章で解説する「条件文」や「繰り返し」でも裏方として活躍します。C言語には存在しない型ではありますが、Javaではあちこちで使用されています。
byte, short, int, longは、いずれも符号付き整数型です。違いは使用するビット数で、これにより取り扱える値の範囲が異なります。一覧にすると以下のようになります。
これらの違いについては、10進数を例に出して以下で解説していきたいと思います。
なお、Javaでは主に int型を利用してプログラムを記述しています。
また、C言語ではプログラムを実行する CPUに応じて、int型でも 16ビットだったり 32ビットだったりと変わることがありますが、Javaでは、Java仮想マシンで仕様が固定されていますので、常にこれらのビット数で固定となります。
0~9まで選択可能な 4枚のパネルがあるとします。それを横一列に並べると下記のようになります。
こうやって 10進数を 4個並べることで、0~9,999(10の 4乗 -1)までの数を自由に表現することができます。このとき、桁がひとつ大きいと、10倍の重みがあることに注目してください。つまり、7000は 700に比べて 10倍の重みがあるということになります。
コンピュータの世界は基本的に 2進数なので、続いて 2進数について考えることにします。
2進数というのは 0と 1しかない世界です。2進数の世界では 0の次は 1、1の次は(2が存在しないので)桁があがって 10になります。
10進数で言うところの 13を、2進数の世界で表現したのが下図になります。
こうやって 2進数を 4個並べることで、0~15(2の 4乗 -1)までの数を自由に表現できることになります。このとき、桁がひとつ大きいと、2倍の重みがあることに注目してください。つまり、2進数の 1000は、2進数の 100に比べて 2倍の重みがあるということになります。
さて、ここまでの考え方では 0以上の数を表現することはできました。ところが、マイナスの数についてはまったく表現することができません。と言うことで、4枚のパネルを使ってルールを少し付け加え、マイナスの数も表現できるようにします。それが下図です。
0~4,999までは「符号無し」と同じなのだけど、ルールを追加したことで 5,000は -5,000として扱われ、7,583は -2,417として扱われ、9,999は -1として扱われるようにします。このようなルールを追加したことで、全体で見れば -5,000~4,999までの数を扱えることになりました。これが「符号付き」の意味するところです。
続いて、これと同じルールを 4桁の 2進数にも適用させてみることにします。
4桁の 2進数について、10進数と同じようなルールを追加してみます。
0~7までは「符号無し」と同じなのだけど、ルールを追加したことで 8は -8として扱われ、13は -3として扱われ、15は -1として扱われるようにします。このようなルールを追加したことで、全体で見れば -8~7までの数を扱えることになりました。
先に byteは 8ビット、short は 16ビット、int は 32ビット、longは 64ビットと記述しました。このビットの数とは、言い換えれば 2進数の桁のことです。例えば、byteの場合、2進数のパネル 8枚で構成されていることになります。これらから計算すると、それぞれの基本型で表現できる範囲は、それぞれ以下のようになります。
byte, short, int, longを使用したサンプルプログラムを挙げます。
D102/D102.java
/** * byte型, short型, int型, long型を使用します。 */ public class D102 { /** * メインメソッド。 * @param args 引数 */ public static void main(String[] args) { // 変数の宣言と初期化 byte a = 100; short b = -30000; int c = 12345678; long d = 1234567812345678L; // 値の表示 System.out.println("変数 aの値は" + a); System.out.println("変数 bの値は" + b); System.out.println("変数 cの値は" + c); System.out.println("変数 dの値は" + d); } }
実行結果は以下の通り。
変数 aの値は100 変数 bの値は-30000 変数 cの値は12345678 変数 dの値は1234567812345678
なお、Javaでの数の表現は int型が基準となっています。long型の数字を使用する際には、上記のプログラムのように数字の末尾に「L」をつけてください。特に、int型では表現できないような大きな値を記述する際には、「L」をつけないとビルドエラーになってしまうことに注意してください。
char型は 16ビットの符号無し整数型です。ただ、char型は普通の数値計算に使われる場合はほとんどなく、1文字を表す文字コードを格納するために使われます。Java仮想マシンでは文字コードは Unicodeと定められているので、文字コードは Unicodeになります。
動きや扱いが特殊なので、まずサンプルプログラムを見てみます。
D103/D103.java
/** * char型を使用します。 */ public class D103 { /** * メインメソッド。 * @param args 引数 */ public static void main(String[] args) { // 変数の宣言と初期化 char a = 'p'; char b = '3'; char c = '義'; char d = 65; // 値の表示 System.out.println("変数 aの値に対応する文字は" + a); System.out.println("変数 bの値に対応する文字は" + b); System.out.println("変数 cの値に対応する文字は" + c); System.out.println("変数 dの値に対応する文字は" + d); } }
実行結果は以下の通り。
変数 aの値に対応する文字はp 変数 bの値に対応する文字は3 変数 cの値に対応する文字は義 変数 dの値に対応する文字はA
'p'
や'3'
、'義'
というように、一重引用符でくくった文字は、その文字に対応する文字コードの数字(整数)を表します。したがって、変数 a, b, cにはそれぞれの値が代入されます。変数 dでは、直接数字(65)を代入しています。
printlnメソッドでは、char型は、格納された数字そのものが表示されるのではなく、その数字に対応した Unicode文字コードの文字が表示されます。Unicode 文字コードにおいて、65は「A」のことなので、変数 dのところでは「A」と表示されます。
このように、char型は文字との関わり合いが強い基本型ということになります。
なお、文字(例えば 'a')と、文字列(例えば"ABC")は、Javaではまったく別の扱いになりますので、混同しないように注意してください。一重引用符でくくったものが文字、二重引用符でくくったものが文字列です。例えば、"A"は、1文字ではありますが、二重引用符でくくっているために文字列とみなされます。
符号付き整数型によってマイナス値を表現できるようになりました。ところが、まだ小数点数を表現することができません。また、大きな数については、「250億円」というように最初の(上位の)何桁かが重要で、小さな桁はあまり重要ではないということが往々にしてよくあります。これらを上手く考えて、浮動小数点数というものが生み出されました。Javaでは、浮動小数点型として float型と double型が存在します。違いは以下の通り。
Javaでは基本的には double型が使用されます。
浮動小数点数の考え方について、次の項では 10進数を例にして見てみます。
10進数の 4枚のパネルと、プラスマイナスパネルの合計 5枚のパネルで浮動小数点数を表現すると、例えば以下のような感じになります。とても複雑な構造になっていますが、時間があればゆっくり考えてみてください。
このように 4枚のパネルとプラスマイナスパネルを用いて、-7,500,000という大きな負の数を表現することができました。また、このような表現方法ゆえに、-7,500,001のような数が表現できないことも分かるかと思います。
それと、右上部の 2枚のパネル「56」を「46」に置き換えることで、「-7.5×10のマイナス 4乗」、つまり -0.0075のような小数点数が表現できることも、数学を駆使できる方なら分かるかと思います。このように、小数点が動くように感じられることから、浮動小数点数という言葉になっているのだと思います。
10進数で浮動小数点数の仕組みを例示しましたが、float型や double型での浮動小数点数の仕組みは複雑で、説明することは非常に困難です。そのため、ここでは解説を省略します。
ただ、おおよその枠組みは、10進数の考え方と同じです。上位の何桁かのみに着目することで、正や負の大きい数から小数点数の数までを表現できることには変わりありません。
なお、実際には floatも doubleも使用するビット数が多いので、普段使用する分には自由な数を表現できると思って構いません。
float型、double型を使用したサンプルを以下に載せます。
D104/D104.java
/** * float型, double型を使用します。 */ public class D104 { /** * メインメソッド。 * @param args 引数 */ public static void main(String[] args) { // 変数の宣言と初期化 float a = 4.5f; double b = -12.75; System.out.println("変数 aの値は" + a); System.out.println("変数 bの値は" + b); } }
実行結果は以下の通り。
変数 aの値は4.5 変数 bの値は-12.75
なお、float型の数値を表す場合には、数字の後ろに「f」をつける必要があります。これをつけないと、float型変数への代入のところでビルドエラーが発生してしまいます。
また、float型や double型の数値を表現する場合、「3.0f」や「-4.0」というように、敢えて「.0」を含めて記述することが多いです。これはうっかり整数型として扱われることを防ぐための措置となります。