リテラル/新しいオブジェクトとして、新しいStringを作成するメモリ割り当て

Priyakデイ:

注:それは重複してマーキングする前に、質問をお読みください。これは、作成されたどのように多くのオブジェクトや異なる作成技術を使用して/インターンを使用すると==の結果をどのように影響するかを定数プールが格納されている場所についての質問、どのようにインターン作品は、ないです..!

String s1 = "Hello";
String s2 = new String("Hello");

Field declaredField = String.class.getDeclaredField("value");
declaredField.setAccessible(true);

byte[] arr1 = (byte[])declaredField.get(s1);
byte[] arr2 = (byte[])declaredField.get(s2);

さて、S1 == S2 = Falseに、ARR1 == ARR2 =真。

私の質問は、オブジェクトがメモリに保存されているかです。

最初の行は、プールに新しい文字列型のオブジェクトを作成しません。2行目は、通常のオブジェクトとしてヒープ上に作成しません

しかし、根本的なバイト[]編曲は同じです。これは、既存のバイトは[]がすでに存在し、同じARRへのすべての参照を指している場合何とかJVMは、このチェックを行い、私は考えさせます。これは根本的な配列がプールにキャッシュされている意味してい、いや、我々はリテラルまたは新しいキーワードを使用しても問題?

また、プールに作成された - だから、S =「何か」は、データを保持している根本的な配列と一緒にプールに新しい文字列型のオブジェクトを作成します。

S =新しい文字列(「何か」) - すでに存在する場合>ヒープ上の文字列型のオブジェクトを作成しますが、根本的なアレイが依然としてプールに保存されている/、参照が単に作成されます。

私の理解でも正しいですか?

これは長い間私を盗聴されているので素晴らしい記事へのポインタを持つ誰も、素敵になります:(

マキシムポポフ:

あなたはどのようなJavaのバージョンを使用していますか?私は11 JDK上でそれを確認し、String.valueのタイプがcharです[]。11 JDKのバージョンに基づいて、すべての次の言葉。

この動作の理由は、Stringコンストラクタです。

public String(String original) {
    this.value = original.value;
    this.hash = original.hash;
}

あなたが見ることができるように、valueフィールドがからコピーされたoriginalStringオブジェクト。あなたが使用しているので"Hello"ためnew String(...)、引数、"Hello"文字列のプールから得ていると、コンストラクタに渡されたvalueフィールドは、新しいStringオブジェクトにコッピングされます。

あなたは、予想される動作に到達するためにコードビットを変更することができます。

String s1 = "Hello";
String s2 = new String("Hell") + "o";
Field declaredField = String.class.getDeclaredField("value");
declaredField.setAccessible(true);
char[] arr1 = (char[])declaredField.get(s1);
char[] arr2 = (char[])declaredField.get(s2);
assert arr1 != arr2;
assert s1.equals(s2);

おすすめ

転載: http://43.154.161.224:23101/article/api/json?id=292787&siteId=1