2013-08-04 21 views
6

Dlaczego StringBuilder nie drukuje co należy wydrukować w małym kodDlaczego StringBuilder nie drukuje?

public final class Test1 { 

    public void test() { 
     System.out.println(setFin().toString()); 
    } 

    protected StringBuilder setFin() { 
     StringBuilder builder = new StringBuilder(); 
     try { 
      builder.append("John"); 
      return builder.append("Ibrahim"); 
     } finally { 
      System.out.println("In finaly"); // builder.append("-DarElBeida"); 
      builder = null; 
     } 
    }  

    public static void main(String args[]){ 
     new Test1().test(); 
    } 
} 

W ostatniej instrukcji wykonywanych w setFin() (w bloku finally) Mam przydzielony null do builder, ale moje odciski kod "In finally" a następnie "JohnIbrahim" . Czy ktoś może mi wyjaśnić, co tu się dzieje?

+1

To jest okropny kod. Prawdopodobnie po prostu chcesz przeczytać http://docs.oracle.com/javase/tutorial/essential/exceptions/finally.html – nes1983

Odpowiedz

5

Jeśli istnieje instrukcja return w bloku try, wykona ona blok finally zanim faktycznie powróci.

A metoda nie zwraca null ponieważ oświadczenie return posiada odniesienie do rzeczywistego StringBuilder obiektu, a nie do zmiennej builder.

Ustawianie builder == null nie usunąć StringBuilder się, to po prostu spada builder „s odniesienie do niego.

Takie zachowanie może być mylące. Żeby było jasne, to może być pomocne, aby powrócić z poza try/catch/finally bloku:

StringBuilder builder = new StringBuilder(); 

try { 
    builder.append("John"); 
    builder.append("Ibrahim"); 
} finally { 
    System.out.println("In finaly"); // builder.append("-DarElBeida"); 
    builder = null; 
} 

return builder; 
+1

Myślę, że PO jest zdezorientowany, dlaczego nie drukuje 'null'. –

+0

nie, oczekuje, że wydrukuje nazwę bez "w końcu". – duffymo

+0

Myślę, że zamieszanie dotyczy tego, dlaczego nie jest to drukowanie 'null' (którego twoje oświadczenie tak naprawdę nie wyjaśnia - to" builder = null "jest" oceniane przed powrotem ", a następnie" powinno zwrócić zero ") – Mat

3

Wracasz builder. Następnie ustaw builder na wartość null. Ale zostało już zwrócone. Nie ma znaczenia, co zrobisz później zmiennej. Zwracana wartość jest już "zablokowana". To, co możesz zrobić, to zepsuć obiekt, który jest zwracany. Na przykład builder.setLength(0) usunie cały tekst do niego.

Teoretycznie można również return null z bloku finally, ale to (zmiana wartości zwracanej) jest wysoce odradzane.

3

Powrót wartość jest oceniana i przechowywane na stosieprzed finally przejazdów grupowych. Zauważ, że wartość na stosie jest faktycznie wartością odniesienia StringBuilder. Tak więc, nawet jeśli ustawisz builder na null, to nie zmieni wartości oszacowanej return już na stosie. Jeśli jednak zwrócona wartość jest odniesieniem do zmiennego obiektu, możesz zmutować obiekt, a zmiany będą widoczne w wartości return.

Na przykład, jeśli dodać poniższego oświadczenia w bloku finally zamiast nullifying odniesienia:

builder.append("Hrithik Roshan"); 

wtedy widać, że zawartość w wartości zwracanej.

Jeśli jednak ponownie uzyskasz returnbuilder, z bloku finally, zostanie ono zastąpione poprzednio ocenianą instrukcją return. Ale pamiętaj, że to nie jest dobry pomysł.

2

finally jest zawsze wykonywany, chyba że JVM ulegnie awarii lub zakończy się przed zakończeniem bloku try.

Jeśli blok try uzupełnia powodu return oświadczeniu wyrazem return oceniana jest w pojedynczą wartość przed z finally sporządzi blokowych. Ta wartość jest zapisywana i zwracana po ukończeniu bloku finally.

Tak więc przypisanie builder = null nie ma wpływu, ponieważ ocena builder.append("Ibrahim") została już zakończona przed wykonaniem finally.

1

builder zawiera odniesienie do utworzonego StringBuilder. Gdy wykonasz builder = null, ustawiasz builder, aby nie przechowywać już tego odniesienia. Sam StringBuilder nadal istnieje (przynajmniej do czasu usunięcia śmieci).

Co się dzieje, że twoja instrukcja return zwraca referencję do StringBuilder. To jest nie zwracanie zmiennej builder; powraca odwołanie do rzeczy, do której odwołuje się builder. Więc nawet jeśli wymazujesz zmienną, instrukcja return ma już odwołanie do utworzonego obiektu.

Jeśli wydrukowałeś builder w swoim bloku 0123-, byłby tam pusty.

0

Pierwsza wykonana instrukcja return, która wykonuje builder.append("Ibrahim"), która zwraca odniesienie StringBuilder. Referecja zostanie zapisana na stosie. Następnie sprawdzono blok finally. Usunięto zmienną lokalną, ale odwołanie do obiektu StringBuilder przekazano do wywołującego po tym, jak metoda faktycznie powróci. Dlatego wydrukowane wszystkie wartości. Błąd polega na tym, że przypisujesz wartość do bloku builder w postaci, która nigdy nie jest używana. Stos zachowuje wartość argumentu instrukcji instrukcji return, zanim został faktycznie zwrócony, tj. Po bloku finally. Jeśli nie chcesz zwracać odwołania z metody, powinieneś return null w bloku finally, który zastąpi wartość w stosie.

} finally { 
    System.out.println("In finaly"); // builder.append("-DarElBeida"); 
    return null; 

}