2015-05-27 21 views
5

FooException ile çalışıyorum ve BarException oluşuyor varsayalım. Her ikisi de denetlenmeyen istisnalar olduklarını varsayalım.Diğer istisnaları kullanırken atılan istisnalar için doğru şekilde zincirlenmiş yığın izi nasıl edinilir?

Ne stacktrace görmek istiyorum geçerli:

com.bar.BarException: Bar Message 
    at com.baz.BazCode(BazCode.java:123) 
    ... 
Caused by: com.foo.FooException: Foo Message 
    at com.baz.BazCode(BazCode.java:321) 
    .... 
Caused by: ... 

Ancak varsayılan olarak, FooException tüm kayıt stacktrace silinecek. Örneğin:

try { 
    foo.doSomething(); 
} catch (FooException foo) { 
    try { 
     bar.doSomethingElse(); 
    } catch (BarException bar) { 
     BarException bar2 = new BarException(bar.getMessage(), foo); 
     bar2.setStackTrace(bar.getStackTrace()); 
     throw bar2; 
    } 
} 

Ancak BarException eğer böyle yok: BarException bir (message, cause) yapıcı varsa

// In a class written by me 
/** 
    * ... 
    * @throws FooException if foo happens 
    * @throws BarException if bar happens 
    */ 
public void upperFrame() { 
    try { 
     foo.doSomething(); 
    } catch (FooException foo) { 
     bar.doSomethingElse(); 
    } 
} 

// In class Bar (not written by me) 
public void doSomethingElse() { 
    if (someConditionWhichHappensToBeTrueInThisScenario()) { 
     throw new BarException("Hello Bar World"); // At this point, FooException gets erased from the stack trace 
    } 
} 

sonra ben hedefe ulaşmak için "manuel klonlama" işleminin oldukça ham türlü takip edebilir bir kurucu (ClassCastException örneğin) o zaman böyle yapıyor şeyler indirgendiğim:

try { 
    foo.doSomething(); 
} catch (FooException foo) { 
    try { 
     bar.doSomethingElse(); 
    } catch (BarException bar) { 
     RuntimeException e = new RuntimeException("com.bar.BarException: " + bar.getMessage(), foo); 
     e.setStackTrace(bar.getStackTrace()); 
     throw e; 
    } 
} 

Bu tehlikeli olduğunu Neden e yanlış tipte ve bu nedenle daha yüksek çerçeveler tarafından doğru şekilde işlenemeyebilir.

Bu durumun üstesinden gelmek için "en iyi uygulama" yolu var mı?

bar.initCause(foo); 
Sürece bağımsız değişken olarak yeni bir özgün durum geçerken
+0

FooException'ın stacktrace bir Foo nedeniyle bir 'BarException 'oluştururken kayboldu mu? Ya da bar.getCause(). GetStackTrace() 'gibi bir şey yapabilir miydiniz? –

+0

@KaspervandenBerg “FooException” un nasıl kaybolduğunu göstermek için sorumu düzenledim. Nedeni olan bir istisnanın yaratılmasıyla ilgili değildir, 'doSomethingElse' yöntemi tarafından atılan bir istisnadır. – Kidburla

cevap

4

bir çözüm Throwable#initCause(Throwable) yöntemini kullanmaktır . Kullanım durumlarınız biraz tuhaf görünüyor. Bana göre, bir hatadan daha fazla hata ile kurtarma veya işleme, bir başka hata ve diğer hata "gerçekten" tarafından değil, başka bir hatadır. Sadece "foo" 'yu ​​yazıp "bar" ı atacağım.

Bazı durumlarda yolunuzun anlamlı olabileceğini tahmin ediyorum. Bunu yapmak için, "foo" yu doSomethingElse (foo) olarak geçirebilir ve bir şeyleri yanlış ele aldığınızda yeni BarException (foo) atabilirsiniz. Hemen hemen tüm standart istisnalar bu kurucuyu destekler ve kendi kendinize sahip olmanız gerekiyorsa, bunlara delege veren bir kurucu oluşturun.

Ben şahsen onları nasıl göründüğün gibi kullanmayacağım. Bir nedenden dolayı farklı bir tip istiyorsanız, yakaladığımdan farklı bir istisna türü atmak için onları kullanırım. Örneğin, uygulamam için belirli bir türdeki istisnalara çeviri yapmak veya bu durumun mantıklı olduğu durumlarda işaretlenmemiş olarak işaretlenmiş olarak çevirmek. Bu gibi durumlarda orijinal istisnayı ve tam olarak "neden oldu .." izini tutmak iyi olur.

+0

İyi bir nokta (Bu yöntemi yalnızca 'setCause' yöntemini aradığımdan farketmedim) .... 'BarException' zaten bir neden tanımlamıyorsa. Bununla birlikte, henüz bir sebep belirten bir istisna sınıfı (en azından java belirtiminde) bulmama rağmen henüz bir “mesaj, sebep” yapıcısı yok. – Kidburla

1

, bu zincir "neden" ve yığın izlemesi korunur oluşturur:

+0

"Sadece foo'yu günlüğe kaydeder ve çubuğu atarım": Günlükleri istisnalar ve daha sonra atmak iyi bir uygulama değildir. Başka bir kitaplık kodunuza bağlıysa ve standart olmayan bir günlükçüyü kullanıyorsa (JMS günlüğü gibi) ne olacak?"Hemen hemen tüm standart istisnalar bu kurucuyu destekliyor" değil, "ClassCastException" sadece bir örnektir. – Kidburla

+0

"Ben şahsen onları göründüğünüz şekilde kullanmayacağım. Bunlara farklı bir istisna türü atamak için kullanıyorum. Ben yakaladım - bu benim yapmaya çalıştığım şey olmadığı izlenimini veriyor? "ClassCastException" gibi istisnalar, – Kidburla

+0

yakaladığım kişiye farklı türde bir özel durum atmaya çalışırken ortaya çıkabilir. "Bunu yapmak için, foo'yu doSomethingElse (foo) olarak iletebilirsiniz" - Sorumu belirttiğim gibi, doSomethingElse Benim tarafımdan yazılmış bir sınıfta değil. Ve bir argümanın bir argüman olarak geçmesini desteklemez. – Kidburla

İlgili konular