Javaのメモリ管理:プリミティブ型と参照型の違い、スタックとヒープの関係

1. プリミティブ型と参照型の違い

Javaにはデータ型として プリミティブ型 と 参照型 の2つがあります。それぞれの違いを、メモリ内での動作を含めて簡単に説明します。

特徴プリミティブ型参照型
格納されるもの値そのものオブジェクトのメモリアドレス(参照値)
メモリの格納場所スタックメモリスタック(参照)+ ヒープ(オブジェクト本体)
代表的な例intdoublebooleancharString, 配列、クラスのインスタンスなど
値の変更による影響独立して動作(他の変数に影響しない)同じオブジェクトを参照している場合、影響を受ける

2. スタックとヒープの違い

Javaのメモリには大きく分けて スタックメモリ と ヒープメモリ があります。

項目スタックメモリヒープメモリ
用途メソッド実行中のローカル変数を保存オブジェクトや配列など動的データを保存
格納されるデータプリミティブ型の値、参照型の参照値オブジェクト本体、フィールド(プリミティブ型含む)
ライフサイクルメソッドが終了すると自動的に解放されるガベージコレクションにより不要時に解放
速度高速比較的遅い

3. スタックとヒープの具体例

以下のコードを例に、スタックとヒープでデータがどのように管理されるかを確認しましょう。

public class Main {
public static void main(String[] args) {
int x = 10; // プリミティブ型
Dog dog = new Dog("Pochi"); // 参照型
System.out.println(x); // 10
System.out.println(dog.name); // Pochi
}
}

class Dog {
String name; // フィールドはヒープに保存

Dog(String name) {
this.name = name; // フィールドに値を格納
}
}

メモリ構造:

  • スタックメモリ:
    • x: 10(プリミティブ型)
    • dog: 0x1234(ヒープ上のオブジェクトのアドレス)
  • ヒープメモリ:
    • Dog オブジェクト(アドレス 0x1234):
      • name: “Pochi”

4. String型が特別な理由

String 型は特別なクラスで、他の参照型と異なり Stringプール という仕組みを活用しています。

  1. Stringプールとは?
    • ヒープメモリ内の特殊な領域で、文字列リテラルを共有・再利用します。
    • 重複する文字列を節約してメモリ効率を上げるために存在します。
  2. 動作例:
public class Main {
public static void main(String[] args) {
String str1 = "hello"; // プール内に保存
String str2 = "hello"; // 同じ文字列を参照
String str3 = new String("hello"); // 新しいオブジェクトを作成

System.out.println(str1 == str2); // true (同じプール内の文字列)
System.out.println(str1 == str3); // false(異なるオブジェクト)
}
}
  • str1 と str2: Stringプール内の同じ文字列を参照。
  • str3: 新しくヒープにオブジェクトを作成。

5. メモリイメージ

+---------------------+                +---------------------+
| Stack | | Heap |
+---------------------+ +---------------------+
| local int x: 10 | | Address 0x1234 |
| local ref obj: 0x1234|----+ | ----------------- |
+---------------------+ | | Object { |
| | String name: |
| | "Pochi" |
| | } |
| +---------------------+
|
| +---------------------+
| | String Pool |
+--------->| "hello" |
+---------------------+

6. まとめ

  • スタックはローカル変数や参照値を一時的に保存する短期メモリ。
  • ヒープはオブジェクト本体や配列を保存する長期メモリ。
  • String型は、メモリ効率化のためにStringプールを利用し、再利用可能な仕組みを持っています。