Необходимое разъяснение для следующего кода:
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, тогда образец также должен быть нулевым, и он должен генерировать исключение NullPointerException, но не выбрасывает его, почему?
источник
sample
все ещеsample
. Вы только изменилисьreferToSample
.sample
иreferToSample
как на объекты, но это не объекты, это переменные. Переменная может содержать ссылку на объект, но сама по себе не является объектом. Это тонкое различие, но в основном это суть вашего замешательства.volatile
,final
,=
,==
...) , когда применяются к переменному влияет на указатель , а не объект , он ссылается.Ответы:
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 делают это неправдоподобным.
источник
hashCode()
- это не то же самое, что адрес памятиhashCode
обычно определяют его так, чтобы он возвращал значение, не имеющее ничего общего с адресами памяти. Я думаю, вы можете выразить свою точку зрения относительно ссылок на объекты и объектов без упоминанияhashCode
. Более тонкие моменты получения адреса памяти можно отложить на другой день.Первоначально, как вы сказали,
referToSample
имелось в виду,sample
как показано ниже:1. Сценарий 1:
2. Сценарий 1 (продолжение):
Здесь, как
referToSample
имелось в видуsample
, добавляется буква "B", пока вы пишетеreferToSample.append("B")
То же самое произошло в сценарии 2:
Но в 3. Сценарий 3: как сказано в гексафракции,
при назначении
null
на ,referToSample
когда он имел в видуsample
его не изменить значение вместо этого он просто разрывает ссылку изsample
, и теперь он не указывает нигде . как показано ниже:Теперь, как
referToSample
точки нигде , так что пока выreferToSample.append("A");
это не будете иметь любые значения или ссылки , где он может приобщать А. Таким образом, было бы броситьNullPointerException
.НО
sample
остается таким же, как и вы инициализировали его с помощьюStringBuilder sample = new StringBuilder();
поэтому он был инициализирован, поэтому теперь он может добавлять A и не будет бросатьNullPointerException
источник
referToSample = sample;
вы ссылаетесь на образец, вы просто копируете адрес того, на что ссылаетесьВ двух словах: вы присваиваете null ссылочной переменной, а не объекту.
В одном примере вы изменяете состояние объекта, на который ссылаются две ссылочные переменные. Когда это произойдет, обе ссылочные переменные будут отражать изменение.
В другом примере вы меняете ссылку, назначенную одной переменной, но это не влияет на сам объект, и поэтому вторая переменная, которая все еще ссылается на исходный объект, не заметит никаких изменений в состоянии объекта.
Итак, что касается ваших конкретных «правил»:
Опять же, вы имеете в виду изменение состояния одного объекта, на который ссылаются обе переменные .
Опять же, вы изменяете ссылку на одну переменную, что абсолютно не влияет на ссылку на другую переменную.
Это два совершенно разных действия, которые приведут к двум совершенно разным результатам.
источник
Смотрите эту простую диаграмму:
При вызове метода на
referToSample
, затем[your object]
обновляется, так что это влияетsample
слишком. Но когда вы говоритеreferToSample = null
, вы просто меняете то, к чемуreferToSample
относится .источник
Здесь 'sample' и 'referToSample' ссылаются на один и тот же объект. Это концепция разных указателей, обращающихся к одной и той же области памяти. Таким образом, присвоение одной ссылочной переменной null не уничтожает объект.
referToSample = null;
означает, что «referToSample» указывает только на null, объект остается таким же, а другая ссылочная переменная работает нормально. Итак, для 'образца', который не указывает на нуль и имеет действительный объект
sample.append("A");
работает отлично. Но если мы попытаемся добавить null к «referToSample», он покажет исключение NullPointException. То есть,
referToSample .append("A");-------> NullPointerException
Вот почему в третьем фрагменте кода есть исключение NullPointerException.
источник
Всякий раз, когда используется новое ключевое слово, оно создает объект в куче
1) Пример StringBuilder = новый StringBuilder ();
2) StringBuilder referToSample = sample;
Во 2) Ссылка на referSample создается на том же образце объекта
таким образом, referToSample = null; Обнуляет Только ссылка referSample, не влияющая на образец, поэтому вы не получаете исключение указателя NULL благодаря сборке мусора Java
источник
Просто в Java нет передачи по ссылке, она просто передает ссылку на объект.
источник