ฉันจะส่งชุดข้อยกเว้นเป็นต้นเหตุได้อย่างไร


52

วิธีการบางอย่างmyMethodจะเรียกใช้การประหารชีวิตหลายขนานและรอการยุติของพวกเขา

การดำเนินการแบบขนานเหล่านี้สามารถเสร็จสิ้นโดยมีข้อยกเว้น เพื่อmyMethodรับรายการข้อยกเว้น

ฉันต้องการส่งรายการข้อยกเว้นเป็นสาเหตุหลัก แต่สาเหตุหลักอาจเป็นเพียงข้อยกเว้นเดียว แน่ใจว่าฉันสามารถสร้างข้อยกเว้นของตัวเองเพื่อให้บรรลุสิ่งที่ฉันต้องการ แต่ฉันต้องการที่จะรู้ว่า Java, Spring หรือ Spring Batch มีบางสิ่งเช่นนี้หรือไม่


3
.NET AggregateExceptionมีรายการข้อยกเว้นอยู่ แนวคิดนั้นควรนำไปใช้กับ Java ได้เช่นกัน
usr

คำตอบ:


49

ผมไม่แน่ใจว่าผมจะทำมัน (แม้ว่าจะได้รับ JavaDoc ฉันไม่สามารถบอกคุณได้ว่าทำไมฉันลังเล) แต่มีรายการยกเว้นปราบปรามบนซึ่งคุณสามารถเพิ่มผ่านทางThrowable addSuppressedJavaDoc ดูเหมือนจะไม่พูดว่านี่เป็นเพียงการ JVM ที่จะใช้ในลองกับทรัพยากร:

ผนวกข้อยกเว้นที่ระบุเข้ากับข้อยกเว้นที่ถูกระงับเพื่อส่งข้อยกเว้นนี้ วิธีการนี้ปลอดภัยต่อเธรดและโดยทั่วไปจะเรียก (โดยอัตโนมัติและโดยปริยาย) โดยข้อความสั่ง try-with-resources

พฤติกรรมการปราบปรามถูกเปิดใช้งานเว้นแต่ปิดการใช้งานผ่านตัวสร้าง เมื่อปิดใช้งานการปราบปรามวิธีนี้จะไม่ทำสิ่งใดนอกจากการตรวจสอบอาร์กิวเมนต์

โปรดทราบว่าเมื่อข้อยกเว้นหนึ่งทำให้เกิดข้อยกเว้นอื่นข้อยกเว้นแรกมักจะถูกดักจับแล้วข้อยกเว้นที่สองจะถูกส่งออกมาเพื่อตอบสนอง กล่าวอีกนัยหนึ่งมีการเชื่อมต่อเชิงสาเหตุระหว่างข้อยกเว้นสองข้อ ในทางตรงกันข้ามมีสถานการณ์ที่สองข้อยกเว้นอิสระสามารถโยนในบล็อกรหัสพี่น้องโดยเฉพาะอย่างยิ่งในลองบล็อกของคำสั่งลองกับทรัพยากรและสุดท้ายสร้างบล็อกคอมไพเลอร์ซึ่งปิดทรัพยากร ในสถานการณ์เหล่านี้มีข้อยกเว้นอย่างใดอย่างหนึ่งเท่านั้นที่สามารถแพร่กระจายได้ ในคำสั่ง try-with-resources เมื่อมีข้อยกเว้นสองประการข้อยกเว้นที่มาจากบล็อกการลองถูกเผยแพร่และมีการเพิ่มข้อยกเว้นจากบล็อกสุดท้ายลงในรายการข้อยกเว้นที่ระงับโดยข้อยกเว้นจากบล็อกการลอง เป็นข้อยกเว้นคลายกองซ้อน

ข้อยกเว้นอาจระงับข้อยกเว้นในขณะที่เกิดจากข้อยกเว้นอื่น ข้อยกเว้นมีสาเหตุที่ทำให้เกิดความหมายหรือไม่ในขณะที่มีการสร้างความแตกต่างหรือไม่ว่าข้อยกเว้นจะระงับข้อยกเว้นอื่น ๆ ซึ่งโดยทั่วไปจะพิจารณาเฉพาะหลังจากข้อยกเว้นจะถูกโยน

