Soru Sonunda her zaman Java'da çalışır mı?


Bu kodu dikkate alarak, olabilir miyim kesinlikle emin o finally blok her zaman çalışır, ne olursa olsun something() nedir?

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

1907
2017-09-15 17:43


Menşei


Bunu kendiniz test ettikten sonra bile, sadece ne olduğunu biliyorsunuz sizin Java / JVM'nin uygulanması veya sürümü ne yapar ve kodun ne olacağını bilmez meli (standartlara göre) yapmak, ve böylece soru geçerli bir tanesidir. Bu yönleri çeşitli cevaplar arasında ele aldığına sevindim. - Rhubbarb
Değil her zaman - Boann
Etkili java aksi halde diyor informit.com/articles/article.aspx?p=1216151&seqNum=7 - Binoy Babu
@BinoyBabu, sonlandırıcı ! = finally; sonlandırıcı == finalize() yöntem. - jaco0646
@LordFarquaad ;-) Bu gerçekten her zaman garanti edilir. - MC Emperor


Cevaplar:


Evet, finally try veya catch kod bloklarının çalıştırılmasından sonra çağrılacaktır.

Sadece kez finally çağrılmayacaklar:

  1. Eğer çağırırsan System.exit();
  2. JVM ilk önce çöker;
  3. JVM, bir sonsuz döngüye (veya başka bir kesinti olmayan, sonlanmayan deyim) ulaşırsa try veya catch blok;
  4. OS, JVM işlemini zorla sonlandırırsa; Örneğin. UNIX üzerinde "-9" öldür.
  5. Ana bilgisayar sistemi ölürse; Örneğin. elektrik kesintisi, donanım hatası, OS panik, vb.
  6. Son olarak blok, daemon iş parçacığı ve diğer tüm daemon olmayan iş parçacıkları tarafından yürütülürse, son olarak çağrılmadan önce çıkılır.

2122
2017-09-15 17:45



Aslında thread.stop() mutlaka önleme finally yürütülmekte olan blok. - Piotr Findeisen
Bunu söyleyelim mi? finallyblok çağrılacak sonra  try blok ve önce Kontrol aşağıdaki ifadelere geçer. Bu sonsuz bir döngüyü içeren deneme bloğu ile tutarlı ve dolayısıyla son olarak aslında hiç çağrılmayan blok. - Andrzej Doyle
yuvalanmış kullandığımızda başka bir durum var deneyin-catch-son bloklar - ruhungry
Ayrıca, son olarak daemon iş parçacığı tarafından atılan istisna durumunda blok çağrılmaz. - Amrish Pandey
@BinoyBabu - Bu finalizer hakkında, sonunda bloke değil - avmohan


Ö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

446
2017-09-15 17:59



FYI: C # içinde davranış, deyimdeki ifadenin değiştirilmesinden farklıdır. finally-la birlikte return 2; izin verilmiyor (Derleyici-Hata). - Alexander Pacha
Burada dikkat edilmesi gereken önemli bir ayrıntı var: stackoverflow.com/a/20363941/2684342 - WoodenKitty
Son olarak, önceki dönüş değerini geçersiz kılacak olan son bloğun kendisine bir dönüş ifadesi bile ekleyebilirsiniz. Bu ayrıca işlenmeyen özel durumları sihirli bir şekilde atar. Bu noktada, kodunuzu tekrar gözden geçirmeyi düşünmelisiniz. - Zyl
Bu gerçekten sonunda kozların geri döndüğünü kanıtlamaz. Dönüş değeri, arayan kodundan yazdırılır. Çok fazla kanıtı yok gibi görünüyor. - Trimtab
Üzgünüm, ama bu bir kanıt değil kanıtıdır. Bu örneğin her zaman tüm Java platformlarında bu şekilde davrandığını ve benzer örneklerin her zaman böyle davrandığını gösterebilirseniz, sadece bir kanıttır. - Stephen C


Ayrıca, kötü bir uygulama olsa da, son blokta bir geri dönüş ifadesi varsa, normal bloktan başka bir getiri koyar. Yani, aşağıdaki blok yanlış döndürür:

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

