Sonunda bir blok her zaman Java'da yürütülür mü?


2382

Bu kod göz önüne alındığında , ne olursa olsun , bloğun her zaman çalıştığından kesinlikle emin olabilir miyim ?finallysomething()

try {  
    something();  
    return success;  
}  
catch (Exception e) {   
    return failure;  
}  
finally {  
    System.out.println("I don't know if this will get printed out");
}

473
Girmediyse, anahtar kelime adlandırılmalıdır probably.
Öğlen İpek




27
@BinoyBabu, sonuçlandırıcı ! = finally; finalizer == finalize()yöntem.
jaco0646

Yanıtlar:


2698

Evet, veya kod bloklarının finallyyürütülmesinden sonra çağrılacaktır .trycatch

Çağrılmayacak tek zaman finally:

  1. Eğer çağırırsan System.exit()
  2. Eğer çağırırsan Runtime.getRuntime().halt(exitStatus)
  3. JVM önce çökerse
  4. JVM tryveya catchbloğunda sonsuz bir döngüye (veya kesintisiz, sonlandırılamayan başka bir ifadeye) ulaşırsa
  5. İşletim sistemi zorla JVM işlemini sonlandırırsa; örneğin, kill -9 <pid>UNIX'te
  6. Ana bilgisayar sistemi ölürse; örneğin, elektrik kesintisi, donanım hatası, işletim sistemi paniği, vb.
  7. finallyBlok bir daemon iş parçacığı tarafından yürütülecekse ve diğer tüm daemon olmayan iş parçacıkları önce çıkarsa finallyçağrılır

44
Aslında bloğun yürütülmesini thread.stop()mutlaka engellemez finally.
Piotr Findeisen

181
Nasıl olduğunu söylemek ilgili finallyblok adı verilecek sonratry bloktan ve önce kontrol aşağıdaki ifadelere geçer. Bu sonsuz bir döngü içeren try bloğu ile uyumludur ve bu nedenle sonunda blok asla gerçekte çağrılmaz.
Andrzej Doyle

9
iç içe try-catch-nihayet blokları kullandığımızda başka bir durum daha var
ruhungry

7
Ayrıca, sonunda daemon iş parçacığı tarafından atılan istisna durumunda blok çağrılmaz.
Amrish Pandey

14
@BinoyBabu - Bu sonlandırıcı hakkında, sonunda engellemiyor
avmohan

567

Örnek kod:

public static void main(String[] args) {
    System.out.println(Test.test());
}

public static int test() {
    try {
        return 0;
    }
    finally {
        System.out.println("finally trumps return.");
    }
}

Çıktı:

finally trumps return. 
0

18
Bilginize: C # 'da davranış, finally-cuse içindeki ifadenin değiştirilmesine return 2;izin verilmemesi dışında aynıdır (Derleyici Hatası).
Alexander Pacha

15
İşte bilinmesi gereken önemli bir ayrıntı: stackoverflow.com/a/20363941/2684342
WoodenKitty

18
Sonunda bloğun kendisine bir return ifadesi bile ekleyebilirsiniz, bu da önceki dönüş değerini geçersiz kılar. Bu ayrıca, ele alınmayan istisnaları sihirli bir şekilde atar. Bu noktada, kodunuzu yeniden düzenlemeyi düşünmelisiniz.
Zyl

8
Bu, sonunda geri dönüşün düştüğünü gerçekten kanıtlamaz. Dönüş değeri arayan kodundan yazdırılır. Çok kanıtlıyor gibi görünmüyor.
Trimtab

20
Üzgünüm, ama bu bir kanıt değil. Bu örneğin, tüm Java platformlarında her zaman bu şekilde davrandığını ve benzer örneklerin de her zaman bu şekilde davrandığını gösterebiliyorsanız, bu bir kanıttır.
Stephen C

391

Ayrıca, kötü uygulama olmasına rağmen, sonunda blokta bir iade ifadesi varsa, normal bloktan başka bir dönüşü koyacaktır. Yani, aşağıdaki blok yanlış döndürür:

try { return true; } finally { return false; }

Nihayet bloktan istisnalar atmakla aynı şey.


95
Bu gerçekten kötü bir uygulamadır. Neden kötü olduğu hakkında daha fazla bilgi için stackoverflow.com/questions/48088/… adresine bakın .
John Meagher

23
Kabul. Son olarak {} içindeki bir dönüş, {} denemesinde atılan istisnaları yoksayar. Korkunç!
neu242

8
@ dominicbri7 Neden daha iyi bir uygulama olduğunu düşünüyorsunuz? Ve işlev / yöntem geçersiz olduğunda neden farklı olmalı?
corsiKa

8
Aynı nedenle ASLA benim C ++ kodları goto's kullanmayın. Bence çoklu geri dönüşler okumayı zorlaştırır ve hata ayıklamayı zorlaştırır (tabii ki gerçekten basit durumlarda geçerli değildir). Sanırım bu sadece kişisel tercih ve sonunda her iki yöntemi kullanarak aynı şeyi elde edebilirsiniz
dominicbri7

16
Bir çeşit istisnai durum ortaya çıktığında birkaç geri dönüş eğilimi gösteririm. Sanki (devam etmemek için bir sebep var) geri dönüyormuş gibi;
iHearGeoff

257

İşte Java Dil Spesifikasyonu'ndaki resmi kelimeler.

14.20.2. Sonunda try-catch-nihayet yürütülmesi

Bir trybir ile deyim finallybloğu ilk yürüterek yürütülür trybloğu. Sonra bir seçenek var:

  • tryBloğun yürütülmesi normal şekilde tamamlanırsa, [...]
  • tryBloğun yürütülmesi throwbir V değerinin a nedeniyle aniden tamamlanırsa , [...]
  • Yürütülmesi durumunda tryblokta başka nedenle aniden tamamlar R , daha sonra finallyblok yürütülür. Sonra bir seçenek var:
    • Nihayet blok normal şekilde tamamlanırsa, tryifade R nedeni için aniden tamamlanır .
    • Eğer finallyblok nedenle aniden tamamlar S , daha sonra tryaniden sebeple deyimi tamamlamalar S ( ve neden R atılır ).

İçin şartname returnbunu açıkça ortaya koymaktadır:

JLS 14.17 İade Beyanı

ReturnStatement:
     return Expression(opt) ;

Kontrolü içeren yöntemi ya da kurucuyu davet eden kişiye aktarma girişimireturn olmayan bir deyim .Expression

Bir returnbir deyimiyle Expression girişimi onu içeren yöntemin invoker kontrolü aktarmak üzere, değeri Expressionyöntemi çağırma değeri olur.

Yukarıdaki açıklamalar "demek girişimleri aktarımı kontrolüne sadece" yerine " transfer kontrol eğer varsa, çünkü" tryyöntemi veya olan yapıcı içindeki ifadeler tryblokları içeren returnaçıklama, daha sonra herhangi bir finallyolanların maddeleri trytabloların en dıştaki içteki, sırayla çalıştırılır , kontrol yöntem veya kurucunun davet edicisine aktarılmadan önce. Bir finallycümlenin aniden tamamlanması, bir returnifade tarafından başlatılan kontrolün transferini bozabilir .


163

Diğer yanıtlara ek olarak, 'nihayet' in try..catch bloğu tarafından herhangi bir istisna / döndürülen değeri geçersiz kılma hakkına sahip olduğuna dikkat etmek önemlidir. Örneğin, aşağıdaki kod 12 değerini döndürür:

public static int getMonthsInYear() {
    try {
        return 10;
    }
    finally {
        return 12;
    }
}

Benzer şekilde, aşağıdaki yöntem bir istisna atmaz:

public static int getMonthsInYear() {
    try {
        throw new RuntimeException();
    }
    finally {
        return 12;
    }
}

Aşağıdaki yöntem bunu atmasına rağmen:

public static int getMonthsInYear() {
    try {
        return 12;          
    }
    finally {
        throw new RuntimeException();
    }
}

