2010-02-22 10 views
40

Biorąc pod uwagę ten kod:Wiele zwrotów: Który ustawia ostateczną wartość zwracaną?

String test() { 
    try { 
     return "1"; 
    } finally { 
     return "2"; 
    } 
} 

wykonaj specyfikacje językowe określić wartość zwracaną przez wywołanie test()? Innymi słowy: czy zawsze jest taka sama w każdej maszynie JVM?

W JVM Sun wartość zwracana to 2, ale chcę mieć pewność, że nie jest to zależne od maszyny wirtualnej.

Odpowiedz

41

Tak, language spec określa, że ​​wynikiem jest "2". Jeśli maszyna wirtualna robi to inaczej, nie jest zgodna ze specyfikacją.

Większość kompilatorów narzeka na to. Na przykład Eclipse twierdzi, że blok powrotu nigdy nie zostanie wykonany, ale jest błędny.

Jest szokująco złe praktyki do pisania kodu takiego, nie zawsze to zrobić :)

+2

I powstrzymał się od niego w chwili myślałem o tym, ale nadal byłem ciekawy :) –

13

Blok finally zawsze będą wykonywane z wyjątkiem w poniższym przykładzie:

String test() { 
    try { 
     System.exit(0); 
    } finally { 
     return "2"; 
    } 
} 

W tym przypadku, JVM zatrzyma się, bez wykonywania bloku finally.

W twoim przykładzie wartość zwracana będzie wynosić 2.

+0

Ci się to odpowiedź – john

7

Tak, jeśli coś powrócić z bloku finally, to zastąpi cokolwiek mogłeś wrócił z bloku try lub catch.

To samo dotyczy także wyjątków. Jeśli rzucisz coś w bloku finally, ten wyjątek zastąpi wyjątek zgłoszony w bloku try lub catch. Uważaj, aby nigdy nie wrzucać czegoś do bloku finally, ponieważ może to ukryć pierwotny powód niepowodzenia.

+1

inny Ciekawostką jest, że jeśli coś się w końcu wrócił z użyciem 'return' następnie każdy rzucony wyjątek jest odrzucane. – sttaq

18

Tak, Java Language Specification jest bardzo jasne w tej kwestii (14.20.2):

Oświadczenie spróbować z bloku finally jest wykonywany przez pierwsze wykonanie bloku try. Wtedy istnieje możliwość wyboru:

  • Jeżeli wykonanie bloku try zakończy się normalnie, [...]
  • Jeżeli wykonanie bloku try kończy się nagle z powodu rzutu o wartości V, [.. .]
  • Jeśli wykonanie bloku try zakończy się nagle z jakiegokolwiek innego powodu R, wówczas wykonywany jest blok finally. Wtedy istnieje możliwość wyboru:
    • Jeżeli wreszcie blok kończy się normalnie, [...]
    • Jeżeli wreszcie blok kończy się nagle z przyczyn S, wówczas oświadczenie próba kończy się nagle z przyczyn S (i powód R jest odrzucany).
0

Można odwołać poniższy link. Mam nadzieję, że będzie dostarczać wszystkie szczegóły:

http://www.programmerinterview.com/index.php/java-questions/will-finally-run-after-return/

Mówi wreszcie blok będzie zawsze powoduje wykonanie lub nawet spróbować blok catch ma powrócić oświadczenie. A jeśli finally blok również zawiera instrukcję return, to zastąpi ona instrukcję return, która znajduje się wewnątrz bloku try lub catch, w takim przypadku każdy wyjątek zgłoszony w try/catch zostanie odrzucony (złe podejście).

Dziękuję Chethan

2

Po odczytaniu kodu bajtowego programu, kod jest w następujący sposób:

bloku finally oświadczenia jest inlined przed stwierdzeniem powrotnej bloku try, więc powrót z finally blok wykonuje się jako pierwszy, a oryginalna instrukcja return nigdy nie działa.

programu:

String test() { 
     try { 
      System.out.println("try"); 
      return "1"; 
     } finally { 
      System.out.println("finally"); 
      return "2"; 
     } 
    } 

To konwertuje do:

String test() 
    { 
     System.out.println("try"); 
     String s = "1"; //temporary variable 
     System.out.println("finally"); 
     return "2"; 
     Exception exception; 
     exception; 
     System.out.println("finally"); 
     return "2"; 
    } 

I programu: z bloku catch:

String test() { 

     try { 
      System.out.println("try"); 
      return "1"; 
     } catch (RuntimeException e) { 
      System.out.println("catch"); 
      return "2"; 
     } finally { 
      System.out.println("finally"); 
      return "3"; 
     } 
    } 

konwertuje do:

String test() 
    { 
     System.out.println("try"); 
     String s = "1"; 
     System.out.println("finally"); 
     return "3"; 
     RuntimeException e; 
     e; 
     System.out.println("catch"); 
     String s1 = "2"; 
     System.out.println("finally"); 
     return "3"; 
     Exception exception; 
     exception; 
     System.out.println("finally"); 
     return "3"; 
    } 

Uwaga: spełnionych przy użyciu JDK 1.7 & dekompilowana użyciu Cavaj.

+1

"throw e" nigdy nie będzie osiągalne. – Viks

+0

dzięki @Viks, dodałem więcej informacji po kilku wyszukiwaniach. –

Powiązane problemy