Почему это не бросает 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 но он не бросает один, почему?
7 ответов:
nullзадания не меняются стоимостью путем глобального уничтожения этого объекта. Такое поведение привело бы к трудноуловимым ошибкам и нелогичному поведению. Они только нарушают этот конкретный ссылка.для простоты, скажем, что
sampleадрес 12345. Это, вероятно, не адрес, и используется только для упрощения здесь.адрес обычно представлены со странным шестнадцатеричный дан в1Object#hashCode(), но это зависит от реализации.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:
2. Сценарий 1 (Продолжение.):
здесь
referToSampleимел в видуsample, поэтому он добавил "B" пока ты пишешь
referToSample.append("B")то же самое случилось в Scenario2:
а, в 3. Scenario3 : как hexafraction сказал:
при назначении
nullдоreferToSampleкогда он имел в видуsampleон не изменился стоимостью вместо этого он просто ломает ссылка Сsample, и теперь он указывает нигде. как показано ниже:
теперь, как
referToSampleочки нигде, так что пока тыreferToSample.append("A");он не будет иметь никаких значений или ссылок, где он может добавить A. Итак, он броситNullPointerException.но
sampleвсе так же, как вы инициализировали его с
StringBuilder sample = new StringBuilder();так что он был инициализирован, так что теперь он может добавить A, и не будет бросатьNullPointerException
в двух словах: вы присваиваете null ссылочной переменной, а не объекту.
в одном примере изменения state объекта, на который ссылаются две ссылочные переменные. Когда это происходит, обе ссылочные переменные будут отражать изменения.
в другом примере вы изменяете ссылку, назначенную одной переменной, но это не влияет на сам объект, и поэтому вторая переменная, которая все еще ссылается на исходный объект, не будет обратите внимание на любое изменение состояния объекта.
Что касается ваших конкретных "правил":
Если два объекта ссылаются на один и тот же объект, то если мы изменим какое-либо значение, то оно также отразится на другом, потому что оба указывают на одну и ту же ссылку на память.
опять же, вы ссылаетесь на изменение state из одного объекта, что оба переменные относятся.
Так почему же это правило не применяется здесь? если я назначьте null для referToSample, тогда образец также должен быть null, и он должен бросить nullPointerException, но он не бросает, почему?
опять же, вы измените ссылка одной переменной, которая имеет абсолютно нет эффекта на ссылка другой переменной.
Это два совершенно разных действия и приведут к двум совершенно разным результатам.
смотрите эту простую диаграмму:
когда вы называете метод 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




Comments