1. ホーム
  2. java

[解決済み] なぜNullPointerExceptionが発生しないのですか?

2023-04-07 17:38:13

質問

以下のコードについて教えてください。

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 を呼び出そうとしているのですから。 append を呼び出そうとしているからです。

StringBuilder sample = new StringBuilder();
StringBuilder referToSample = sample;
referToSample = null;
sample.append("A");
System.out.println(sample);

ここで質問ですが、なぜ最後のコードサンプルは NullPointerException なぜなら、私が最初の2つの例から見て理解したことは、2つのオブジェクトが同じオブジェクトを参照している場合、何らかの値を変更すると、それはもう一方にも反映されるということです。では、なぜここではそのルールが適用されないのでしょうか?もし私が null をreferToSampleに代入すると、sampleもnullになり、NullPointerExceptionが投げられるはずですが、投げられないのはなぜでしょうか?

どのように解決するのですか?

null 割り当てが変更されない をグローバルに破壊することによって変更することはできません。そのような動作は、追跡困難なバグや直感に反する動作につながるでしょう。彼らは、その特定の 参照 .

簡単のために、次のようにしましょう。 sample はアドレス 12345 を指しているとします。これはおそらくアドレスではなく、ここでは物事を単純にするために使われているだけです。 通常 で与えられる奇妙な 16 進数で表されます。 Object#hashCode() で表されますが、これは実装に依存します。 1

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 の参照は壊れません。 sample での StringBuilder への参照は壊れません。 00012345 .

1 GC を考慮すると、これはありえないことです。