Bir istisna koleksiyonunu temel neden olarak nasıl iletebilirim?


52

Bazı yöntemler, myMethodbirkaç paralel yürütmeyi başlatır ve bunların sonlandırılmasını bekler.

Bu paralel yürütmeler istisnalarla tamamlanabilir. Yani myMethodbir istisna listesi alır.

İstisna listesini bir kök nedeni olarak geçmek istiyorum, ancak kök nedeni sadece tek bir istisna olabilir. Elbette istediğimi elde etmek için kendi istisnamı oluşturabilirim, ancak Java, Spring veya Spring Batch'in kutuda böyle bir şey olup olmadığını bilmek istiyorum.


3
.NET, bir AggregateExceptionistisnalar listesi içerir. Bu fikir Java için de geçerli olmalıdır.
usr

Yanıtlar:


49

Yapacağımdan emin değilim (JavaDoc verildiğinde neden tereddüt ettiğimi söyleyemedim), ancak üzerinden Throwableekleyebileceğiniz bastırılmış istisnaların listesi var addSuppressed. JavaDoc, bunun yalnızca JVM'nin kaynaklarla denemede kullanacağı anlamına gelmiyor:

Belirtilen istisnayı, bu istisnayı sağlamak için bastırılmış istisnalara ekler. Bu yöntem iş parçacığı için güvenlidir ve genellikle try-with-resources deyimi tarafından (otomatik ve örtük olarak) çağrılır.

Bastırma davranışı bir kurucu aracılığıyla devre dışı bırakılmadığı sürece etkinleştirilir. Bastırma devre dışı bırakıldığında, bu yöntem argümanını doğrulamaktan başka bir şey yapmaz.

Bir istisna başka bir istisnaya neden olduğunda, ilk istisnanın genellikle yakalandığını ve ardından ikinci istisnanın yanıt olarak atıldığını unutmayın. Başka bir deyişle, iki istisna arasında nedensel bir bağlantı vardır. Buna karşılık, kardeş kod bloklarında, özellikle kaynaklarla deneme ifadesinin try bloğunda ve derleyici tarafından oluşturulan ve kaynağı kapatan nihayet bloğunda iki bağımsız istisnanın atılabileceği durumlar vardır. Bu durumlarda, atılan istisnalardan sadece biri yayılabilir. Kaynaklarla deneme ifadesinde, bu tür iki istisna olduğunda, try bloğundan kaynaklanan istisna yayılır ve nihayet bloğundan istisna try bloğundan istisna tarafından bastırılan istisnalar listesine eklenir. İstisna yığını gevşetirken,

Bir istisna, başka bir istisnanın neden olduğu istisnaları bastırmış olabilir. Bir istisnanın bir nedeni olup olmadığı, bir istisnanın tipik olarak yalnızca bir istisna atıldıktan sonra belirlenen diğer istisnaları bastırıp bastırmayacağından farklı olarak, yaratılış sırasında anlamsal olarak bilinir.

Programcı yazılı kodunun, birden fazla kardeş istisnası olan ve yalnızca bir tanesinin yayılabileceği durumlarda bu yöntemi çağırmanın avantajlarından da yararlanabileceğini unutmayın.

Durumunuza uygun görünen son paragrafa dikkat edin.


[...] bir istisnanın diğer istisnaları bastırıp bastırmayacağı [...] tipik olarak sadece bir istisna atıldıktan sonra belirlenir. Paralel çalışmalardan çoklu bastırılmış istisnalar toplandığında durum böyle olmayacağını düşünüyorum.
GOTO 0

24

İstisnalar ve nedenleri her zaman sadece 1: 1 bir şeydir: bir istisna atayabilirsiniz ve her istisnanın sadece bir nedeni olabilir (yine bir nedeni olabilir ...).

Bu, özellikle tanımladığınız gibi çok iş parçacıklı davranış göz önüne alındığında, bir tasarım hatası olarak düşünülebilir.

Java 7'nin addSuppressedtek bir diğerine keyfi olarak istisnalar ekleyebilen atılabilirliğe eklenmesinin nedenlerinden biri de (diğer birincil motivasyon, sessizce düşmeden son blokta istisnaları ele almanın bir yoluna ihtiyaç duyan kaynaklarla denemeydi. onları).

Temel olarak, işleminizin başarısız olmasına neden olan 1 istisnanız varsa, bunu üst düzey istisnanızın nedeni olarak eklersiniz ve daha fazlasına sahipseniz, bunları kullanarak orijinaline eklersiniz addSuppressed. Buradaki fikir, ilk istisnanın diğerlerini "gerçek istisna zincirine" üye olmaları için "baskıladığı" dır.

Basit kod:

Exception exception = null;
for (Foobar foobar : foobars) {
  try {
    foobar.frobnicate();
  } catch (Exception ex) {
    if (exception == null) {
      exception = ex;
    } else {
      exception.addSuppressed(ex);
    }
  }
}
if (exception != null) {
  throw new SomethingWentWrongException(exception);
}

4
Altta yatan istisnalardan biri gerçekten "ana" olarak seçilemezse, bunu önerdiğiniz gibi yapmazdım. İstisnalardan birini ana olarak diğerini bastırılmış olarak rasgele seçerseniz, arayanı bastırılmış istisnaları yok saymaya ve sadece ana olanı bildirmeye davet edersiniz - "ana" istisna bir TypoInUserInputException ve bastırılanlar bir DatabaseCorruptedException'dır.
Ilmari Karonen

1
... Bunun yerine, işaretlemek istiyorum tüm SomethingWentWrongException tarafından bastırılmış olarak altta yatan istisnalar ve bu istisna açıkça bir veya daha fazla bastırılmış istisnalar olduğunu belirten bir mesaj iletir gerektiğini "gibi izleyin örn şey X dışına Y aşağıda başarısızlık listesini görmek, görev başarısız ".
Ilmari Karonen
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.