Nihayet bloktan istisnalar atmakla aynı şey.


325
2017-09-15 18:19



Bu gerçekten kötü bir uygulamadır. Görmek stackoverflow.com/questions/48088/... Neden kötü olduğu hakkında daha fazla bilgi için. - John Meagher
Kabul. Sonunda {} bir dönüş, {} 'de atılan istisnaları göz ardı eder. Korkunç! - neu242
@ dominicbri7 Neden daha iyi bir uygulama olduğunu düşünüyorsun? İşlev / yöntem geçersiz olduğunda neden farklı olmalıdır? - corsiKa
Aynı sebepten dolayı GOT'ları C ++ kodlarımda ASLA kullanmıyorum. Birden fazla getiri okumayı zorlaştırıyor ve hata ayıklamayı daha zorlaştırıyor (tabi ki, gerçekten basit durumlarda geçerli değil). Sanırım bu sadece kişisel tercihtir ve sonunda her iki yöntemle de aynı şeyi elde edebilirsiniz. - dominicbri7
Bir çeşit istisnai durum söz konusu olduğunda, birtakım iadeler kullanıyorum. Gibi (devam etmemek için bir neden var) geri dönmek; - iHearGeoff


İşte Java Dil Özellikleri'nden resmi kelimeler.

14.20.2. Sonunda deneyin ve son olarak deneyin

bir try deyimiyle finally blok ilk yürütme tarafından yürütülür try blok. Sonra bir seçim var:

  • Eğer yürütülmesi try blok normal tamamlar, [...]
  • Eğer yürütülmesi try blok aniden tamamlanır throw bir değerin V, [...]
  • Eğer yürütülmesi try blok başka herhangi bir sebeple aniden tamamlar R,, sonra finally blok yürütülür. Sonra bir seçim var:
    • Son olarak blok normal tamamlanırsa, o zaman try deyim, sebeple aniden tamamlanır R,.
    • Eğer finally blok aniden aniden tamamlar S, sonra try deyim, sebeple aniden tamamlanır S (ve sebep R, atılır).

Şartname return aslında bu açık yapar:

JLS 14.17 İade Beyanı

ReturnStatement:
     return Expression(opt) ;

bir return hayırlı beyan Expression  denemeler kontrolü, onu içeren yöntemin veya yapıcının invokerine transfer etmek.

bir return bir ifadeyle Expression  denemeler kontrolü, onu içeren yöntemin içicisine transfer etmek; değerinin Expression yöntem çağırma değeri olur.

Önceki açıklamalar şöyle diyor:denemeler kontrolü transfer etmek"sadece değil"kontrolleri transfer eder"çünkü eğer varsa try yöntemi veya yapıcısı içindeki ifadeleri try blokları içerir return deyim, sonra herhangi finally bunların cümleleri try Kontrol, yöntemin veya kurucunun müdahalesine transfer edilmeden önce, en dışta en dışta ifadeler yapılacaktır. Bir anının tamamlanması finally Madde tarafından başlatılan kontrol aktarımını bozabilir return Beyan.


229
2018-05-25 06:50





Diğer cevaplara ek olarak, 'nihayet', try..catch bloğu tarafından herhangi bir istisna / iade değerini geçersiz kılma hakkına sahip olduğunu belirtmek ö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 atar:

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

Aşağıdaki yöntem atıyor iken:

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

134
2018-05-13 07:11



