Почему это не бросает NullPointerException?



Nead разъяснение для следующего кода:



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 потому что то, что я вижу и понимаю из первых двух примеров, - это если два объекта ссылаются на один и тот же объект, то если мы изменим какое-либо значение, то оно также отразится на другом, потому что оба указывают на одну и ту же ссылку на память. Так почему же это правило не применяется здесь? Если я назначу null для referToSample то образец также должен быть null и он должен бросить NullPointerException но он не бросает один, почему?

609   7  

7 ответов:

null задания не меняются стоимостью путем глобального уничтожения этого объекта. Такое поведение привело бы к трудноуловимым ошибкам и нелогичному поведению. Они только нарушают этот конкретный ссылка.

для простоты, скажем, что sample адрес 12345. Это, вероятно, не адрес, и используется только для упрощения здесь. адрес обычно представлены со странным шестнадцатеричный дан в 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 делают это неправдоподобным.

первоначально это было так, как вы сказали referToSample имел в виду sample как показано ниже:

1. Сценарий1:

referToSample refers to sample

2. Сценарий 1 (Продолжение.):

referToSample.append("B")

  • здесь referToSample имел в виду sample, поэтому он добавил "B" пока ты пишешь

    referToSample.append("B")

то же самое случилось в Scenario2:

а, в 3. Scenario3 : как hexafraction сказал:

при назначении null до referToSample когда он имел в виду sample он не изменился стоимостью вместо этого он просто ломает ссылка С sample, и теперь он указывает нигде. как показано ниже:

when referToSample = null

теперь, как referToSample очки нигде, так что пока ты referToSample.append("A"); он не будет иметь никаких значений или ссылок, где он может добавить A. Итак, он бросит NullPointerException.

но sample все так же, как вы инициализировали его с

StringBuilder sample = new StringBuilder(); так что он был инициализирован, так что теперь он может добавить A, и не будет бросать NullPointerException

в двух словах: вы присваиваете null ссылочной переменной, а не объекту.

в одном примере изменения state объекта, на который ссылаются две ссылочные переменные. Когда это происходит, обе ссылочные переменные будут отражать изменения.

в другом примере вы изменяете ссылку, назначенную одной переменной, но это не влияет на сам объект, и поэтому вторая переменная, которая все еще ссылается на исходный объект, не будет обратите внимание на любое изменение состояния объекта.


Что касается ваших конкретных "правил":

Если два объекта ссылаются на один и тот же объект, то если мы изменим какое-либо значение, то оно также отразится на другом, потому что оба указывают на одну и ту же ссылку на память.

опять же, вы ссылаетесь на изменение state из одного объекта, что оба переменные относятся.

Так почему же это правило не применяется здесь? если я назначьте null для referToSample, тогда образец также должен быть null, и он должен бросить nullPointerException, но он не бросает, почему?

опять же, вы измените ссылка одной переменной, которая имеет абсолютно нет эффекта на ссылка другой переменной.

Это два совершенно разных действия и приведут к двум совершенно разным результатам.

смотрите эту простую диаграмму:

diagram

когда вы называете метод on referToSample, потом [your object] обновляется, так что это влияет sample тоже. Но когда вы говорите referToSample = null, тогда ты просто меняешь что referToSampleотносится для.

здесь 'sample' и 'referToSample' ссылаются на один и тот же объект.Это концепция разных указателей, обращающихся к одной и той же ячейке памяти. Таким образом, присвоение одной ссылочной переменной null не уничтожает объект.

   referToSample = null;

означает 'referToSample' только указывая на null, объект остается таким же и другие ссылочные переменные работают нормально. Поэтому для "образца", который не указывает на null и имеет действительный объект

   sample.append("A");

работает нормально. Но если мы попытаемся добавить null для 'referToSample', он покажет NullPointException. То есть,

   referToSample .append("A");-------> NullPointerException

вот почему вы получили NullPointerException в вашем третьем фрагменте кода.

всякий раз, когда a new ключевое слово используется, он создает объект в куче

1) StringBuilder sample = new StringBuilder ();

2) StringBuilder referToSample = sample;

в 2) Ссылка referSample создается на том же объекте sample

referToSample = null; обнуление только ссылки referSample не дает никакого эффекта для выборки вот почему вы не получаете исключение нулевого указателя Благодаря сборке мусора Java

просто легко, Java не имеют pass by reference, он просто передает ссылку на объект.

Comments

    Ничего не найдено.