ฉันขอขอบคุณฟีเจอร์ Java 8 ใหม่มากมายเกี่ยวกับ lambdas และอินเตอร์เฟสเมธอดดีฟอลต์ แต่ฉันยังคงเบื่อกับข้อยกเว้นที่ตรวจสอบ ตัวอย่างเช่นหากฉันต้องการแสดงรายการเขตข้อมูลที่มองเห็นได้ทั้งหมดของวัตถุที่ฉันต้องการจะเขียนสิ่งนี้:
Arrays.asList(p.getClass().getFields()).forEach(
f -> System.out.println(f.get(p))
);
แต่เนื่องจากget
วิธีการอาจมีข้อยกเว้นการตรวจสอบซึ่งไม่เห็นด้วยกับConsumer
สัญญาอินเตอร์เฟซดังนั้นฉันต้องจับข้อยกเว้นนั้นและเขียนรหัสต่อไปนี้:
Arrays.asList(p.getClass().getFields()).forEach(
f -> {
try {
System.out.println(f.get(p));
} catch (IllegalArgumentException | IllegalAccessException ex) {
throw new RuntimeException(ex);
}
}
);
อย่างไรก็ตามในกรณีส่วนใหญ่ฉันแค่ต้องการยกเว้นจะถูกโยนเป็นRuntimeException
และให้โปรแกรมจัดการหรือไม่ยกเว้นโดยไม่มีข้อผิดพลาดในการรวบรวม
ดังนั้นฉันต้องการแสดงความคิดเห็นของคุณเกี่ยวกับวิธีแก้ไขปัญหาการโต้เถียงของฉันสำหรับการตรวจสอบข้อยกเว้นที่น่ารำคาญ ด้วยเหตุนี้ฉันจึงสร้างส่วนต่อประสานConsumerCheckException<T>
และฟังก์ชั่นยูทิลิตี้rethrow
( อัปเดตตามความต้องการของความคิดเห็นของ Doval ) ดังต่อไปนี้:
@FunctionalInterface
public interface ConsumerCheckException<T>{
void accept(T elem) throws Exception;
}
public class Wrappers {
public static <T> Consumer<T> rethrow(ConsumerCheckException<T> c) {
return elem -> {
try {
c.accept(elem);
} catch (Exception ex) {
/**
* within sneakyThrow() we cast to the parameterized type T.
* In this case that type is RuntimeException.
* At runtime, however, the generic types have been erased, so
* that there is no T type anymore to cast to, so the cast
* disappears.
*/
Wrappers.<RuntimeException>sneakyThrow(ex);
}
};
}
/**
* Reinier Zwitserloot who, as far as I know, had the first mention of this
* technique in 2009 on the java posse mailing list.
* http://www.mail-archive.com/javaposse@googlegroups.com/msg05984.html
*/
public static <T extends Throwable> T sneakyThrow(Throwable t) {
throw (T) t;
}
}
และตอนนี้ฉันสามารถเขียน:
Arrays.asList(p.getClass().getFields()).forEach(
rethrow(f -> System.out.println(f.get(p)))
);
ฉันไม่แน่ใจว่านี่เป็นสำนวนที่ดีที่สุดในการตรวจสอบข้อยกเว้น แต่ตามที่อธิบายฉันต้องการวิธีที่สะดวกกว่าในการบรรลุตัวอย่างแรกโดยไม่ต้องจัดการกับข้อยกเว้นที่ตรวจสอบและนี่เป็นวิธีที่ง่ายกว่าที่ฉันพบ ที่จะทำมัน
sneakyThrow
ด้านในของที่จะโยนเดิมยกเว้นการตรวจสอบแทนการห่อไว้ในrethrow
RuntimeException
หรือคุณสามารถใช้@SneakyThrows
คำอธิบายประกอบจากProject ลอมบอกที่ทำสิ่งเดียวกัน
Consumer
s ในforEach
อาจถูกดำเนินการแบบขนานเมื่อใช้Stream
s ขนาน บทสรุปที่ยกมาจากการใช้ภายในผู้บริโภคจะแพร่กระจายไปยังเธรดการโทรซึ่ง 1) จะไม่หยุดผู้ใช้ที่รันอยู่พร้อม ๆ กันซึ่งอาจหรืออาจไม่เหมาะสมและ 2) หากผู้บริโภคมากกว่าหนึ่งคนขว้างอะไรบางอย่างเท่านั้น เธรดการโทรอย่างใดอย่างหนึ่งจะเห็นได้