Ortadaki durumun tam olarak, son olarak bir bloğun içinde bir dönüş ifadesinin olmasının kesinlikle korkunç olmasının sebebi olduğu unutulmamalıdır (herhangi bir Trowable'ı gizleyebilir). - Dimitris Andreou


Yukarıdaki örneği biraz modifikasyonla 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üyorlar.
  2

Çünkü ne zaman return i; Idam edildi i bir değeri var 2. Bundan sonra finally bloğa 12 atanan blok yürütülür i ve sonra System.out dışarı yürütülür.

Çalıştırdıktan sonra finally engellemek try blok, geri dönen 12 yerine, 2 döndürür, çünkü bu dönüş ifadesi yeniden yürütülmez.

Eclipse'de bu kodu ayıklarsanız, o zaman yürütme sonrasında System.out arasında finally engellemek return beyanı try blok tekrar yürütülür. Ama durum böyle değil. Sadece 2 değerini döndürür.


88
2017-11-17 16:25



Bu örnek harika, düzinelerce son olarak ilgili konularda söz edilmemiş bir şey ekler. Bence herhangi bir geliştirici bunu bilecektir. - HopefullyHelpful
Farzedelim i bir ilkel değil, bir Tamsayı nesnesiydi. - Yamcha
Bu davayı anlamakta zorlanıyorum. docs.oracle.com/javase/specs/jls/se8/html/jls-14.html#jls-14.17 diyor ki, "Bir İfade ile bir geri dönüş ifadesi, yöntemi içeren yönteme veya lambda kütlesine kontrolü transfer etmeye çalışır. İfadenin değerlendirmesi normal olarak tamamlanırsa, bir V .. değeri üretilir." Bu deyim, dönüşün V değerini değerlendirdikten sonra ifadeyi tekrar değerlendirmediği anlamına gelir, bu yüzden değiştirilen değeri etkilemediğimi, düzeltmemi sağladım. - meexplorer
Ama ben buna dair herhangi bir kanıt bulamadım, geri dönüşün ifadeyi tekrar değerlendirmediği yerde. - meexplorer
@meexplorer biraz geç, ama açıklandığı gibi JLS 14.20.2. Sonunda deneyin ve son olarak deneyin - biraz karmaşık, 14.17. İade beyanı ayrıca okunmalı - Carlos Heuberger


İşte bir ayrıntı Kevin'ın cevabı. Döndürülecek ifadenin daha önce değerlendirildiğini bilmek önemlidir finallysonra iade olsa bile.

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

80
2017-12-03 23:36



Bilmek önemli. - Aminadav Glickshtein


Sonunda bir bloğun bütünü budur. Aksi halde atlanabildiğiniz temizleme işlemlerini yaptığınızdan emin olursunuz, çünkü diğer şeylerin yanı sıra geri dönersiniz.

Sonunda çağrılır ne olursa olsun try bloğunda (olmadıkça sen ara System.exit(int) ya da Java Virtual Machine başka bir sebepten yola çıkıyor.


46
2018-05-13 06:19





Bunun hakkında düşünmenin mantıklı bir yolu:

  1. Son olarak bloğa yerleştirilen kod çalıştırılmalıdır. ne olursa olsun try bloğu içinde
  2. Bu nedenle, try bloğundaki kod bir değer döndürmeye veya bir istisna atmaya çalışırsa, öğe sonuncu blok çalışana kadar 'rafta' yerleştirilir.
  3. Nihayet bloktaki kodun (tanım olarak) yüksek bir önceliğe sahip olması nedeniyle, istediği gibi geri dönebilir veya atabilir. Bu durumda 'rafta' bırakılan bir şey atılır.
  4. Bunun tek istisnası, VM'nin, örn. 'System.exit' tarafından

31
2017-09-15 19:26



Bu sadece "bunu düşünmenin mantıklı bir yolu" mu yoksa gerçekten de son bloğun şartnameye göre nasıl çalıştığı düşünülüyor mu? Bir Sun kaynağına bir bağlantı burada çok ilginç olurdu. - matias
4. nokta ile çelişiyor whatever happens 1'de ifade - ojonugwa ochalifu


Ayrıca sonunda bir dönüş herhangi bir istisna atmak olacaktır. http://jamesjava.blogspot.com/2006/03/dont-return-in-finally-clause.html


14
2017-09-15 19:26





Sonunda her zaman, anormal program sonlandırması olmadıkça (System.exit (0) .. gibi) çağırılmaz. bu yüzden senin özgeçmişin basılacak


13
2017-09-15 17:46