Yığın izini kaybetmeden özel durumları Java'da yeniden bağlama


417

C #, ben throw;yığın izini koruyarak bir özel durum yeniden yazmak için deyimi kullanabilirsiniz :

try
{
   ...
}
catch (Exception e)
{
   if (e is FooException)
     throw;
}

Java'da ( orijinal yığın izini kaybetmeyen) böyle bir şey var mı ?


4
Neden orijinal yığın izini kaybettiğini düşünüyorsun? Yeni SomeOtherException komutunu attığınızda ve yapıcıya veya initCause () öğesinde kök nedeni atamayı unutmanın tek yolu.
akarnokd

4
Bu kod .Net gibi davranıyor inanıyorum, ama artık olumlu değilim. Bir yere bakmak ya da küçük bir test yapmak faydalı olabilir.
ripper234

11
Throwableonları atarak değiştirilmez. Yığın izini güncellemek için aramalısınız fillInStackTrace(). Uygun olarak bu yöntem bir yapıcısında çağrılır Throwable.
Robert

50
C # 'da, evet, throw e;yığın izini kaybeder. Ama Java'da değil.
Tim Goodman

Yanıtlar:


560
catch (WhateverException e) {
    throw e;
}

yakaladığınız istisnayı yeniden düzenleyecektir (açıkçası çevredeki yöntem buna imzasıyla izin vermek zorundadır). İstisna orijinal yığın izini koruyacaktır.


4
Merhaba, ben e satırını eklediğimde, InterruptedException e işlenmeyen bir özel durum iletisi verir. Bunu daha geniş İstisna e ile değiştirirsem öyle değil. Bu nasıl düzgün yapılmalıdır?
James P.

1
@James, ben sadece fonksiyon bildiriminde "XxxException atar" eklerseniz mesajın gittiğini gözlemledim.
shiouming

2
Java 7'de böyle bir yeniden derleme için derleyici daha zekidir. Şimdi içeren yöntem belirli "atar" istisnalar ile iyi çalışıyor.
Waldemar Wosiński

193
@James Eğer bu catch(Exception e) { throw e; }ele alınamaz. Eğer sen catch(InterruptedException ie) { throw ie; }halledilir. Genel bir kural olarak, yapma catch(Exception e)- bu pokemon değil ve hepsini yakalamak istemiyoruz!
corsiKa

3
@corsiKa "Hepsini yakalamak" istemediğiniz doğru olmayabilir, bu sadece farklı bir kullanım durumudur. En azından RuntimeException özel durumunu yakalamaz ve günlüğe kaydetmezseniz, üst düzey bir döngü veya olay işleyiciniz varsa (örneğin, bir iş parçacığının çalışması içinde), genellikle özel durumu tamamen kaçırırsınız ve ne için önemli bir döngüden sessizce koparsınız genellikle bir defalık bir başarısızlıktır. Ek kodun ne yapabileceğini veya atabileceğini bilmediğiniz eklenti işlevselliği için de gerçekten iyi ... Bu yakalama gibi yukarıdan aşağı kullanımlar için İstisna genellikle sadece iyi bir fikir değil, en iyi uygulamadır.
Bill K

82

Tercih ederim:

try
{
    ...
}
catch (FooException fe){
   throw fe;
}
catch (Exception e)
{
    // Note: don't catch all exceptions like this unless you know what you
    // are doing.
    ...
}

6
Java genel olarak daha özel istisnalar yakalamak için uygun ve örneğin kontrol. +1
amischiefr

8
-1 çünkü ne yaptığınızı bilmiyorsanız hiçbir zaman düz "İstisna" yakalamamalısınız.
Stroboskop

19
@Stroboskop: doğru, ancak cevaplamak en iyisi sorudakiyle aynı (benzer) kodu kullanmaktır!
user85421

14
Bazen tüm istisnaları yakalamak sorun olmaz. Bir test senaryosu yazarken olduğu gibi. Veya kayıt amaçları için. Ya da ana yakalamada çarpışma demek.
John Henckel

1
@JohnHenckel ve diğerleri: Geçerli noktalar inded. Soruyu, yakalamanın Exceptiongenellikle (ancak hepsi değil) çoğu durumda yapılacak doğru şey olmadığını açıklığa kavuşturmak için güncelledim .
Per Lundberg

74

İstisnayı başka bir tanesine sarıp VE İstisna'yı neden parametresi olarak Atılabilir olarak ileterek orijinal yığın izini saklayabilirsiniz:

try
{
   ...
}
catch (Exception e)
{
     throw new YourOwnException(e);
}

8
Ben de kullanarak, birlikte bir mesaj ekleme tavsiye ediyorumthrow new YourOwnException("Error while trying to ....", e);
Julien

aradığım şey bu, özellikle kendi mesajınızı iletebileceğiniz ilk yorumdan sürüm
Csaba

Bu, hata iletisini doğru bir şekilde gösterir, ancak yığın izlemesi hata satırını, özel duruma neden olan orijinal satırı değil, 'yeni atma ....... (e)' satırıyla gösterir.
Ashburn RK

22

Java'da neredeyse aynı:

try
{
   ...
}
catch (Exception e)
{
   if (e instanceof FooException)
     throw e;
}

5
Hayır, yeni bir Exception nesnesini başlatmazsanız yığın yığını aynı kalır.
Mnementh

28
FooException için belirli bir catch eklerdim
dfa

3
Bu özel durumda katılıyorum, ancak belirli bir yakalama eklemek doğru seçim olmayabilir - tüm istisnalar için belirli bir kodunuz olduğunu ve belirli bir istisna için yeniden düşünün.
alves

1
@MarkusLausberg Ama sonunda istisnaları yakalamıyor.
Robert

Evet, ama soru bu değildi.
Markus Lausberg

14

Java, sen sadece bu yüzden, yakayı istisna throw edeğil sadece daha throw. Java yığın izlemesini korur.


6

böyle bir şey

try 
{
  ...
}
catch (FooException e) 
{
  throw e;
}
catch (Exception e)
{
  ...
}

5
public int read(byte[] a) throws IOException {
    try {
        return in.read(a);
    } catch (final Throwable t) {
        /* can do something here, like  in=null;  */
        throw t;
    }
}

Bu, yöntemin bir attığı somut bir örnektir IOException. finalAraçlar tsadece try bloğundan atılan bir istisna tutabilir. Ek okuma materyalleri burada ve burada bulunabilir .



3

Yakalanan eksiplini başka bir istisnaya (daha fazla bilgi sağlamak için) sarırsanız veya yakalanan ekseriya yeniden sararsanız yığın izlemesi korunur.

try{ ... }catch (FooException e){ throw new BarException("Some usefull info", e); }


2

Ben sadece benim kod potansiyel olarak sadece yeniden istedim bir dizi farklı istisnalar atıyor benzer bir durum vardı. Yukarıda açıklanan çözüm benim için işe yaramadı, çünkü Eclipse bana el throw e;değmemiş bir istisnaya yol açtığını söyledi , bu yüzden bunu yaptım:

try
{
...
} catch (NoSuchMethodException | SecurityException | IllegalAccessException e) {                    
    throw new RuntimeException(e.getClass().getName() + ": " + e.getMessage() + "\n" + e.getStackTrace().toString());
}

Benim için çalıştı .... :)

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.