Instanțiere multiplă a aceluiași obiect (Inginerie software, Java, Orientat Pe Obiecte, Practici De Programare)

userIsAMonkey a intrebat.

Ce se întâmplă mai exact în Java atunci când instanți același obiect de mai multe ori?

De exemplu:

Test test = new Test();

apoi, mai târziu, îl voi apela din nou, Test test = new Test(); din nou sau în interiorul unei bucle. Va fi eliminată instanțierea anterioară?

3 răspunsuri
Doc Brown
  1. fiecare apel new Test() creează o nouă instanță a obiectului Test clasa
  2. test = new Test(); atribuie un referință a acestui obiect la variabila test
  3. O instrucțiune repetată test = new Test() creează o a doua instanță a clasei Test și atribuie referința la aceasta variabilei test din nou, astfel încât prima referință este înlocuită.

Depinde însă dacă și când va fi eliminată prima instanțiere. Mediul de execuție Java urmărește referințele, astfel încât, atât timp cât există referințe la un obiect în uz, obiectul nu va fi eliminat. De exemplu, dacă între pasul 2 și pasul 3 referința la prima instanțiere este stocată în altă parte (cum ar fi Test test2 = test;), iar variabila respectivă este încă în domeniul de aplicare atunci când are loc pasul 3, atunci primul obiect nu este eliminat, deoarece test2 păstrează în continuare o referință la acesta. Cu toate acestea, atunci când nu există o astfel de declarație și pasul 3 omite referința unică la primul obiect, atunci se va produce o eliminare a obiectului respectiv.

Rețineți că eliminarea în sine nu are loc imediat, ci uneori mai târziu, la următoarea rulare a colectorului de gunoi. Dar acest lucru este independent de semantica codului discutat, este doar o problemă de memorie și performanță.

Comentarii

  • JVM face nu numără referințele. Strict vorbind, specificația nu impune modul în care (sau chiar faptul că) este implementată colectarea gunoiului, dar toate JVM-urile mainstream utilizează un fel de colector de urmărire. –  > Por Michael Borgwardt.
  • @MichaelBorgwardt: mi-am modificat răspunsul datorită comentariului dvs. –  > Por 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... Acest lucru este oarecum pedant, dar colectarea gunoiului nu se bazează pe domeniul de aplicare, ci pe accesibilitate. Este posibil ca o variabilă să se afle în domeniul de aplicare, dar valoarea sa să nu mai fie utilizată, iar această valoare poate fi colectată la gunoi. Colectorii de gunoi nu au la îndemână domenii de cuprindere pentru a lua decizii bazate pe acest lucru. –  > Por Doval.
  • @Doval: Sunt de acord, acest comentariu este pedant 😉 –  > Por Doc Brown.
mins

1: Unele formulări: Noi nu instanțiem deloc obiecte, instanțiem clase, iar produsul instanțierii unei clase este un obiect (numit și instanță). Desigur, putem instanția o clasă de câte ori este necesar pentru a crea un obiect nou și diferit la fiecare instanțiere.

2: Mă rog, nu se poate avea codul pe care îl propuneți:

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

nici nu puteți avea acest lucru:

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

Nici unul nu va compila, deoarece partea Test test este declarația variabilei test (de tip Test), iar niciun limbaj, inclusiv Java, nu permite declararea de două ori a aceleiași variabile în același domeniu.

Cu toate acestea, puteți atribui de mai multe ori aceeași variabilă (așa cum sugerează și numele), cu obiecte diferite, astfel:

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

Prima linie declară test și îi atribuie un obiect nou creat. A doua linie atribuie la test un alt obiect, de asemenea nou creat.

Rețineți, de asemenea, că în Java sunt permise scurtăturile:

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

Această buclă nu va declara test de 3 ori. Aceasta este înțeleasă ca fiind atribuirea a trei noi obiecte diferite, în succesiune, variabilei test care va fi declarată o singură dată. (comparați cu bucla anterioară).

3: Ce se întâmplă cu variabila test, , și cu cele două obiecte de tip Test?

Variabila test este atribuită mai întâi referința unui obiect, apoi a unui alt obiect. O variabilă păstrează doar ultima referință atribuită.

Primul obiect de tip Test nu este atribuit la test mai mult. Dacă nu a fost atribuită referința sa niciunei alte variabile, atunci acest obiect nu poate fi accesat în nici un fel de către program, fiind astfel inutil. Sistemul îl face eligibil pentru colectarea de gunoi. La un moment dat, sistemul (JVM) va rula colectorul de gunoi care îl va șterge din memorie.

Cel de-al doilea obiect va supraviețui atâta timp cât cel puțin o variabilă îl va referi, după care colectorul de gunoi se va ocupa și de el și îl va aduce în Cimitirul obiectelor nereferite. Aceasta este adevărata viață a obiectelor Java 🙁

Comentarii

  • S-a întâmplat să găsesc această greșeală într-o clasă. Clasa are o proprietate declarată ca: WindowManager wm = new WindowsManager(); și apoi o metodă în care programatorul folosea această proprietate, dar a scris din greșeală: WindowManager wm = new WindowsManager(); din nou. Nu numai că a compilat, dar a și rulat!!! Fără nici un fel de avertisment și bineînțeles că aplicația, care este una de test, nu funcționa bine. Apoi mi-am dat seama că se crea obiectul în cadrul metodei și proprietatea nu era modificată niciodată. Deci, aveți grijă –  > Por Ricker Silva.
  • După cum ați explicat perfect, aceasta nu este o reatribuire a aceleiași variabile. A greșeală similară de shadowing poate apărea atunci când se utilizează un parametru dacă uitați de this cuvânt cheie, ca în constructori: this.name = name. –  > Por mins.
Tulains Córdova

Răspuns scurt: toate obiectele create anterior vor fi eliminate dacă nimeni nu le indică. Doar cel mai recent va exista pentru că testul îl va referi.