Esclarecimento Nead para o seguinte código:
StringBuilder sample = new StringBuilder();
StringBuilder referToSample = sample;
referToSample.append("B");
System.out.println(sample);
Isso será impresso de B
forma que provas sample
e referToSample
objetos se refiram à mesma referência de memória.
StringBuilder sample = new StringBuilder();
StringBuilder referToSample = sample;
sample.append("A");
referToSample.append("B");
System.out.println(referToSample);
Isso vai imprimir AB
que também prova o mesmo.
StringBuilder sample = new StringBuilder();
StringBuilder referToSample = sample;
referToSample = null;
referToSample.append("A");
System.out.println(sample);
Obviamente, isso vai lançar NullPointerException
porque estou tentando chamar append
uma referência nula.
StringBuilder sample = new StringBuilder();
StringBuilder referToSample = sample;
referToSample = null;
sample.append("A");
System.out.println(sample);
Então, aqui está minha pergunta, por que o último exemplo de código não está sendo lançado, NullPointerException
porque o que eu vejo e entendo nos dois primeiros exemplos é se dois objetos se referindo ao mesmo objeto, se alterarmos qualquer valor, ele também refletirá para outro porque ambos estão apontando para mesma referência de memória. Então, por que essa regra não se aplica aqui? Se eu atribuir null
a referToSample, sample também deve ser nulo e deve lançar um NullPointerException, mas não está jogando um, por quê?
fonte
sample
está paradosample
. Você apenas mudoureferToSample
.sample
ereferToSample
como objetos, mas eles não são objetos, são variáveis. Uma variável pode conter uma referência a um objeto, mas não é ela própria um objeto. É uma distinção sutil, mas é basicamente a essência da sua confusão.volatile
,final
,=
,==
...) quando aplicado a um objecto variável afecta o ponteiro , não o objecto que se refere.Respostas:
null
atribuições não mudam o valor destruindo globalmente esse objeto. Esse tipo de comportamento levaria a bugs difíceis de rastrear e comportamento contra-intuitivo. Eles apenas quebram aquela referência específica .Para simplificar, digamos que
sample
aponta para o endereço 12345. Este provavelmente não é o endereço e é usado apenas para simplificar as coisas aqui.O endereço é normalmente representado com o hexadecimal estranho fornecido1Object#hashCode()
, mas isso depende da implementação.A partir das linhas marcadas,
See diagram
os diagramas dos objetos naquele momento são os seguintes:Diagrama 1:
Diagrama 2:
O Diagrama 2 mostra que a anulação
referToSample
não quebra a referência desample
ao StringBuilder em00012345
.1 As considerações do GC tornam isso implausível.
fonte
hashCode()
não é a mesma coisa que endereço de memóriahashCode
normalmente o definem para retornar um valor que não tem nada a ver com endereços de memória. Acho que você pode mostrar seu ponto de vista sobre referências a objetos vs. objetos sem mencionarhashCode
. Os detalhes de como obter o endereço de memória podem ser deixados para outro dia.Inicialmente era como você disse que
referToSample
se referiasample
como mostrado abaixo:1. Cenário 1:
2. Cenário 1 (cont.):
Aqui, como
referToSample
estava se referindo asample
, então ele anexou "B" enquanto você escrevereferToSample.append("B")
A mesma coisa aconteceu no Cenário 2:
Mas, em 3. Cenário 3: como disse a hexafração,
quando você atribui
null
parareferToSample
quando ele estava se referindosample
não mudança de valor em vez disso, apenas quebra a referência a partir desample
, e agora ele aponta a lugar nenhum . como mostrado abaixo:Agora, como não
referToSample
aponta para lugar nenhum , embora vocêreferToSample.append("A");
não tenha nenhum valor ou referência onde possa anexar A. Então, ele jogariaNullPointerException
.MAS
sample
ainda é o mesmo que você inicializou comStringBuilder sample = new StringBuilder();
então ele foi inicializado, então agora ele pode anexar A, e não vai lançarNullPointerException
fonte
referToSample = sample;
está se referindo à amostra, está apenas copiando o endereço do que é referenciadoResumindo: você atribui null a uma variável de referência, não a um objeto.
Em um exemplo, você altera o estado de um objeto que é referido por duas variáveis de referência. Quando isso ocorrer, ambas as variáveis de referência refletirão a mudança.
Em outro exemplo, você altera a referência atribuída a uma variável, mas isso não tem efeito sobre o objeto em si e, portanto, a segunda variável, que ainda se refere ao objeto original, não notará qualquer alteração no estado do objeto.
Quanto às suas "regras" específicas:
Novamente, você se refere à alteração do estado de um objeto ao qual ambas as variáveis se referem.
Novamente, você altera a referência de uma variável que não tem absolutamente nenhum efeito na referência da outra variável.
Essas são duas ações completamente diferentes e resultarão em dois resultados completamente diferentes.
fonte
Veja este diagrama simples:
Quando você chama um método on
referToSample
, o[your object]
é atualizado, por isso afetasample
também. Mas quando você dizreferToSample = null
, então você está simplesmente mudando o quereferToSample
se refere .fonte
Aqui, 'sample' e 'referToSample' fazem referência ao mesmo objeto. Esse é o conceito de ponteiro diferente acessando o mesmo local de memória. Portanto, atribuir uma variável de referência a nulo não destrói o objeto.
significa 'referToSample' apontando apenas para nulo, o objeto permanece o mesmo e outras variáveis de referência estão funcionando bem. Portanto, para 'amostra' que não aponta para nulo e tem um objeto válido
funciona bem. Mas se tentarmos acrescentar null a 'referToSample', ele mostrará NullPointException. Isso é,
É por isso que você obteve NullPointerException em seu terceiro trecho de código.
fonte
Sempre que uma nova palavra-chave é usada, ela cria um objeto no heap
1) Amostra StringBuilder = new StringBuilder ();
2) StringBuilder referToSample = amostra;
Em 2) a referência de referSample é criada na mesma amostra de objeto
portanto, referToSample = null; está anulando apenas a referência referSample, não dando efeito à amostra, por isso você não está recebendo a exceção de ponteiro NULL graças à coleta de lixo do Java
fonte
Simplesmente fácil, Java não tem passagem por referência, apenas passa referência de objeto.
fonte