Nead clarification pour le code suivant:
StringBuilder sample = new StringBuilder();
StringBuilder referToSample = sample;
referToSample.append("B");
System.out.println(sample);
Cela s'imprimera de B
sorte que les preuves sample
et les referToSample
objets se réfèrent à la même référence mémoire.
StringBuilder sample = new StringBuilder();
StringBuilder referToSample = sample;
sample.append("A");
referToSample.append("B");
System.out.println(referToSample);
Cela imprimera AB
qui prouve également la même chose.
StringBuilder sample = new StringBuilder();
StringBuilder referToSample = sample;
referToSample = null;
referToSample.append("A");
System.out.println(sample);
Évidemment, cela jettera NullPointerException
parce que j'essaye d'appeler append
une référence nulle.
StringBuilder sample = new StringBuilder();
StringBuilder referToSample = sample;
referToSample = null;
sample.append("A");
System.out.println(sample);
Donc, voici ma question, pourquoi le dernier exemple de code ne lance-t-il pas NullPointerException
parce que ce que je vois et comprends à partir des deux premiers exemples, c'est si deux objets faisant référence au même objet, si nous modifions une valeur, il reflétera également l'autre car les deux pointent vers même référence mémoire. Alors pourquoi cette règle ne s'applique-t-elle pas ici? Si null
j'assigne à referToSample, sample doit également être null et il doit lancer une NullPointerException mais il n'en lance pas une, pourquoi?
la source
sample
est toujourssample
. Vous avez seulement changéreferToSample
.sample
et enreferToSample
tant qu'objets mais ce ne sont pas des objets, ce sont des variables. Une variable peut contenir une référence à un objet, mais elle n'est pas elle-même un objet. C'est une distinction subtile, mais c'est essentiellement l'essence de votre confusion.volatile
,final
,=
,==
...) , lorsqu'elle est appliquée à une variable d'objet affecte le pointeur , et non l'objet , il se réfère.Réponses:
null
les affectations ne changent pas de valeur en détruisant globalement cet objet. Ce type de comportement conduirait à des bogues difficiles à suivre et à un comportement contre-intuitif. Ils ne cassent que cette référence spécifique .Pour simplifier, disons que cela
sample
pointe vers l'adresse 12345. Ce n'est probablement pas l'adresse, et n'est utilisé que pour simplifier les choses ici.L'adresse est généralement représentée avec l'étrange hexadécimal donné dans1Object#hashCode()
, mais cela dépend de l'implémentation.À partir des lignes marquées,
See diagram
les schémas des objets à ce moment-là sont les suivants:Diagramme 1:
Schéma 2:
Le diagramme 2 montre que l'annulation
referToSample
ne rompt pas la référence desample
à StringBuilder at00012345
.1 Les considérations du CG rendent cela invraisemblable.
la source
hashCode()
n'est pas la même chose que l'adresse mémoirehashCode
définissent généralement pour renvoyer une valeur qui n'a rien à voir avec les adresses mémoire. Je pense que vous pouvez faire votre point sur les références d'objets par rapport aux objets sans mentionnerhashCode
. Les détails de la façon d'obtenir l'adresse mémoire peuvent être laissés pour un autre jour.Initialement , il était comme vous avez dit
referToSample
se référait àsample
comme indiqué ci - dessous:1. Scénario1:
2. Scénario1 (suite):
Ici comme cela
referToSample
faisait référencesample
, donc il a ajouté "B" pendant que vous écrivezreferToSample.append("B")
La même chose s'est produite dans le scénario 2:
Mais, dans 3. Scénario3: comme l'a dit l'hexafraction,
lorsque vous attribuez
null
àreferToSample
quand il faisait référence ,sample
il n'a pas changé la valeur au lieu de cela casse juste la référence desample
, et il fait maintenant nulle part . comme indiqué ci-dessous:Maintenant, comme ne
referToSample
pointe nulle part , alors que vous,referToSample.append("A");
il n'aurait aucune valeur ou référence où il peut ajouter A. Donc, il lanceraitNullPointerException
.MAIS
sample
est toujours le même que vous l'aviez initialisé avecStringBuilder sample = new StringBuilder();
donc il a été initialisé, donc maintenant il peut ajouter A, et ne lancera pasNullPointerException
la source
referToSample = sample;
référence à sample, vous copiez simplement l'adresse de ce qui est référencéEn un mot: vous affectez null à une variable de référence, pas à un objet.
Dans un exemple, vous modifiez l' état d'un objet auquel se réfèrent deux variables de référence. Lorsque cela se produit, les deux variables de référence refléteront le changement.
Dans un autre exemple, vous modifiez la référence affectée à une variable, mais cela n'a aucun effet sur l'objet lui-même, et ainsi la deuxième variable, qui fait toujours référence à l'objet d'origine, ne remarquera aucun changement d'état de l'objet.
En ce qui concerne vos "règles" spécifiques:
Encore une fois, vous faites référence à la modification de l' état du seul objet auquel les deux variables font référence.
Encore une fois, vous modifiez la référence d'une variable qui n'a absolument aucun effet sur la référence de l'autre variable.
Ce sont deux actions complètement différentes et aboutiront à deux résultats complètement différents.
la source
Voir ce schéma simple:
Lorsque vous appelez une méthode sur
referToSample
, puis[your object]
est mis à jour, il affectesample
aussi. Mais quand vous ditesreferToSample = null
, vous changez simplement de quoi ilreferToSample
s'agit .la source
Ici, «sample» et «referToSample» font référence au même objet. C'est le concept de pointeur différent accédant au même emplacement mémoire. Ainsi, affecter une variable de référence à null ne détruit pas l'objet.
signifie 'referToSample' ne pointant que sur null, l'objet reste le même et les autres variables de référence fonctionnent correctement. Donc pour 'sample' qui ne pointe pas sur null et qui a un objet valide
fonctionne très bien. Mais si nous essayons d'ajouter null à 'referToSample', cela affichera NullPointException. C'est,
C'est pourquoi vous avez NullPointerException dans votre troisième extrait de code.
la source
Chaque fois qu'un nouveau mot-clé est utilisé, il crée un objet au niveau du tas
1) exemple StringBuilder = nouveau StringBuilder ();
2) StringBuilder referToSample = exemple;
En 2) la référence de referSample est créée sur le même objet échantillon
donc referToSample = null; Nulling Seule la référence referSample ne donne aucun effet à l'échantillon, c'est pourquoi vous n'obtenez pas d'exception de pointeur NULL grâce à la récupération de place de Java
la source
Simplement facile, Java n'a pas de passe par référence, il passe simplement la référence d'objet.
la source