5. Javaで扱われるデータ
Javaで扱われるデータの型は大きく分けて2つあります。一つは基本データ型と呼ばれるもので、もう一つは参照型といわれるものです。両者の違いは次の点になります。
- 基本データ型の場合は、データの値を直接保持している
- 参照型の場合は、値を保持しているインスタンスの参照先アドレス(メモリ上に配置されている場所)を保持していて、インスタンス自体の値を保持していない
5.1. 基本データ型
基本データ型はデータの値を直接持っているデータです。データの値を変えた際に直接そのデータが持つ値が変わります。
基本データ型には次のものがあります。
型 | サイズ | デフォルト値 | 概要 |
---|---|---|---|
byte | 8ビット | 0 | 8ビットの範囲(-128 ~ 127)の整数。 |
short | 16ビット | 0 | 16ビットの範囲(-32,768 ~ 32,767)の整数。 |
int | 32ビット | 0 |
32ビットの範囲(-2,147,483,648 ~ 2,147,483,647)の整数。 ただし、Java 8より符号なしの値にすると範囲が0 ~ 4,294,967,295となります。 |
long | 64ビット | 0 |
64ビットの範囲(-9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807)の整数。 longを表すには数字の値の後に「l」もしくは「L」をつけます。小文字の「l」は数字の「1」と間違えやすいため一般的に大文字の「L」を使われます。 ただし、Java 8より符号なしの値にすると範囲が0 ~ 18,446,744,073,709,551,615となります。 |
float | 32ビット | 0.0 |
浮動小数点数。 floatを表すには数字の値の後に「f」もしくは「F」をつけます。 |
double | 64ビット | 0.0 |
浮動小数点数。 ソースコード上で小数点数を記述するとデフォルトでdoubleになります。 |
char | 16ビット |
\u0000 (空文字) |
Unicodeが持つ1文字。 「'」(シングルクォーテーション)で1文字を囲むことでcharの値を指定できます。 |
boolean | 1ビット | false | trueもしくはfalseを表す真偽値。 |
ここで注意するべき点は、データ型の範囲を超した際にエラーなどにならずに、正の値なら負の値へ、負の値なら正の値へ自動で変わってしまうことです。例えばintの最大値である2,147,483,647に1を足した場合、結果は-2,147,483,648となります。次のソースコードを実行すると、次の結果が表示されます。
package jp.codezine.java.sample02; /** * intが最大値を越える際の動きを確認するクラス。 */ public class OverflowCheck1 { /** * 最大値に1を加算した際の値を標準出力します。 * * @param args * コマンドライン引数。今回は使いません。 */ public static void main(String[] args) { int i = Integer.MAX_VALUE; System.out.println(i); i = i + 1; System.out.println(i); } }
2147483647 -2147483648
そのため、あまりに大きな値を扱っていると、知らない間に値が意図したものでなくなっている可能性があるので注意してください。
Java 8より、intとlongに関しては符号なしで値を保持することが可能になりました。「符号なし」とはマイナスの値を持たないことで、そのためマイナス値としていた領域が使えるようになり、それぞれが扱える範囲も変わっています。ただし、他の言語と違い符号なしの修飾子が用意されているのではなく特殊なメソッドを使わないと、それらの符号なしの値を取得したり使ったりすることはできません。
package jp.codezine.java.sample02; /** * Java8での符号なしIntegerとLongについての限界値の際の動きを確認するクラス。 */ public class OverflowCheck2 { /** * Java8での符号なしIntegerとLongについての限界値のサンプルを標準出力します。 * * @param args * コマンドライン引数。今回は使いません。 */ public static void main(String[] args) { // Java 8より int i = Integer.MAX_VALUE + 1; String value = Integer.toUnsignedString(i); System.out.println(value); i = Integer.MAX_VALUE + Integer.MAX_VALUE + 1; value = Integer.toUnsignedString(i); System.out.println(value); i = i + 1; value = Integer.toUnsignedString(i); System.out.println(value); long l = Long.MAX_VALUE + Long.MAX_VALUE + 1; value = Long.toUnsignedString(l); System.out.println(value); l = l + 1; value = Long.toUnsignedString(l); System.out.println(value); } }
2147483648 4294967295 0 18446744073709551615 0
5.2. 参照型
参照型はインスタンスの参照先アドレスを保持しているデータです。主なものにクラスや配列があります。
参照型の場合、データが保持している値はインスタンスのあるメモリ領域の参照先のアドレスになります。もし、参照型のデータ名を宣言しただけの場合、参照先のアドレスがないので、そのデータの値はnull、つまり何もない状態になります。
そのため、参照型のデータの場合、そのデータが示しているインスタンスが変わると参照先のアドレスが変わることになります。
ただし、文字列のクラスであるStringは特別で「"」(ダブルクォーテーション)で囲った値を直接代入した場合、それぞれのデータは同じ参照先のアドレスを示すことになります。次のサンプルを実行すると、次の結果が標準出力されます。
package jp.codezine.java.sample02; /** * 文字列のデータの参照先をチェックする */ public class StringCheck1 { /** * 2つのStringのデータに同じダブルクォーテーションで囲った文字列を参照させた場合、同じもの指しているのかを標準出力します。 * * @param args * コマンドライン引数。今回は使いません。 */ public static void main(String[] args) { String a = "あいうえお"; String b = "あいうえお"; // a と b が同じ参照先を見ているか比較し、同じ場合はtrueになります。 boolean result = (a == b); System.out.println("a == b: " + result); } }
a == b: true
これはStringの場合、「"」(ダブルクォーテーション)で囲った値を代入した際に、すでに同じ値があるか確認し、同じ値が存在する場合には、そのインスタンスの参照先を返すように、内部で行われているからです。
5.3. インスタンス
クラスから生成されたものをインスタンスといい、参照型のデータになります。Javaでは下記のように「new」キーワードを使ってインスタンスを生成します。
Date today = new Date();
ただしStringの場合は「"」(ダブルクォーテーション)で囲んだものを代入することでインスタンスを生成することも可能です。
String name = "太郎";
5.4. 配列
参照型のデータの種類の一つに配列があります。配列は複数のデータを1つにまとめたものです。基本的には配列が持つデータ(要素)の数を指定して「new」キーワードを使って宣言します。その際にデータ型に「[]」(角カッコ)をつけることが特徴です。
データ型[] 配列名 = new データ型[要素数];
その後に各データ(要素)に値を設定し、各要素を初期化します。要素に値を設定する際は、配列のどの要素を取得するのかをインデックスと呼ばれる要素の順番を使って指定します。このインデックスは0から始まるのが特徴です。
例えば1、2、3の要素を持つintの配列を作成する場合は、次のようにします。
int[] datas = new int[3]; datas[0] = 1; datas[1] = 2; datas[2] = 3;
また、この例のように要素の値が最初から決まっている場合は、「{}」(波カッコ)の中に各要素の値を宣言することで、宣言と一緒に各要素の値を初期化することも可能です。その場合、次のようになります。
int[] datas = { 1, 2, 3 };
今回は基本データ型を使って配列を作成しましたが、配列のデータ型は参照型でも可能です。
また、配列の要素数は一度宣言をすると増やしたり減らしたりできないので注意してください。
5.5. ラッパークラス
Javaでは受け取る値が参照型のみと定義されている場合、基本データ型が受け付けられないことがあります。その場合、基本データ型を何らかのクラスに変換しなければならなくなります。Javaではそのような場合に対応するために、ラッパークラスという、それぞれの基本データ型を表すクラスがjava.langパッケージに用意されています。次のものが各基本データ型を表すラッパークラスになります。
基本データ型 | ラッパークラス |
---|---|
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
char | Charater |
Boolean | Boolean |
この基本データ型とラッパークラスの変換は自動的に行われます。
ただし、このラッパークラスで注意すべき点は、基本データ型と違いラッパークラスの初期値は他の参照型と同じくnullになることです。そのため、値を設定していないと0ではなくnullが返ってくるので、そこで自動変換されると例外が発生するので注意してください。
5.6. 変数
今まで出てきたように識別子をつけて値を格納するものを「変数」と呼びます。変数は「=」を使って値を代入します。そしてその代入した値を後で別の値で代入することも可能です。後述する定数と違い、変数の特徴は値の代入が何回もできることになります。
5.5. 定数
変数では値の代入を何回もすることが可能でした。しかし、場合によってはそれらの値を変えたくないことがあります。Javaでは「final修飾子」をつけることにより、変数への代入を制御することができます。このfinal修飾子がついた値の代入ができないデータを「定数」と呼びます。
final データ型 定数名;
ただし注意すべき点は、参照型のデータの場合、データが持つ参照先のアドレスを代入することができなくなることを制御しているだけで、参照先のインスタンスの値が変わることは制御されていないことです。
例えば、次のようなことは行えません。
final Date date1 = new Date(); date1 = new Date(); // エラーになります。
次のようにすることはできます。
final Date date2 = new Date(); date2.setTime(0);
ちなみに1行目と2行目の値を出力すると、下記の結果のようにインスタンスの値が変わっています。
Sun Dec 21 22:31:43 JST 2014 Thu Jan 01 09:00:00 JST 1970