Java言語でのデータ型の説明(プリミティブ型、参照型)

最終更新日: 2019年9月15日 14時30分

目次

講義の目的

Java言語のデータ型が理解できる

1. はじめに

Javaには基本データ型参照型の2つのデータ型があります。

2. 基本データ型

Javaでは8つの基本データ型が用意されています。

基本データ型一覧表
データ型 サイズ
整数 byte 8bit -128 ~ 127
short 16bit -32,768 ~ 32,767
int 32bit 2147483648 ~ 2147483647
long 64bit -9223372036854775808 ~ 9223372036854775807
浮動小数点 float 32bit IEEEで定められれた範囲
double 64bit IEEEで定められれた範囲
文字 char 16bit Unicodeで表現できる1文字
真偽値 boolean - true,false

基本データ型は、プリミティブ型とも呼ばれます。

実際のプログラミングにおいても、基本データ型は頻繁に利用します。特に利用するのは、

int, boolean, float, double, long です。

byte、short、charは、他のプリミティブ型に比べて利用する機会は少ないです。とはいえ実装者は、全てのプリミティブ型を理解して使い分ける必要があります。

2. 参照型

Javaでは、基本データ型(プリミティブ型)以外は全て参照型です。

具体的には、 配列、 文字列、 クラス です。

参照型の変数は値が置いてある場所(メモリ上のアドレス)を保持します。

参照型と参照先
fig1. 参照型と参照先

なので、同じ参照先をもつ変数がある場合、どちらかの変数を変更すると他の変数の値も変更されます。

では、参照型の配列、文字列、クラスの動作を実装して確認しながら学習していきましょう。

2-1. 配列

配列は連続したデータを格納することができます。データは0から始まる添字で管理します。

まずは変数配列aを宣言して値を出力してみましょう。

int a[] = {1, 2};
System.out.println("a[0] index is " + a[0]);
System.out.println("a[1] index is " + a[1]);

上記のコードを実行します。

a[0] index is 1
a[1] index is 2

この配列aの値を変数bに代入します。

int a[] = {1, 2};
int b[] = a;
System.out.println("a[0] index is " + a[0]);
System.out.println("a[1] index is " + a[1]);
System.out.println("b[0] index is " + b[0]);
System.out.println("b[1] index is " + b[1]);

実行します。

a[0] index is 1
a[1] index is 2
b[0] index is 1
b[1] index is 2

変数aと変数bは同じ値が出力されます。変数aと変数bが同じ参照先を指しています。

では、配列bのb[0]に10を代入してみます。

int a[] = {1, 2};
int b[] = a;
// 10 is assigned 
b[0] = 10;

実行します。

a[0] index is 10
a[1] index is 2
b[0] index is 10
b[1] index is 2

配列bのb[0]だけでなく、配列aのa[0]の値も変わってます。

これは、aとbが同じ配列を参照しているからです。つまり、a[0]とb[0]は全く同じアドレスを見ています。

初心者のうちは間違えてしまうことも多いので、理解しておいてください。

2-2. 文字列

Javaでは文字列を Stringクラス で保持します。

Stringクラスは参照型なのですが、基本型のように使うことができます。なので、最初は戸惑うと思います。

実際にコードで動きを確認してみます。

String s1 = "Hello";
String s2 = s1;
System.out.println("s1 is " + s1 + ". s2 is " + s2);
System.out.println(s1 == s2);

(s1 == s2)でオブジェクトの同一性をチェックしています。オブジェクトの同一性は比較演算子「==」で判定します。

このコードを実行します。

s1 is Hello. s2 is Hello
true

(s1 == s2) の結果が true になっているので同じオブジェクトだと確認できます。

では、変数 s2 の値を書き換えてみます。

String s1 = "Hello";
String s2 = s1;
s2 = "world";
System.out.println("s1 is " + s1 + ". s2 is " + s2);
System.out.println(s1 == s2);

実行します。

s1 is Hello. s2 is world
false

実行します。

今度は s2 の値だけが変更され、(s1 == s2) の結果がfalseになりました。s1 と s2 のオブジェクトが異なってしまったということです。これはどういうことでしょうか。

実は、Javaの文字列は定数です。定数なので値を作成したあとに変更はできません。

Stringは新しくオブジェクトを生成します。つまり、 コード s2 = "world" は新しい文字オブジェクトを生成しています。

重要なのは、s1のオブジェクトは変更されず、s2だけが別のオブジェクトとして扱われるようになることです。

Stringの仕様は、最初は戸惑うと思いますが、慣れると基本型のように扱えるので重宝します。

2-3. クラス

クラス型はオブジェクトを生成して、基本データ型や参照型を保持できます。

この講義ではUserクラスを作成して動作を確認します。

User user1 = new User();
user1.id = 1;
user1.name = "suzuki";
User user2 = user1;
System.out.println(user1 == user2);
System.out.println(user1.name);
System.out.println(user2.name);

user2 = user1 なので変数user1と変数user2は同じ参照先です。

実行して確認します。

true
suzuki
suzuki

(user1 == user2) の結果が true になっているので同じオブジェクトだと確認できます。変数nameの値も同じです。

では、user2のname属性の値を変更してみます。

User user1 = new User();
user1.id = 1;
user1.name = "suzuki";
User user2 = user1;
// 変更
user2.name = "sato";
System.out.println(user1.name);
System.out.println(user2.name);
System.out.println(user1 == user2);

実行して確認します。

sato
sato
true

user1.nameとuser2.name2の両方の変数が書き換わりました。(user1 == user2) の結果が trueなので、user1とuser2が同じオブジェクトを参照していることも確認できます。

3. まとめ

この講義では、Java言語でのデータ型の特徴について学習しました。

Javaでは、基本データ型参照型を理解することが、正しいコードを書くための第一歩です。

同じ参照型であるStringと配列の挙動の違いは理解しにくいので、慣れも必要になります。

演習

この講義に関連する演習問題を用意しました。理解度を確認してください。

演習