63
Ortadaki durumun, nihayet bir bloğun içinde bir iade ifadesine sahip olmanın kesinlikle korkunç olmasının nedeni kesinlikle belirtilmelidir (herhangi bir Throwable'ı gizleyebilir).
Dimitris Andreou

2
Kim bastırılmak istemez kiOutOfMemoryError ? ;)
RecursiveExceptionException

Test ettim ve böyle bir hatayı bastırıyor (yipes!). Derlediğimde de bir uyarı oluşturur (yay!). Ve kullandığınız sonra bir dönüş değişken tanımlama ve kendisine çalışabilirsiniz return retVal sonrafinally tabii bu kod aksi mantıklı değildir çünkü diğer bazı istisnalar bastırılmış varsayar rağmen, bloğun.
Maarten Bodewes

120

Yukarıdaki örneği hafif bir değişiklikle denedim.

public static void main(final String[] args) {
    System.out.println(test());
}

public static int test() {
    int i = 0;
    try {
        i = 2;
        return i;
    } finally {
        i = 12;
        System.out.println("finally trumps return.");
    }
}

Yukarıdaki kod çıktıları:

Sonunda dönüş koz.
2

Bunun nedeni return i;, yürütüldüğünde i2'nin bir değere sahip olmasıdır. Bundan sonra finallyblok 12'ye atanır ive sonra System.outdışarı yürütülür.

finallyBloğu yürüttükten sonra blok try12 döndürmek yerine 2 döndürür, çünkü bu dönüş ifadesi tekrar yürütülmez.

Eğer Eclipse Bu kodu hata ayıklamak olacak o zaman yürüttükten sonra bir his alırsınız System.outait finallybloğunun returntablosu trybloğunun tekrar yürütülür. Ancak durum böyle değil. Basitçe 2 değerini döndürür.


10
Bu örnek harika, onlarca nihayet ilgili iş parçacığında bahsedilmeyen bir şey ekliyor. Bence neredeyse hiçbir geliştirici bunu bilemez.
HopefullyHelpful

4
iİlkel değil, bir Tamsayı nesnesi ne olurdu ?
Yamcha

Bu davayı anlamakta zorlanıyorum. docs.oracle.com/javase/specs/jls/se8/html/jls-14.html#jls-14.17 , " İfadeli bir iade ifadesi, kontrolü yöntemi veya lambda gövdesinin Eğer .... İfadenin değerlendirilmesi normal bir şekilde tamamlanırsa, bir değer üretir. döndürülen değeri etkilemez, düzelt beni.
meexplorer

Ama bununla ilgili herhangi bir kanıt bulamadım, burada geri dönüşün ifadeyi tekrar değerlendirmediği belirtiliyor.
meexplorer

1
@ explorer biraz geç oldu, ancak JLS 14.20.2'de açıklandı . Sonunda try-catch ve nihayet try-catch-icra - biraz karmaşık ifade 14.17. İade Beyanı da okunmalıdır
user85421

117

İşte Kevin'in cevabının bir ayrıntısı . Döndürülecek ifadenin finally, daha sonra döndürülse bile daha önce değerlendirildiğini bilmek önemlidir .

public static void main(String[] args) {
    System.out.println(Test.test());
}

public static int printX() {
    System.out.println("X");
    return 0;
}

public static int test() {
    try {
        return printX();
    }
    finally {
        System.out.println("finally trumps return... sort of");
    }
}

Çıktı:

X
finally trumps return... sort of
0

8
Bilmek önemlidir.
Aminadav Glickshtein

Bilmek güzel ve mantıklı. Görünüşe göre aslında dönüşün değerini döndürmek bundan sonra gelir finally. Dönüş değerini ( printX()burada) hesaplamak yine de ondan önce gelir.
Albert

3 "dönen" puan ile iyi bir örnek!
radistao

Hayır! Yukarıdaki kod değiştirmelisiniz System.out.println("finally trumps return... sort of");ileSystem.out.print("finally trumps return in try"); return 42;
Pacerier

54

