JDK7は以前とは違う方法でインターンを処理しているようです。
ビルド1.7.0-b147でテストしたところ、「両方が等しい」と表示されましたが、1,6.0_24で(同じバイトコード)実行すると、メッセージが表示されません。
またString b2 =...
、ソースコードのどこに行があるかによっても異なります。次のコードもメッセージを出力しません。
class Test {
public static void main(String... args) {
String s1 = "Good";
s1 = s1 + "morning";
String s2 = "Goodmorning";
System.out.println(s1.intern()); //just changed here s1.intern() and the if condition runs true
if(s1 == s2) {
System.out.println("both are equal");
} //now it works.
}
}
intern
文字列のプールで文字列が見つからなかった後、実際のインスタンスs1をプールに挿入しているようです。JVMは、s2の作成時にそのプールを使用しているため、s1と同じ参照を取得します。一方、s2が最初に作成された場合、その参照はプールに格納されます。
これは、インターンされた文字列をJavaヒープの永続的な生成から移動した結果である可能性があります。
ここにあります:JDK7で対処される重要なRFE
JDK 7では、インターンされた文字列はJavaヒープの永続的な世代では割り当てられなくなりましたが、代わりに、アプリケーションによって作成された他のオブジェクトとともに、Javaヒープの主要部分(若い世代と古い世代として知られています)に割り当てられます。 。この変更により、メインのJavaヒープに存在するデータが増え、永続生成のデータが少なくなるため、ヒープサイズの調整が必要になる場合があります。ほとんどのアプリケーションでは、この変更によりヒープ使用量に比較的小さな違いしか見られませんが、多くのクラスをロードしたり、String.intern()メソッドを多用する大規模なアプリケーションでは、より大きな違いが見られます。
それがバグであるかどうか、そしてどのバージョンからのものかわからない...JLS3.10.5は述べています
計算された文字列を明示的にインターンした結果は、同じ内容の既存のリテラル文字列と同じ文字列になります。
したがって、問題は、既存のものがコンパイル時または実行時にどのように解釈されるかです。「Goodmorning」は既存のものかどうかです。
私はそれが7以前に実装された方法を好みます...