Saya menghargai banyak fitur Java 8 baru tentang lambdas dan antarmuka metode standar. Namun, saya masih bosan dengan pengecualian yang diperiksa. Misalnya, jika saya hanya ingin membuat daftar semua bidang yang terlihat dari suatu objek, saya hanya ingin menulis ini:
Arrays.asList(p.getClass().getFields()).forEach(
f -> System.out.println(f.get(p))
);
Namun, karena get
metode ini dapat membuang pengecualian yang diperiksa, yang tidak setuju dengan Consumer
kontrak antarmuka, maka saya harus menangkap pengecualian itu dan menulis kode berikut:
Arrays.asList(p.getClass().getFields()).forEach(
f -> {
try {
System.out.println(f.get(p));
} catch (IllegalArgumentException | IllegalAccessException ex) {
throw new RuntimeException(ex);
}
}
);
Namun dalam kebanyakan kasus saya hanya ingin pengecualian untuk dilemparkan sebagai RuntimeException
dan biarkan program menangani, atau tidak, pengecualian tanpa kesalahan kompilasi.
Jadi, saya ingin pendapat Anda tentang solusi kontroversial saya untuk gangguan pengecualian yang diperiksa. Untuk itu, saya membuat antarmuka tambahan ConsumerCheckException<T>
dan fungsi utilitas rethrow
( diperbarui sesuai dengan saran komentar Doval ) sebagai berikut:
@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;
}
}
Dan sekarang saya bisa menulis:
Arrays.asList(p.getClass().getFields()).forEach(
rethrow(f -> System.out.println(f.get(p)))
);
Saya tidak yakin bahwa ini adalah ungkapan terbaik untuk membalikkan pengecualian yang diperiksa, tetapi seperti yang saya jelaskan, saya ingin memiliki cara yang lebih nyaman untuk mencapai contoh pertama saya tanpa berurusan dengan pengecualian yang diperiksa dan ini adalah cara yang lebih sederhana yang saya temukan untuk melakukannya.
sneakyThrow
bagian dalam rethrow
untuk membuang yang asli, memeriksa pengecualian alih-alih membungkusnya dalam RuntimeException
. Atau Anda dapat menggunakan @SneakyThrows
anotasi dari Project Lombok yang melakukan hal yang sama.
Consumer
s dalam forEach
dapat dieksekusi secara paralel saat menggunakan paralel Stream
s. Suatu throwable yang muncul dari dalam konsumen kemudian akan menyebar ke thread panggilan, yang 1) tidak akan menghentikan konsumen yang berjalan bersamaan lainnya, yang mungkin atau mungkin tidak sesuai, dan 2) jika lebih dari satu konsumen melempar sesuatu, hanya salah satu throwables akan terlihat oleh utas panggilan.