Dlaczego to nie rzuca wyjątku NullPointerException?

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

To wyświetli B, CO udowodni, że obiekty sample i referToSample odnoszą się do tego samego odniesienia do pamięci.

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

To wydrukuje AB, które również udowadniają to samo.

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

Oczywiście to rzuci NullPointerException, ponieważ próbuję wywołać append NA null reference.

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

Oto moje pytanie, dlaczego ostatnia próbka kodu nie rzuca NullPointerException ponieważ to, co widzę i Rozumiem z dwóch pierwszych przykładów, to jeśli dwa obiekty odnoszące się do tego samego obiektu wtedy jeśli zmienimy jakąkolwiek wartość to będzie ona również odzwierciedlać do innych ponieważ oba są wskazujące na to samo odniesienie do pamięci. Więc dlaczego ta zasada nie ma zastosowania tutaj? Jeśli przypisuję null do referToSample, to sample również powinno być null i powinno rzucać NullPointerException, ale to nie jest rzucanie, dlaczego?

Author: commit, 2013-09-05

7 answers

null przypisania nie zmieniają wartości globalnie niszcząc ten obiekt. Takie zachowanie prowadziłoby do trudnych do wyśledzenia błędów i zachowań antyintuicyjnych. Przełamują tylko ten specyficzny odniesienie .

Dla uproszczenia, powiedzmy, że sample wskazuje na adres 12345. To prawdopodobnie nie jest adres i jest używany tylko do uproszczenia tutaj. adres jest zazwyczaj reprezentowany przez dziwny szesnastkowy podany w Object#hashCode(), ale to zależne od wdrożenia.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);

z linii zaznaczonych See diagram wykresy obiektów w tym czasie są następujące:

Diagram 1:

[StringBuilder sample]    -----------------> [java.lang.StringBuilder@00012345]
                                                      ↑
[StringBuilder referToSample] ------------------------/

Diagram 2:

[StringBuilder sample]    -----------------> [java.lang.StringBuilder@00012345]

[StringBuilder referToSample] ---->> [null pointer]

Diagram 2 pokazuje, że anulowanie referToSample nie łamie odniesienia sample do Stringbuildera w 00012345.

1rozważania GC czynią to nieprawdopodobnym.

 89
Author: Andrey Akhmetov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-18 12:17:18

Początkowo było tak jak powiedziałeś referToSample odnosiło się do sample Jak pokazano poniżej:

1. Scenario1:

referToSample odnosi się do próbki

2. Scenario1 (kont.):

referToSample.append ("B")

  • Tutaj jako referToSample odnosiło się do sample, więc dopisało "B" while you write

    referToSample.append("B")

To samo stało się w Scenario2 :

Ale, w 3. Scenario3: jak powiedział hexafraction,

Kiedy przypisujesz null do referToSample kiedy referuje sample nie zmienia wartości zamiast tego po prostu zrywa odniesienie z sample, a teraz wskazuje nigdzie. jak pokazano poniżej:

when referToSample = null

Teraz, jako referToSample punkty nigdzie , więc gdy ty referToSample.append("A"); nie będzie miał żadnych wartości ani referencji, gdzie może dołączyć A. więc rzuci NullPointerException.

BUT sample is still the same as you had initialized it with

StringBuilder sample = new StringBuilder(); Tak więc został zainicjalizowany, więc teraz może dołączyć A i nie rzuci NullPointerException

 61
Author: Parth,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-18 18:16:24

W skrócie: przypisujesz null do zmiennej referencyjnej, a nie do obiektu.

W jednym przykładzie zmienia się stan obiektu, do którego odnoszą się dwie zmienne referencyjne. Gdy to nastąpi, obie zmienne referencyjne będą odzwierciedlać zmianę.

W innym przykładzie zmieniasz odniesienie przypisane do jednej zmiennej, ale nie ma to wpływu na sam obiekt, a więc druga zmienna, która nadal odnosi się do oryginalnego obiektu, nie zauważy żadnej zmiany w stan obiektu.


Tak jak twoje konkretne "zasady":

Jeśli dwa obiekty odnoszą się do tego samego obiektu, to jeśli zmienimy dowolną wartość, to będzie ona również odzwierciedlać inne, ponieważ oba wskazują na to samo odniesienie do pamięci.

Ponownie odnosisz się do zmiany stanujednego obiektu, do którego odnoszą się obie zmienne .

Więc dlaczego ta zasada nie ma zastosowania tutaj? Jeśli przypisuję null do referToSample to sample również powinno być null i to powinien rzucać nullPointerException, ale to nie jest rzucanie, dlaczego?

Ponownie zmieniasz referencję jednej zmiennej, która nie ma absolutnie żadnego wpływu na referencję drugiej zmiennej.

Są to dwa zupełnie różne działania i przyniosą dwa zupełnie różne rezultaty.

 17
Author: Hovercraft Full Of Eels,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-09-05 12:53:49

Zobacz ten prosty diagram:

diagram

Kiedy wywołujesz metodę na referToSample, [your object] jest aktualizowana, więc wpływa również na sample. Ale kiedy mówisz referToSample = null, to po prostu zmieniasz to, co referToSample odsyła do.

 8
Author: Doorknob,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-09-06 01:50:36

Tutaj 'sample' i 'referToSample' odnoszą się do tego samego obiektu.Jest to koncepcja różnych wskaźników dostępu do tej samej lokalizacji pamięci. Przypisanie jednej zmiennej referencyjnej do null nie niszczy obiektu.

   referToSample = null;

Oznacza 'referToSample' tylko wskazując na null, obiekt pozostaje taki sam, a inne zmienne referencyjne działają poprawnie. Tak więc dla 'próbki', która nie wskazuje na null i ma ważny obiekt

   sample.append("A");
Działa dobrze. Ale jeśli spróbujemy dodać null do 'referToSample', pokaże NullPointException. Czyli
   referToSample .append("A");-------> NullPointerException

Dlatego masz NullPointerException w trzecim fragmencie kodu.

 3
Author: NCA,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-09-05 17:32:20

Gdy używane jest słowo kluczowe new tworzy obiekt na stercie

1) StringBuilder sample = new StringBuilder ();

2)StringBuilder referToSample = sample;

W 2) odniesienie do referSample jest tworzone na tej samej próbce obiektu

Tak więc referToSample = null; czy Nulling tylko referSample Reference dające żadnego wpływu na próbkę dlatego nie otrzymujesz wyjątku wskaźnika NULL Dzięki Java ' s Garbage Collection

 0
Author: nitesh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-09-16 09:41:33

Po prostu proste, Java nie ma pass by reference, tylko pass Object reference.

 0
Author: Peerapat A,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-09-18 08:07:29