Javaの文字列リテラルには「既に同じ文字列リテラルを作っている場合は、同じオブジェクトを再利用する」という性質があります。この性質のために、このような現象が起きます。詳しく動きを見ていきましょう。
Data da1 = new Data("Test");
と言うコードで"Test"
の部分は"Test"を意味する内容のStringのオブジェクトが作成されますが、このオブジェクトを仮に__objS1__と名前をつけておきましょう。この__objS1__は作成されると同時にString.intern
というメソッドを使って、Java本体の共有プールに保存されます。共有プールでは"Test"は__objS1__と覚えていると思っておいてください。さて、この__objS1__はDataのコンストラクタの引数として渡されて、da1
のdata
に代入されます。つまり、da1
のdata
は__objS1__というオブジェクトへの参照値が入るっている状態になります。
次にData da2 = new Data("Test");
と言うコードを実行されることになります。おっと、"Test"はさっき作った文字列と同じですね。このように一度作ったことがある文字列リテラルの場合、共有プールに保存しておいたオブジェクトを探して、再利用します。共有プールでは"Test"は__objS1__として保存されているのでした。**よって、"Test"
の部分は新たにオブジェクトを作成せずに__objS1__になります。**ここまで来たら後は同じです。__objS1__はDataのコンストラクタ引数と渡されて、da2
のdata
に代入されます。結局、da2
のdata
も__objS1__というオブジェクトへの参照値が入っている状態になります。
後はもうわかりますね。da1.getData() == da2.getData()
というところですが、getData()
はdata
をそのまま返すだけです。da1
のdata
もda2
のdata
も同じ__objS1__というオブジェクトなのでtrueになる、ということです。
※ __objS1__は説明するためにつけた名前で、JavaVM内部で実際にそのような何か名前が付いているわけではなく、一意のID(番号)で管理されています。
※ この性質は単体の文字列リテラルだけでは無く、定数式にも当てはまります。詳しくは後述の参考文献を参照してください。
参考文献
Java言語規定 字句文法#3.10.5 文字列リテラル
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。