次のコードの説明:
StringBuilder sample = new StringBuilder();
StringBuilder referToSample = sample;
referToSample.append("B");
System.out.println(sample);
これによりB
が出力され、sample
およびreferToSample
オブジェクトが同じメモリ参照を参照していることが証明されます。
StringBuilder sample = new StringBuilder();
StringBuilder referToSample = sample;
sample.append("A");
referToSample.append("B");
System.out.println(referToSample);
これは、同じことを証明するAB
を出力します。
StringBuilder sample = new StringBuilder();
StringBuilder referToSample = sample;
referToSample = null;
referToSample.append("A");
System.out.println(sample);
明らかに、これはNullPointerException
をスローします。これは、null参照でappend
を呼び出そうとしているためです。
StringBuilder sample = new StringBuilder();
StringBuilder referToSample = sample;
referToSample = null;
sample.append("A");
System.out.println(sample);
だから私の質問です、最後のコードサンプルがNullPointerException
をスローしないのはなぜですか。その他は、両方が同じメモリ参照を指しているためです。では、なぜそのルールがここに適用されないのですか? null
をreferToSampleに割り当てると、サンプルもnullになり、NullPointerExceptionがスローされますが、スローされません。なぜですか?
null
割り当ては、そのオブジェクトをグローバルに破棄してもvalueは変更されません。このような動作は、追跡が困難なバグや直感に反する動作につながります。それらはその特定の参照のみを破壊します。
簡単にするために、sample
がアドレス12345を指しているとしましょう。これはおそらくアドレスではなく、ここでは物事を簡単にするためにのみ使用されています。 アドレスはtypicalであり、1Object#hashCode()
で指定された奇妙な16進数で表されますが、これは実装に依存します。
StringBuilder sample = new StringBuilder(); //sample refers to
//StringBuilder at 12345
StringBuilder referToSample = sample; //referToSample refers to
//the same StringBuilder at 12345
//SEE DIAGRAM 1
referToSample = null; //referToSample NOW refers to 00000,
//so accessing it will throw a NPE.
//The other reference is not affected.
//SEE DIAGRAM 2
sample.append("A"); //sample STILL refers to the same StringBuilder at 12345
System.out.println(sample);
See diagram
とマークされた行から、そのときのオブジェクトの図は次のとおりです。
図1:
[StringBuilder sample] -----------------> [Java.lang.StringBuilder@00012345]
↑
[StringBuilder referToSample] ------------------------/
図2:
[StringBuilder sample] -----------------> [Java.lang.StringBuilder@00012345]
[StringBuilder referToSample] ---->> [null pointer]
図2は、referToSample
を無効にしても、00012345
にあるStringBuilderへのsample
の参照が壊れないことを示しています。
1GCの考慮事項により、これは現実的ではありません。
最初はreferToSample
が以下に示すようにsample
を参照していたとおっしゃったとおりです。
1。シナリオ1:
2。シナリオ1(続き):
ここでreferToSample
はsample
を参照していたため、書き込み中に「B」を追加しました
referToSample.append("B")
同じことがScenario2:でも起こりました
しかし、3。Scenario3:では、6分数が言ったように、
null
をreferToSample
に割り当てたとき、それがsample
を参照していたとき、変更されませんでしたvalue代わりにreferenceが壊れます= sample
から、現在はnowhereを指しています。以下に示すように:
さて、referToSample
はnowhereを指すので、referToSample.append("A");
の間、値や参照はありません。 Aを追加できます。つまり、NullPointerException
をスローします。
BUT sample
は、初期化したときと同じです。
StringBuilder sample = new StringBuilder();
なので初期化されているため、Aを追加でき、NullPointerException
をスローしません
簡単に言えば、オブジェクトではなく参照変数にnullを割り当てます。
1つの例では、2つの参照変数によって参照されるオブジェクトのstateを変更します。これが発生すると、両方の参照変数に変更が反映されます。
別の例では、1つの変数に割り当てられた参照を変更しますが、これはオブジェクト自体には影響しないため、元のオブジェクトを参照している2番目の変数はオブジェクトの状態の変化に気づきません。
特定の「ルール」について:
2つのオブジェクトが同じオブジェクトを参照している場合、値を変更すると、両方が同じメモリ参照を指しているため、他のオブジェクトにも反映されます。
ここでも、両方の変数が参照する1つのオブジェクトのstateを変更することを参照しています。
では、なぜそのルールがここに適用されないのですか? referToSampleにnullを割り当てると、サンプルもnullになり、nullPointerExceptionがスローされますが、スローされません。なぜですか?
繰り返しますが、ある変数のreferenceを変更すると、他の変数のreferenceに対して完全にno effectになります。
これらは2つのまったく異なるアクションであり、2つのまったく異なる結果になります。
次の簡単な図を参照してください。
referToSample
でメソッドを呼び出すと、[your object]
が更新されるため、sample
にも影響します。しかし、あなたが言うときreferToSample = null
の場合、referToSample
refersを単に変更するだけです。
ここで、「sample」と「referToSample」は同じオブジェクトを参照しています。これは、同じメモリロケーションにアクセスする異なるポインタの概念です。したがって、1つの参照変数をnullに割り当てても、オブジェクトは破棄されません。
referToSample = null;
nullのみを指す「referToSample」を意味します。オブジェクトは同じままで、他の参照変数は正常に機能しています。したがって、nullを指さず、有効なオブジェクトを持つ「サンプル」の場合
sample.append("A");
正常に動作します。しかし、「referToSample」にnullを追加しようとすると、NullPointExceptionが表示されます。あれは、
referToSample .append("A");-------> NullPointerException
そのため、3番目のコードスニペットでNullPointerExceptionが発生しました。
newキーワードを使用すると、ヒープにオブジェクトが作成されます
1)StringBuilderサンプル= new StringBuilder();
2)StringBuilder referToSample = sample;
2)で、referSampleの参照が同じオブジェクトサンプルに作成されます
したがってreferToSample = null; is nulling referSample参照のみがサンプルに影響を与えないため、JavaのガベージコレクションのおかげでNULLポインタ例外が発生しません。
簡単です、Java参照渡しではなく、オブジェクト参照を渡すだけです。