String(文字列型)の比較で「==」で比較する参照の比較を理解するために、いきついた「String Constant Pool」をまとめてみます。
String Constant Pool とは
String Constant Pool (略してSCPやString poolと言ってる人もいた)は日本語訳は見当たらなかったので、そのままStringコンスタントプールと呼びます。
一言で言えばヒープ領域を節約するための機能です。
String(文字列)は不変(immutable)のため不必要なオブジェクトの生成を避けます。そこでStringコンスタントプールが活用されます。
ここからはサンプルコードと、イメージを使って説明していきます。
文字列はString Constant Poolを参照する
String Constant PoolはHeap領域の中にあります。
サンプルコード
String str1 = “Hello”;
解説
上記コードで生成された文字列はヒープ領域の中にあるStringコンスタントプールへ保管されます。
ローカル変数のインターン化
同じ文字列を生成した場合の参照はどうなるでしょう。
サンプルコード
String str1 = “Hello”;
String str2 = “Hello”;
System.out.println(str1 == str2); // true
解説
ローカル変数「str1」と「str2」は同じHelloを生成しています。
一度Stringコンスタントプールに生成されたものがあれば、後から同じ文字列を生成した場合、暗黙的にインターン化(同じものを参照しよう的な)されます。そのため参照の比較はtrue(一致)となります。
Stringをnewして生成する
文字列の生成方法には他にもnewで生成する方法もありますよね。
サンプルコード
String str1 = new String(“Hello”);
解説
newした場合、Stringコンスタントプールへの保管はされず、ヒープ領域へ直接保管されます。
Stringをnewして複数生成する
同じ値をnewで生成してみます。
サンプルコード
String str1 = new String(“Hello”);
String str2 = new String(“Hello”);
System.out.println(str1 == str2); // false
解説
ヒープ領域ではStringコンスタントプールと異なりインターン化などはないため、newして生成された参照(インスタンス)が同じになることはありません。そのため参照の比較はfalse(不一致)となります。
newとnewを使わない生成
newとnewを使わない基本的な文字列の生成についでです。
サンプルコード
String str1 = new String(“Hello”);
String str2 = “Hello”;
System.out.println(str1 == str2); // false
解説
new String()で生成されたものはヒープ領域へ、基本的な生成はStringコンスタントプールへ保管されており、別々の参照のため参照の比較はfalse(不一致)となります。
おわり
文字列の比較はbooleanを使えばいいんだし、関係ないんだからいいかなとも思ったのですがきちんと理解したいなと思い調べだしたらなかなかいい記事が見当たらずかなり時間を要してしまいました。
いい記事にも巡りあえたし、わかってしまえばさほど難しくなかったですね。
参考
https://www.geeksforgeeks.org/string-constant-pool-in-java/