✈️ Go Up

リテラルのメモリ格納方式

Go to Nav

リテラルのメモリ格納方式

リテラルはプログラミング言語で変数に直接割り当てられる固定値を意味します。この記事ではJavaのリテラルがメモリにどのように格納され管理されるかを見ていきます。

リテラルとは?

リテラルはコードで値として直接現れるデータを指します。例えば、数字10、文字列"Hello"、論理値trueなどはすべてリテラルです。簡単に言えば、リテラルはコードで使用されるデータそのものです。

リテラルの代表的な種類は次のとおりです:

  • 整数リテラル: 10-4209999L
  • 実数リテラル: 3.14f0.5
  • 文字リテラル: 'A''B'
  • 文字列リテラル: "Hello""World"
  • ブーリアンリテラル: truefalse

リテラルの格納方式

リテラルがメモリに格納される方式は、変数が基本型かラッパークラスまたは文字列かによって異なります。

基本型変数

基本型変数にリテラルを代入すると、その値は変数のメモリ空間に直接格納されます。例えば、整数リテラル10を基本型変数に割り当てると、変数のメモリ空間に10という値が直接格納されます。これは処理速度が速く効率的です。

コード例:

public class Main {
    public static void main() {
        int intVal = 3;
    }
}

メモリダイアグラム:

基本型変数はコールスタックにビットデータを直接格納します。

ラッパークラスと文字列

基本型の参照型であるラッパークラス(Integer、Doubleなど)と文字列クラスは、定数プール(Constant Pool)という特別な空間に格納されます。定数プールに同じ値がすでに存在する場合、既存のアドレスを返してメモリを節約します。

コード例:

public class Main {
    public static void main(String[] args) {
        Integer intVal = 3;
        String str = "hello";
    }
}

メモリダイアグラム:

ラッパークラスと文字列は定数プールに格納された値を参照します。

ラッパークラスと文字列の比較

ラッパークラスと文字列リテラルは定数プールのアドレスを参照するため、同じ値を複数回生成しても常に同じインスタンスを参照します。一方、newキーワードを使用してオブジェクトを生成すると、定数プールの代わりにヒープメモリに新しいオブジェクトが生成されます。

コード例:

public class ConstantPoolTest {  
    public static void main(String[] args) {  
        A a = new A();  
        B b = new B();  
  
        System.out.println(a.instanceStr == b.instanceStr);  // true  
        System.out.println(a.instanceStr == b.newStr);       // false  
        System.out.println(a.instanceStr == b.internStr);    // true  
        System.out.println(a.instanceStr.equals(b.newStr));  // true  

        System.out.println(a.instanceInt == b.instanceInt);  // true  
        System.out.println(a.instanceInt == b.newInt);       // false  
        System.out.println(a.instanceInt == b.internInt);    // true  
        System.out.println(a.instanceInt.equals(b.newInt));  // true  
    }  
}  
  
class A {  
    String instanceStr = "instanceStr";  
    Integer instanceInt = 1;  
}  
  
class B {  
    String instanceStr = "instanceStr";  
    String newStr = new String("instanceStr");  
    String internStr = newStr.intern();  

    Integer instanceInt = 1;  
    Integer newInt = new Integer(1);  
    Integer internInt = newInt.intValue();  
}

intern()メソッドを使用すると、文字列定数プールで同じ値を見つけてアドレスを返します。

リテラルで生成されたオブジェクトは同じ定数プールアドレスを共有するため比較結果が「真」になりますが、newキーワードを使用して生成したオブジェクトはヒープメモリに別々に生成されるため比較結果が「偽」になります。