Nihayet bir blok fikri budur. Aksi takdirde atlanabilecek temizlik işlemleri yaptığınızdan emin olmanızı sağlar, çünkü elbette diğer şeylerin yanı sıra geri dönersiniz.

Son olarak çağrılan bakılmaksızın ne olur (try bloğundaki sürece aramak System.exit(int)veya Java Virtual Machine başladı başka bir nedenle dışarı).


Bu çok zayıf bir cevap. stackoverflow.com/a/65049/715269
Gangnus

42

Bunu düşünmenin mantıklı bir yolu:

  1. Son olarak bir bloğa yerleştirilen kod , try bloğunda ne olursa olsun yürütülmelidir
  2. Bu nedenle, try bloğundaki kod bir değer döndürmeye veya bir istisna atmaya çalışırsa, son blok yürütülene kadar öğe 'rafa' yerleştirilir
  3. Nihayet bloktaki kodun (tanım gereği) yüksek önceliği olduğundan, istediği her şeyi geri verebilir veya atabilir. Bu durumda 'rafta' kalan herhangi bir şey atılır.
  4. Bunun tek istisnası, VM'nin try bloğu sırasında tamamen kapanması, örneğin 'System.exit'

10
Bu sadece "düşünmenin mantıklı bir yolu" mu yoksa son blokun spesifikasyonlara göre çalışması gerçekten böyle mi planlanıyor? Bir Sun kaynağına bağlantı burada çok ilginç olurdu.
Matias

21

son olarak anormal program sonlandırması olmadıkça (System.exit (0) .. çağrısı gibi) yürütülür. böylece, sysout'unuz yazdırılacak



18

Son olarak blok, bir JVM çökmesinden veya çağrısından kaynaklanan anormal program sonlandırması olmadığı sürece her zaman yürütülür System.exit(0).

Bunun da ötesinde, nihayet bloğundan döndürülen herhangi bir değer, nihayet bloğun yürütülmesinden önce döndürülen değeri geçersiz kılacaktır, bu yüzden nihayet try kullanırken tüm çıkış noktalarını kontrol etmeye dikkat edin.


18

Hayır, her zaman bir istisna durumu // System.exit (0) değildir; nihayet blok önce nihayet yürütülmesini engeller.

  class A {
    public static void main(String args[]){
        DataInputStream cin = new DataInputStream(System.in);
        try{
            int i=Integer.parseInt(cin.readLine());
        }catch(ArithmeticException e){
        }catch(Exception e){
           System.exit(0);//Program terminates before executing finally block
        }finally{
            System.out.println("Won't be executed");
            System.out.println("No error");
        }
    }
}

Ve gerçekten System.exit () 'i asla aramamanızın nedenlerinden biri de budur
Franz D.

13

Sonunda her zaman çalıştırmak tüm mesele bu, sadece dönüşten sonra kodda göründüğü için bu nasıl uygulandığı anlamına gelmez. Java çalışma zamanı, trybloktan çıkarken bu kodu çalıştırma sorumluluğuna sahiptir .

Örneğin, aşağıdakilere sahipseniz:

int foo() { 
    try {
        return 42;
    }
    finally {
        System.out.println("done");
    }
}

Çalışma zamanı şöyle bir şey üretecektir:

int foo() {
    int ret = 42;
    System.out.println("done");
    return 42;
}

Yakalanmayan bir istisna atılırsa, finallyblok çalışır ve istisna yayılmaya devam eder.


11

Bunun nedeni, i değerini 12 olarak atamanız, ancak i değerini işleve döndürmemenizdir. Doğru kod aşağıdaki gibidir:

public static int test() {
    int i = 0;
    try {
        return i;
    } finally {
        i = 12;
        System.out.println("finally trumps return.");
        return i;
    }
}

10

Çünkü nihayet bir blok, siz çağırmadıkça System.exit()(veya iş parçacığı çökmedikçe) her zaman çağrılır .


10

Kısacası, resmi Java Belgelerinde ( Buraya tıklayın ), yazılmıştır -

