Instanciação Múltipla Mesmo Objeto

8

O que exatamente acontece em Java quando você instancia o mesmo objeto várias vezes?

Por exemplo:

Test test = new Test();

depois, chamarei de novo, de Test test = new Test();novo ou dentro de um loop. A instanciação anterior será descartada?

userIsAMonkey
fonte

Respostas:

16
  1. cada chamada new Test()cria uma nova instância de objeto da Testclasse
  2. test = new Test();atribui uma referência desse objeto à variáveltest
  3. Uma instrução repetida test = new Test()cria uma segunda instância Teste atribui a referência à variável testnovamente, portanto, a primeira referência é substituída.

Se e quando a primeira instanciação será descartada, no entanto, depende. O Java Runtime Environment rastreia referências, portanto, desde que haja referências a um objeto em uso, o objeto não será descartado. Por exemplo, se entre as etapas 2 e 3, a referência à primeira instanciação for armazenada em outro lugar (como Test test2 = test;) e essa variável ainda estiver no escopo quando a etapa 3 ocorrer, o primeiro objeto não será descartado, pois test2ainda mantém uma referência para isso. No entanto, quando não existe essa declaração e a etapa 3 omite a referência única ao primeiro objeto, a eliminação desse objeto ocorrerá.

Observe que o descarte em si não ocorre imediatamente, mas algumas vezes mais tarde, na próxima vez em que o coletor de lixo for executado. Mas isso é independente da semântica do código discutido, isso é apenas uma questão de memória e desempenho.

Doc Brown
fonte
4
A JVM não faz contagem de referência. Estritamente falando, a especificação não determina como (ou mesmo isso) a coleta de lixo é implementada, mas todas as JVMs convencionais usam algum tipo de coletor de rastreamento.
Michael Borgwardt
@ MichaelBorgwardt: alterei minha resposta devido ao seu comentário.
Doc Brown
if between step 2 and step 3 the reference to the first instantiation is stored somewhere else (like Test test2 = test;), and that variable is still in scope when step 3 occurs...Isso é um tanto pedante, mas a coleta de lixo não se baseia no escopo, mas na acessibilidade. É possível que uma variável esteja no escopo, mas seu valor não seja mais usado e esse valor possa ser coletado como lixo. Os coletores de lixo não têm escopos à mão para tomar decisões com base nisso.
Doval 3/17
@Doval: Concordo, este comentário é pedante ;-)
Doc Brown
5

1: Algumas palavras: não instanciamos objetos, instanciamos classes, e o produto de uma instanciação de classe é um objeto (também chamado de instância). É claro que podemos instanciar uma classe quantas vezes for necessário para criar um objeto novo e diferente a cada instanciação.

2: Seja como for, você não pode ter o código que sugere:

Test test = new Test();
Test test = new Test();

nem você pode ter isso:

for (i=0; i<3; i++) {
    Test test = new Test();
    Test test = new Test();
}

Nenhum será compilado, porque a parte Test testé a declaração da variável test(do tipo Test) e nenhuma linguagem, incluindo Java, permite declarar duas vezes a mesma variável no mesmo escopo.

No entanto, você pode atribuir várias vezes a mesma variável (como o nome indica), com objetos diferentes, como este:

Test test = new Test();
test = new Test();

A primeira linha declara teste atribui a ele um objeto recém-criado. A segunda linha é atribuída a testoutro objeto, também recém-criado.

Observe também que os atalhos são permitidos em Java:

for (i=0; i<3; i++) {
    Test test = new Test();
}

Este loop não será declarado test3 vezes. Entende-se como atribuir três novos objetos diferentes em sequência à variável testque será declarada apenas uma vez. (compare com o loop anterior).

3: O que acontece com a variável teste com os dois objetos do tipo Test?

A variável testrecebe primeiro a referência de um objeto, depois de outro objeto. Uma variável retém apenas a última referência atribuída.

O primeiro objeto do tipo Testnão está mais atribuído test. Se nenhuma outra variável tiver sido designada como referência, esse objeto não poderá ser acessado de forma alguma pelo programa e, portanto, será inútil. É qualificado para a coleta de lixo pelo sistema. Em algum momento, o sistema (a JVM) executará seu coletor de lixo que o limpará da memória.

O segundo objeto permanecerá enquanto pelo menos uma variável fizer referência a ele; o coletor de lixo também cuidará dele e o levará ao cemitério de objetos não referenciados. Essa é a verdadeira vida dos objetos Java :-(

min
fonte
Por acaso encontrei esse erro em uma aula. As classes têm uma propriedade declarada como: WindowManager wm = new WindowsManager (); e, em seguida, um método no qual o programador estava usando essa propriedade, mas escreveu por engano: WindowManager wm = new WindowsManager (); novamente. Não é apenas compilado, mas também executado! Nenhum aviso e, é claro, o aplicativo, que é um teste, não estava funcionando bem. Então percebi que estava criando o objeto no escopo do método e a propriedade nunca foi modificada. Portanto, tenha cuidado
Ricker Silva
1
Como você explicou perfeitamente, isso não é uma reatribuição da mesma variável. Um erro sombreamento semelhante pode ocorrer quando usando um parâmetro se você esquecer a thispalavra-chave, como em construtores: this.name = name.
mins
-1

Resposta curta: todos os objetos criados anteriormente serão descartados se ninguém apontar para eles. Somente o mais recente existirá porque o teste faz referência a ele.

Tulains Córdova
fonte