Neden nihayet blokları kullanıyoruz?


91

Anladığım kadarıyla, aşağıdaki kod parçalarının ikisi de aynı amaca hizmet edecek. Neden finallyhiç blok var ?

Kod A:

try { /* Some code */ }
catch { /* Exception handling code */ }
finally { /* Cleanup code */ }

B kodu:

try { /* Some code */ }
catch { /* Exception handling code */ }
// Cleanup code

Bu C # 'a özgü değildir, bu bir .Net sorusudur
Sruly

1
Java7 ile artık gerek yok: AutomaticResourceManagement, try (new resourceDeclartion ()) {}
Kanagavelu Sugumar

Yanıtlar:


139
  • Başa çıkmadığınız bir istisna atılırsa ne olur? (Umarım yakalamıyorsundur Throwable...)
  • Try bloğunun içinden dönerseniz ne olur?
  • Catch bloğu bir istisna atarsa ​​ne olur?

Bir finallyblok emin kılan ancak bu bloğu (açıkça tüm süreci iptal edilme birkaç yolu modulo), çalıştırılacaktır alacak çıkın. Kaynakların deterministik temizliği için bu önemlidir.


48
Mutlaka doğru değil; (1) bir System.exit()çağrı varsa (2) denemede veya yakalama bloğundan birinde sonsuz bir döngü varsa (3) bilgisayardaki fişi
çekersem

2
@Alon deneyin {dönüş 1; } sonunda {retrun 2; } 2
Dennis C

19
@NullUserException: "modulo birkaç yol ..." biti
Jon Skeet

2
John Skeet burada stackoverflow'da yaşıyor, her soru cevaplaması gereken bir kapı zili gibi :)
naikus

1
Bu gönderi , sonunda çağrılamayacak (nadir) koşulları tartışıyor.
Candamir

13

Unutmayın ki (en azından Java'da, muhtemelen C #'da da) a tryolmadan catch, ancak a ile bir bloğa sahip olmanın da mümkün olduğunu unutmayın finally. tryBlokta bir istisna meydana geldiğinde, bloktaki kod finallyistisna daha yükseğe fırlatılmadan önce çalıştırılır:

InputStream in = new FileInputStream("somefile.xyz");
try {
    somethingThatMightThrowAnException();
}
finally {
    // cleanup here
    in.close();
}

7

Deneme veya yakalama bloğunuzda ne olduğuna bakılmaksızın çalıştırılmasını istediğiniz kodu koymak isteyebilirsiniz.

Ayrıca, birden fazla catch kullanıyorsanız ve tüm catch blokları için ortak olan bazı kodları koymak istiyorsanız, burası yerleştirilecek bir yer olacaktır - ancak try'deki kodun tamamının çalıştırıldığından emin olamazsınız.

Örneğin:

conn c1 = new connection();
try {
    c1.dosomething();
} catch (ExceptionA exa) {
    handleexA();
    //c1.close();
} catch (ExceptionB exb) {
    handleexB();
    //c1.close();
} finally {
    c1.close();
}

1
Ya 'nihayet' kullanmazsam ancak bağlantıyı kapatırsam?
Istiaque Ahmed

5

Sonunda her zaman çalıştırılır, yakalama işleminden sonraki kodunuz olmayabilir.


1
neden olmasın! İstisna düzgün bir şekilde ele alınırsa, kod kesinlikle çalıştırılır.
Mohammad Nadeem

1
@Nadeem: 3 nedenden dolayı cevabıma bakın, olmayabilir.
Jon Skeet

2

Uygulamamız zorla kapatılmış olsa bile, yürütmemiz gereken bazı görevler olacaktır (bellek serbest bırakma, veri tabanını kapatma, serbest bırakma kilidi, vb.), Bu kod satırlarını finallybloğa yazarsanız, bir istisna atılıp atılmayacağını veya değil...

Uygulamanız bir Exceptioniş parçacığı koleksiyonu olabilir , iş parçacığını sonlandırır, ancak tüm uygulamayı değil, bu durumda finallydaha kullanışlıdır.

finallyJVM Başarısız, İş Parçacığı sonlandırma vb. Gibi bazı durumlarda yürütülmez


1

Çünkü, atılabilecek istisnalara bakılmaksızın bu kodu çalıştırmak için ihtiyacınız var. Örneğin, bazı yönetilmeyen kaynakları temizlemeniz gerekebilir ('using' yapı, bir dene / nihayet bloğuna derlenir).


0

Ne olursa olsun bir kod parçasını çalıştırmak istediğiniz zamanlar olabilir. Bir istisna atılıp atılmadığı. Sonra biri kullanır finally.


0

finallyJVM kapatılmadıkça, HER ZAMAN yürütülür, finallyyalnızca temizleme kodunu tek bir yere koymak için bir yöntem sağlar.

catchBlokların her birine temizleme kodunu koymanız çok yorucu olurdu .


0

Eğer catch bloğu herhangi bir istisna atarsa, kalan kod çalıştırılmaz, bu nedenle son bloğu yazmamız gerekir.


0

son olarak java'da blok, bir dosyayı kapatmak, bağlantıyı kapatmak gibi "temizleme" kodunu koymak için kullanılabilir.


Program çıkarsa (System.exit () çağırarak veya işlemin durmasına neden olan ölümcül bir hataya neden olarak) sonuncu blok çalıştırılmayacaktır.


0

Hala aşağı mı kaydırıyorsunuz? Hadi bakalım!

Bu soru bana bir süre önce zor zamanlar verdi.

try
{
 int a=1;
 int b=0;
 int c=a/b;
}
catch(Exception ex)
{
 console.writeline(ex.Message);
}
finally
{
 console.writeline("Finally block");
}
console.writeline("After finally");

yukarıdaki senaryoda ne basılacaktır? Evet doğru tahmin ettim:

  • ör. mesaj - her neyse (muhtemelen sıfıra bölme girişiminde bulunuldu)

  • Sonunda engelle

  • Sonunda sonra

    try
    {
        int a=1;
        int b=0;
        int c=a/b;
    }
    catch(Exception ex)
    {
        throw(ex);
    }
    finally
    {
        console.writeline("Finally block");
    }
    console.writeline("After finally");
    

Bu neyi yazdırır? Hiçbir şey değil! Catch bloğu bir hata ortaya çıkardığı için bir hata atar.

İyi bir programlama yapısında, bu kodun başka bir katmandan ele alınması anlamında istisnalarınız aktarılır. Böyle bir durumu uyarmak için iç içe geçeceğim bu kodu deneyeceğim.

try
{    
 try
    {
     int a=1;
     int b=0;
     int c=a/b;
    }
    catch(Exception ex)
    {
     throw(ex);
    }
    finally
    {
     console.writeline("Finally block")
    }
    console.writeline("After finally");
}
catch(Exception ex)
{
 console.writeline(ex.Message);
}

Bu durumda çıktı şöyle olacaktır:

  • Sonunda engelle
  • ör. mesaj - her neyse.

Bir istisna yakalayıp diğer katmanlara tekrar attığınızda (Huni oluşturma), fırlatma sonrası kodun çalıştırılmayacağı açıktır. Bir işlevin içindeki dönüşün nasıl çalıştığına benzer şekilde davranır.

Artık catch bloğundan sonra kaynaklarınızı neden kapatmayacağınızı biliyorsunuz. Nihayet bloğuna yerleştirin.

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.