JVM, try veya catch kodu yürütülürken çıkarsa, nihayet blok yürütülemeyebilir. Benzer şekilde, try veya catch kodunu yürüten iş parçacığı kesintiye uğrarsa veya öldürülürse, uygulama bir bütün olarak devam etse bile son olarak blok yürütülemeyebilir.


10

Cevap basit EVET .

GİRİŞ:

try{
    int divideByZeroException = 5 / 0;
} catch (Exception e){
    System.out.println("catch");
    return;    // also tried with break; in switch-case, got same output
} finally {
    System.out.println("finally");
}

ÇIKTI:

catch
finally

1
Cevap basit HAYIR.
Christophe Roussy

1
@ChristopheRoussy Nasıl? Açıklayabilir misiniz lütfen?
Tanışma

1
kabul edilen cevabı okuyun, asıl soru 'Her zaman çalıştırılacak mı' ile ilgilidir ve her zaman olmayacaktır. Sizin durumunuzda bu olacak ama bu orijinal soruya cevap vermiyor ve hatta yanıltıcı yeni başlayanlar bile olabilir.
Christophe Roussy

o zaman hangi durumda idam olmayacak?
Tanışma

Diğer cevaplarda belirtilen tüm durumlarda, 1000'den fazla oylama ile kabul edilen cevaba bakınız.
Christophe Roussy

9

Evet aranacak. Sonunda bir anahtar kelimeye sahip olmanın asıl amacı budur. Eğer try / catch bloğundan atlamak sadece nihayet bloğu atlayabilirse, System.out.println dosyasını try / catch'in dışına koymakla aynıydı.


9

Evet, sonunda blok her zaman yürütülür. Geliştiricilerin çoğu, veritabanı bağlantısını, sonuç kümesi nesnesini, ifade nesnesini kapatarak bu bloğu kullanır ve ayrıca işlemi geri almak için java hazırda bekletme moduna kullanır.


9

HER ZAMAN DEĞİL

Java Dili belirtimi try- catch- finallyve try- catchbloklarının 14.20.2'de nasıl çalıştığını açıklar
. Hiçbir yerde finallybloğun her zaman yürütüldüğünü belirtmez . Ancak try- catch- finallyve try- finallybloklarının tamamlandığı tüm durumlar için, tamamlanmadan önce finallyyapılması gerektiğini belirtir .

try {
  CODE inside the try block
}
finally {
  FIN code inside finally block
}
NEXT code executed after the try-finally block (may be in a different method).

JLS garanti etmez FIN sonra yürütülür KODU . JLS, CODE ve NEXT yürütülürse, FIN'in her zaman CODE ve NEXT öncesinde yürütüleceğini garanti eder .

JLS neden finallybloğun her zaman trybloktan sonra yürütüldüğünü garanti etmiyor ? Çünkü bu imkansız. JVM'nin, trybloğu tamamladıktan hemen sonra ancak bloğun yürütülmesinden önce iptal edilmesi (öldürme, çökme, kapatma) olası değildir, ancak olası değildir finally. JLS'nin bundan kaçınmak için yapabileceği hiçbir şey yoktur.

Böylece, uygun davranışları için finally, tryblokları tamamlandıktan sonra her zaman yürütülen bloklara bağlı olan herhangi bir yazılım hatalandırılır.

returntrybloktaki talimatlar bu konuyla ilgili değildir. Yürütme try- catch- işaretinden sonra koda ulaşırsa finally, finallybloğun blok returniçinde talimatlar olsun veya olmasın, yürütüleceği garanti edilir try.


8

Evet, olacak. Aksi takdirde System.exit () çağrılmadıkça veya JVM çökmedikçe, try veya catch bloğunuzda ne olursa olsun. blok (lar) da herhangi bir dönüş ifadesi varsa, nihayet bu dönüş ifadesinden önce yürütülür.


8

Evet olacak. Sadece JVM çıkışları veya çökmeleri olmaz


8

Ekleme @ vibhash cevabı başka hiçbir cevap aşağıdaki gibi bir değişken nesne durumunda ne açıkladığı gibi.