โปรดทราบว่าโค้ดที่เขียนโดยโปรแกรมเมอร์สามารถใช้ประโยชน์จากการเรียกใช้เมธอดนี้ในสถานการณ์ที่มีข้อยกเว้นพี่น้องหลายรายการและสามารถแพร่กระจายได้เพียงอันเดียวเท่านั้น

โปรดสังเกตว่าย่อหน้าสุดท้ายซึ่งดูเหมือนจะเหมาะกับกรณีของคุณ


[... ] ไม่ว่าจะมีข้อยกเว้นหรือไม่ก็ตามจะระงับข้อยกเว้นอื่น ๆ [... ] โดยทั่วไปจะพิจารณาเฉพาะหลังจากมีการโยนข้อยกเว้น ฉันคิดว่าสิ่งนี้จะไม่เกิดขึ้นเมื่อมีการรวบรวมข้อยกเว้นหลายรายการจากการรันแบบขนาน
GOTO 0

24

ข้อยกเว้นและสาเหตุของพวกเขาอยู่เสมอเพียง 1: สิ่งที่ 1: คุณสามารถโยนหนึ่งข้อยกเว้นและแต่ละข้อยกเว้นสามารถมีได้เพียงหนึ่งสาเหตุ (ซึ่งสามารถมีสาเหตุได้อีก ...

ซึ่งอาจถือได้ว่าเป็นความผิดพลาดในการออกแบบโดยเฉพาะเมื่อพิจารณาถึงพฤติกรรมแบบมัลติเธรดตามที่คุณอธิบายไว้

นั่นเป็นหนึ่งในเหตุผลที่เพิ่ม Java 7 addSuppressedใน Throwable ซึ่งโดยทั่วไปสามารถแนบข้อยกเว้นจำนวนหนึ่งเข้ากับอีกอันหนึ่ง (แรงจูงใจหลักอื่น ๆ คือลองกับทรัพยากรที่ต้องการวิธีจัดการข้อยกเว้นในบล็อกในที่สุด พวกเขา)

ดังนั้นโดยทั่วไปเมื่อคุณมีข้อยกเว้น 1 ข้อที่ทำให้กระบวนการของคุณล้มเหลวคุณเพิ่มหนึ่งข้อนั้นเป็นสาเหตุของข้อยกเว้นระดับที่สูงกว่าของคุณและถ้าคุณมีมากกว่านั้นคุณจะเพิ่มสิ่งเหล่านั้นลงในต้นฉบับโดยใช้ addSuppressedข้อยกเว้นที่ทำให้เกิดกระบวนการของคุณล้มเหลวคุณเพิ่มที่หนึ่งเป็นสาเหตุของการยกเว้นระดับสูงของคุณและถ้าหากคุณมีมากขึ้นแล้วคุณเพิ่มเหล่านั้นไปยังคนเดิมใช้ แนวคิดก็คือข้อยกเว้นแรกคือ "แทนที่" คนอื่น ๆ กลายเป็นสมาชิกของ "ห่วงโซ่การยกเว้นจริง"

รหัสตัวอย่าง:

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
ฉันจะไม่ทำตามวิธีที่คุณแนะนำยกเว้นกรณีที่ข้อยกเว้นที่สำคัญข้อใดข้อหนึ่งสามารถถูกแยกออกเป็น "หลัก" อย่างใดอย่างหนึ่ง หากคุณเลือกข้อยกเว้นข้อใดข้อหนึ่งเป็นข้อหลักอย่างใดอย่างหนึ่งโดยไม่ได้ตั้งใจคุณจะเชิญผู้โทรให้ละเว้นข้อยกเว้นที่ระงับไว้และรายงานข้อผิดพลาดหลัก - แม้ว่าข้อยกเว้น "หลัก" คือ TypoInUserInputException และอีกข้อ สิ่งที่ถูกระงับคือ DatabaseCorruptedException
Ilmari Karonen

1
…แทนฉันจะทำเครื่องหมายข้อยกเว้นพื้นฐานทั้งหมดที่ถูกระงับโดย SomethingWentWrongException และให้ข้อความที่ระบุอย่างชัดเจนว่ามีข้อยกเว้นที่ถูกระงับอย่างน้อยหนึ่งอย่างควรทำตามเช่นสิ่งX " จากงานYล้มเหลวดูรายการความล้มเหลวด้านล่าง "
Ilmari Karonen
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.