変数宣言のイメージをつかむ
Javaで「変数を宣言する」というのは、「この名前の箱を用意して、こういう種類の値だけを入れます」と宣言することです。
例えば次の1行は「age という名前の箱に、整数だけを入れる」と決めて、最初の中身として 20 を入れています。
int age = 20;
Javaint が「型(どんな種類の値か)」、age が「変数名(箱の名前)」、20 が「初期値(最初に入れる値)」です。
ここから「プリミティブ型」と「参照型」で、箱の中身のルールが変わります。
プリミティブ型の変数宣言と初期化
プリミティブ型とは何か
プリミティブ型は「値そのものを直接入れる箱」です。
Javaにはプリミティブ型が 8 種類あります。
代表的なものだけ先に押さえましょう。
int count = 10; // 整数
double price = 19.8; // 小数
boolean isOk = true; // 真偽値
char initial = 'A'; // 1文字
Javaここで重要なのは「箱の中に、値そのものが入っている」というイメージです。count の箱を開けると、そこにはそのまま 10 が入っています。
プリミティブ型の種類と使い分け(初心者向け)
本当は 8 種類ありますが、初心者のうちは次の4つをメインで使えば十分です。
int age = 25; // 普通の整数はとりあえず int
double height = 172.5; // 小数は基本 double
boolean isAdult = true; // 条件の結果などに使う
char grade = 'A'; // 1文字だけ扱いたいとき
Java他の byte / short / long / float は、
「メモリを極端に節約したい」「とても大きな整数を扱いたい」など、
もう少し先の段階で意識すればOKです。
プリミティブ型の初期化で絶対に覚えてほしいこと
プリミティブ型のローカル変数(メソッドの中で宣言した変数)は、「必ず自分で初期化しないと使えません」。
public class PrimitiveInitExample {
public static void main(String[] args) {
int x; // ここではまだ中身が決まっていない
// System.out.println(x); // コンパイルエラー(初期化されていない)
x = 10; // 初期化
System.out.println(x); // 10 と表示される
}
}
Java「宣言したら、すぐに意味のある初期値を入れる」が鉄則です。
バグの かなりの割合 が「初期化忘れ」や「変な初期値」から生まれます。
参照型の変数宣言と初期化
参照型とは何か
参照型は「値そのもの」ではなく、「値が置いてある場所への案内状(アドレス)」を箱に入れる型です。
よくある例は String(文字列)や配列、そして自分で作るクラスです。
String name = "Taro"; // 文字列
int[] scores = {80, 90, 70}; // 整数の配列
Javaname の箱の中には "Taro" そのものが入っているわけではなく、
「ヒープ領域のどこかにある "Taro" というデータへの参照」が入っています。
String と配列の例でイメージする
public class ReferenceExample {
public static void main(String[] args) {
String message = "こんにちは";
int[] numbers = {1, 2, 3};
System.out.println(message); // こんにちは
System.out.println(numbers[0]); // 1
}
}
Javamessage も numbers も「参照型」です。
変数自体は「場所への矢印」を持っていて、実際のデータ本体は別の場所に置かれています。
null と NullPointerException(ここは超重要)
参照型の変数には「何も指していない」という特別な値 null を入れることができます。
String text = null; // まだどの文字列も指していない状態
Javaこの状態で、次のように「中身にアクセス」しようとすると、NullPointerException という例外が発生します。
String text = null;
System.out.println(text.length()); // 実行時に NullPointerException
Java初心者が一番よく出会うエラーのひとつなので、
「参照型の変数を使う前に、null じゃないか確認する」という癖をつけると一気にレベルが上がります。
if (text != null) {
System.out.println(text.length());
} else {
System.out.println("text はまだ設定されていません");
}
Java型選びの考え方(プリミティブ/参照型)
どのプリミティブ型を選べばいいか
初心者向けの「まずこれを使え」という指針は次の通りです。
int // 普通の整数(年齢、個数、ID など)
double // 小数(身長、重さ、割合 など)
boolean // 条件(〜かどうか)
char // 1文字だけ扱いたいとき
Java金額計算など「誤差が困る」場面では、本当は double より BigDecimal を使うのがベストですが、
最初のうちは「小数 = double」で感覚をつかんでから、あとで精度の話に進むと理解しやすいです。
プリミティブ型か参照型かをどう決めるか
ざっくり、次のように考えると迷いにくくなります。
- 「単純な数・真偽・1文字」ならプリミティブ型
- 「文字列・配列・複数の値をまとめたもの・自作クラス」なら参照型
例:
int age = 30; // プリミティブ
String name = "Yamada"; // 参照型
int[] scores = {80, 90, 70}; // 参照型
Java「何かの機能(メソッド)を持っていそう」「複雑なデータ構造っぽい」と感じたら、ほぼ参照型だと思ってOKです。
値のコピーの違い(プリミティブ vs 参照型)【重要ポイント】
プリミティブ型のコピー
プリミティブ型は「中身そのもの」をコピーします。
int x = 10;
int y = x; // x の中身 10 を y にコピー
y = 20;
System.out.println(x); // 10
System.out.println(y); // 20
Javax と y は完全に別々の箱です。y を変えても x には一切影響しません。
参照型のコピー
参照型は「矢印(参照)をコピー」します。
つまり「同じデータを一緒に指す」ことになります。
int[] a = {1, 2, 3};
int[] b = a; // a と同じ配列を指す矢印を b にコピー
b[0] = 99;
System.out.println(a[0]); // 99
System.out.println(b[0]); // 99
Javaa と b は「同じ配列」を共有しているので、
片方から中身を変えると、もう片方から見ても変わっています。
ここを理解していないと、
「え、こっちの変数しか変えてないのに、あっちまで変わってるんだけど!?」
というホラー現象に何度も遭遇します。
まとめとミニ練習問題
ここまでの超要約
- 変数宣言は「型+名前+初期値」で書く
- プリミティブ型は「値そのもの」が箱に入る(
int,double,boolean,charなど) - 参照型は「値がある場所への矢印」が箱に入る(
String, 配列、自作クラスなど) - 参照型には
nullを入れられるが、nullのまま中身に触るとNullPointerException - コピーしたとき、プリミティブは「値のコピー」、参照型は「矢印のコピー」になる
ミニ練習問題
自分の手でコードを書いて、動かしてみてください。
問題1
次の変数宣言を、プリミティブ型か参照型かに分類してみてください。
int age = 18;
String nickname = "mono";
boolean isStudent = false;
int[] points = {10, 20, 30};
char rank = 'S';
Java問題2
次のコードの実行結果を予想してから、実際に動かして答え合わせをしてみてください。
public class CopyCheck {
public static void main(String[] args) {
int a = 5;
int b = a;
b = 10;
int[] x = {1, 2, 3};
int[] y = x;
y[1] = 99;
System.out.println("a = " + a);
System.out.println("b = " + b);
System.out.println("x[1] = " + x[1]);
System.out.println("y[1] = " + y[1]);
}
}
Java「なぜそうなるのか」を、自分の言葉で説明できるようになったら、
プリミティブ型と参照型の一番大事なところはもう掴めています。