public static void main(String[] args) {
    System.out.println(test().toString());
}

public static StringBuffer test() {
    StringBuffer s = new StringBuffer();
    try {
        s.append("sb");
        return s;
    } finally {
        s.append("updated ");
    }
}

Çıktı olacak

sbupdated 

Java 1.8.162 itibariyle, bu çıktı değildir.
Sam

8

Bunu denedim, tek iş parçacıklı.

public static void main(String args[]) throws Exception {
    Object obj = new Object();
    try {
        synchronized (obj) {
            obj.wait();
            System.out.println("after wait()");
        }
    } catch (Exception ignored) {
    } finally {
        System.out.println("finally");
    }
}

main ThreadOlacak waitdolayısıyla sonsuza devlet finallydenilen asla ,

böylece konsol çıkışı olmaz print String:wait() veyafinally

@Stephen C ile hemfikir olunan yukarıdaki örnek, burada bahsedilen 3. durumdan biridir :

Aşağıdaki kodda daha fazla sonsuz döngü olasılığı eklemek:

// import java.util.concurrent.Semaphore;

public static void main(String[] args) {
    try {
        // Thread.sleep(Long.MAX_VALUE);
        // Thread.currentThread().join();
        // new Semaphore(0).acquire();
        // while (true){}
        System.out.println("after sleep join semaphore exit infinite while loop");
    } catch (Exception ignored) {
    } finally {
        System.out.println("finally");
    }
}

Durum 2: Önce JVM çökerse

import sun.misc.Unsafe;
import java.lang.reflect.Field;

public static void main(String args[]) {
    try {
        unsafeMethod();
        //Runtime.getRuntime().halt(123);
        System.out.println("After Jvm Crash!");
    } catch (Exception e) {
    } finally {
        System.out.println("finally");
    }
}

private static void unsafeMethod() throws NoSuchFieldException, IllegalAccessException {
    Field f = Unsafe.class.getDeclaredField("theUnsafe");
    f.setAccessible(true);
    Unsafe unsafe = (Unsafe) f.get(null);
    unsafe.putAddress(0, 0);
}

Ref: Nasıl JVM çöküyorsun?

Durum 6: finallyBlok daemon tarafından yürütülecekse Threadve daha Threadsönce tüm diğer daemon olmayan çıkışlar finallyçağrılır.

public static void main(String args[]) {
    Runnable runnable = new Runnable() {
        @Override
        public void run() {
            try {
                printThreads("Daemon Thread printing");
                // just to ensure this thread will live longer than main thread
                Thread.sleep(10000);
            } catch (Exception e) {
            } finally {
                System.out.println("finally");
            }
        }
    };
    Thread daemonThread = new Thread(runnable);
    daemonThread.setDaemon(Boolean.TRUE);
    daemonThread.setName("My Daemon Thread");
    daemonThread.start();
    printThreads("main Thread Printing");
}

private static synchronized void printThreads(String str) {
    System.out.println(str);
    int threadCount = 0;
    Set<Thread> threadSet = Thread.getAllStackTraces().keySet();
    for (Thread t : threadSet) {
        if (t.getThreadGroup() == Thread.currentThread().getThreadGroup()) {
            System.out.println("Thread :" + t + ":" + "state:" + t.getState());
            ++threadCount;
        }
    }
    System.out.println("Thread count started by Main thread:" + threadCount);
    System.out.println("-------------------------------------------------");
}

çıktı: Bu "son olarak" yazdırmaz, bu da "daemon thread" de "Nihayet engelle" anlamına gelmediğini

main Thread Printing  
Thread :Thread[My Daemon Thread,5,main]:state:BLOCKED  
Thread :Thread[main,5,main]:state:RUNNABLE  
Thread :Thread[Monitor Ctrl-Break,5,main]:state:RUNNABLE   
Thread count started by Main thread:3  
-------------------------------------------------  
Daemon Thread printing  
Thread :Thread[My Daemon Thread,5,main]:state:RUNNABLE  
Thread :Thread[Monitor Ctrl-Break,5,main]:state:RUNNABLE  
Thread count started by Main thread:2  
-------------------------------------------------  

