talosのプログラミング教室

Java Silver合格への道 ~コンスタントプール~

スポンサーリンク

こんにちは。たろすです。

今回はコンスタントプールについて説明します。

a == b

Javaではa == bと書くとaとbが同一かを判定し、同一であればtrue、同一でなければfalseを返します。

つまり以下のようなプログラムを実行すると「false」と表示されます。

public class Main {

	public static void main(String[] args) {
		// TODO 自動生成されたメソッド・スタブ

		Food a = new Food("gohan");
		Food b = new Food("cake");

		System.out.println(a == b);
	}

}

どこからどう見ても別のオブジェクトですからね。

それでは次のプログラムはどうでしょうか。

public class Main {

	public static void main(String[] args) {
		// TODO 自動生成されたメソッド・スタブ

		Food a = new Food("gohan");
		Food b = new Food("gohan");

		System.out.println(a == b);
	}

}

実はこの場合も「false」と表示されます。

なぜなら別々にインスタンス化しているため、別のインスタンスとして扱われるからです。

コンスタントプール

String型の場合はダブルクォーテーションで括られた文字列を記述するだけでインスタンス化できます。

つまり、わざわざnewしなくてもインスタンス化できるため以下のように書くことができます。

public class Main {

	public static void main(String[] args) {
		// TODO 自動生成されたメソッド・スタブ
		
		String a = "gohan";
		String b = "gohan";

		System.out.println(a == b);
	}

}

しかし、このプログラムを実行すると「true」と表示されます。

なぜこのような挙動をするかというとコンスタントプールという仕組みがあるからです。

コンスタントプールは文字列リテラルを定数値としてインスタンスとは異なるメモリに保存し、どの変数から参照されても同じ文字列の場合は同じ場所を参照することでメモリの消費を減らす仕組みです。

つまりこのプログラムでは変数aも変数bもコンスタントプール内の同じ場所を参照しているため、aとbは同一であると判定されたわけです。


一方で、newした場合は新しいインスタンスが作られるため、以下のプログラムを実行すると「false」と表示されます。

public class Main {

	public static void main(String[] args) {
		// TODO 自動生成されたメソッド・スタブ

		String a = new String("gohan");
		String b = new String("gohan");

		System.out.println(a == b);
	}

}

つまりこの書き方はメモリを無駄に消費しているので、実際にはやらないほうが良いです。

おわりに

今回はコンスタントプールについて説明しました。

String型の比較はequals()を使うのが普通なので意外とこの仕組みは知らないかもしれませんね。