2015-06-17 15 views
5

Moje pytanie związane jest z:życie nowego obiektu bez odnoszenia

Co właściwie się dzieje, gdy mamy coś takiego w naszym kodzie:

(new SomeClass()).longMethod(); 

Czy jest jeszcze jakiś rodzaj nienazwane odniesienie (silne?) wskazujące na nowo utworzony obiekt na Sterty nałożone na Stos?

Jeśli nic nie jest w Stack, to w jaki sposób Garbage Collector wie, aby zachować obiekt przez cały czas trwania metody?

Jest to prawdopodobnie taki sam jak

{ 
    // very local scope 
    SomeClass throwAwayRef = new SomeClass(); 
    throwAwayRef.longMethod(); 
} 
+0

Słyszał 'this'? – Ingo

+0

@Ingo - Chcesz opracować? –

+0

Odpowiedz najpierw. Co to jest w metodzie? I skąd się bierze? – Ingo

Odpowiedz

1

tak, odniesienie do nowego obiektu istnieje na stosie.

prosto z Oracle:

Aby uzyskać dostęp do pola, można użyć nazwie odniesienie do obiektu, jak w poprzednich przykładach , czy można użyć dowolnego wyrażenia, która zwraca odwołanie obiektu. Przypomnijmy, że nowy operator zwraca referencję do obiektu . Więc można używać wartości zwracanych od nowa, aby uzyskać dostęp do pól danej nowego obiektu za:

int height = new Rectangle().height;

Stwierdzenie to tworzy nowy Prostokąt obiekt i natychmiast staje się jego wysokość. W istocie instrukcja oblicza domyślną wysokość prostokąta. Należy zauważyć, że po wykonaniu tej instrukcji program nie ma już odwołania do utworzonego prostokąta, ponieważ program nigdy nie zapisywał w dowolnym miejscu odwołania do . Obiekt nie jest odwoływany, a jego zasoby mogą być poddane recyklingowi przez wirtualną maszynę Java.

źródło: https://docs.oracle.com/javase/tutorial/java/javaOO/usingobject.html

+3

więcej dowodu lub przykładu, proszę – jgr208

+0

Metoda wysokości może gdzieś przechowywać "to", więc Oracle nie jest tutaj w porządku. Nie znając kodu wysokości, po prostu nie wiemy, czy odniesienie jest gdzieś przechowywane. – Ingo

+0

@Ingo Zakładam, że chodziło o 'java.awt.Rectangle', który nie ma takiego zachowania, ale robisz dobry punkt dla ogólnego przypadku. –

3

Tak,

new SomeClass().longMethod(); 

jest faktycznie taka sama jak, zwłaszcza z punktu widzenia zbierania śmieci:

{ 
    SomeClass throwAwayRef = new SomeClass(); 
    throwAwayRef.longMethod(); 
} 

in-line wersja ma niejawne odniesienie do nowego obiektu (na stosie). Staje się dostępny do usuwania śmieci, jak tylko zakończy się wywołanie metody.

+0

Należy zauważyć, że dwa fragmenty są różne na poziomie kodu bajtowego, chociaż w rzeczywistości są one funkcjonalnie równoważne. – arshajii

+0

Czy jest to gdzieś udokumentowane lub pozostawione w implementacjach JVM? –

5

Można spojrzeć na kod bajtowy do wglądu:

0: new   #16     // class SomeClass 
    3: dup 
    4: invokespecial #18     // Method SomeClass."<init>":()V 
    7: invokevirtual #19     // Method SomeClass.longMethod:()V 
  • new rzeczywiście alokuje obiektu, odniesienie do którego jest pchany na stosie.
  • dup duplikuje wierzchołek stosu; teraz dwa górne elementy stosu są odniesieniami do nowo utworzonego obiektu.
  • invokespecial tutaj nazywa konstruktora SomeClass, popping stos; teraz stos składa się z tylko jednego odniesienia do naszej instancji SomeClass. Instancja nie jest GCed, ponieważ odniesienie do niej istnieje na stosie.
  • invokevirtual tutaj nazywa longMethod. Znowu instancja nie jest GCed, ponieważ odwołanie do niej nadal istnieje na stosie (i jest wyskakiwane po zakończeniu tej metody, po czym jest ona uprawniona do uzyskania GC).

(new SomeClass()).longMethod(); 

nie jest taki sam jak

{ 
    // very local scope 
    SomeClass throwAwayRef = new SomeClass(); 
    throwAwayRef.longMethod(); 
} 

na poziomie kodu Java, ponieważ obejmuje ono jest astore oraz aload. Jednak te dwie są z pewnością funkcjonalnie równoważne. Instancja SomeClass nadal kwalifikuje się do GC po zakończeniu longMethod (stosy dla dwóch fragmentów będą wyglądały identycznie, gdy zostanie wykonane invokevirtual).


referencyjny:

Powiązane problemy