Process finished with exit code 0

4
Kabul edilen cevaba bakınız. Bu sadece "sonsuz döngü" nin uç bir örneğidir.
Stephen C

8

Aşağıdaki programı düşünün:

public class SomeTest {

    private static StringBuilder sb = new StringBuilder();

    public static void main(String args[]) {

        System.out.println(someString());
        System.out.println("---AGAIN---");
        System.out.println(someString());
        System.out.println("---PRINT THE RESULT---");
        System.out.println(sb.toString());
    }

    private static String someString() {

        try {
            sb.append("-abc-");
            return sb.toString();

        } finally {
            sb.append("xyz");
        }
    }
}

Java 1.8.162'den itibaren, yukarıdaki kod bloğu aşağıdaki çıktıyı verir:

-abc-
---AGAIN---
-abc-xyz-abc-
---PRINT THE RESULT---
-abc-xyz-abc-xyz

Bu, finallynesneleri serbest bırakmak için kullanmanın aşağıdaki kod gibi iyi bir uygulama olduğu anlamına gelir :

private static String someString() {

    StringBuilder sb = new StringBuilder();

    try {
        sb.append("abc");
        return sb.toString();

    } finally {
        sb = null; // Just an example, but you can close streams or DB connections this way.
    }
}

sb.setLength(0)Sonunda olmamalı mıydı ?
user7294900

sb.setLength (0), StringBuffer'daki verileri boşaltır. Bu nedenle, sb = null nesneyi başvurudan ayırır.
Sam

Çıktıya iki kez "xyz" basılmamalı mı? Fonksiyon iki kez çağrıldığından, neden "nihayet" sadece bir kez oldu?
fresko

2
Bu iyi bir uygulama değil. Sonunda blok ile sb = null;sadece gereksiz kod ekler. Bir finallybloğun, veritabanı bağlantısı veya benzeri bir kaynak gibi kaynakları serbest bırakmak için iyi bir yer olduğunu anladığınızı anlıyorum , ancak örneğinizin yeni gelenleri karıştırabileceğini unutmayın.
Roc Boronat

1
@Samim Teşekkürler, satırları ekledim System.out.println("---AGAIN2---"); System.out.println(sb);ve şimdi daha net. Olduğu gibi, çıktı tezinize karşıydı: p Cevabınıza da ekledim, ancak düzenleme bir moderatör veya bunun gibi biri tarafından kabul edilmelidir. Başka ekleyebilirsiniz
fresko

7

Bu aslında herhangi bir dilde doğrudur ... nihayet her zaman bir dönüş ifadesinden önce, bu dönüşün yöntem gövdesinde nerede olursa olsun yürütülecektir. Eğer durum böyle olmasaydı, nihayet bloğun pek bir anlamı olmazdı.


7

Sonunda try bloğundaki bir dönüşün yerine getirilmesiyle ilgili noktasına ek olarak, aynı durum bir istisna için de geçerlidir. Son olarak istisna atan bir blok, try bloğunun içinden atılan bir dönüşün veya istisnanın yerini alacaktır.


7

finally yürütecek ve bu kesin.

finally aşağıdaki durumlarda yürütülmez:

dava 1 :

Sen yürütürken System.exit() .

durum 2:

JVM / Thread'iniz çöktüğünde.

durum 3:

İcra işleminiz manuel olarak durdurulduğunda.


6
  1. Sonunda Block her zaman idam edilir. System.exit () ifadesi bulunmadığı sürece ( son bloktaki ilk ifade).
  2. Eğer System.exit () sonra nihayet blok nihayet bloğun çıkıp idam ve kontrol almazsınız ilk ifadedir. System.exit () deyimi sonunda bu deyim sonunda blok çalıştırılana kadar bloke olur ve System.exit () göründüğünde, kontrol kuvveti son bloktan tamamen çıkar.

1
Bu birçok kez cevaplanmıştır, bu yüzden cevabınız hangi yeni bilgileri ekler?
Tom
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.