Tôi đánh giá cao rất nhiều tính năng Java 8 mới về lambdas và các giao diện phương thức mặc định. Tuy nhiên, tôi vẫn cảm thấy nhàm chán với các ngoại lệ được kiểm tra. Chẳng hạn, nếu tôi chỉ muốn liệt kê tất cả các trường hiển thị của một đối tượng, tôi chỉ muốn viết điều này:
Arrays.asList(p.getClass().getFields()).forEach(
f -> System.out.println(f.get(p))
);
Tuy nhiên, vì get
phương thức có thể đưa ra một ngoại lệ được kiểm tra, không đồng ý với Consumer
hợp đồng giao diện, nên tôi phải bắt ngoại lệ đó và viết mã sau đây:
Arrays.asList(p.getClass().getFields()).forEach(
f -> {
try {
System.out.println(f.get(p));
} catch (IllegalArgumentException | IllegalAccessException ex) {
throw new RuntimeException(ex);
}
}
);
Tuy nhiên, trong hầu hết các trường hợp, tôi chỉ muốn ngoại lệ được ném như một RuntimeException
và để chương trình xử lý, hoặc không, ngoại lệ không có lỗi biên dịch.
Vì vậy, tôi muốn có ý kiến của bạn về cách giải quyết gây tranh cãi của tôi đối với sự phiền toái ngoại lệ được kiểm tra. Cuối cùng, tôi đã tạo ra một giao diện phụ trợ ConsumerCheckException<T>
và một chức năng tiện ích rethrow
( được cập nhật theo đường dẫn của nhận xét của Doval ) như sau:
@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;
}
}
Và bây giờ tôi chỉ có thể viết:
Arrays.asList(p.getClass().getFields()).forEach(
rethrow(f -> System.out.println(f.get(p)))
);
Tôi không chắc chắn rằng đây là thành ngữ tốt nhất để xoay quanh các ngoại lệ được kiểm tra, nhưng như tôi đã giải thích, tôi muốn có một cách thuận tiện hơn để đạt được ví dụ đầu tiên của mình mà không phải xử lý các ngoại lệ được kiểm tra và đây là cách đơn giản hơn mà tôi tìm thấy để làm điều đó.
sneakyThrow
bên trong rethrow
để ném ngoại lệ gốc, đã kiểm tra thay vì gói nó trong một RuntimeException
. Ngoài ra, bạn có thể sử dụng @SneakyThrows
chú thích từ Project Lombok cũng làm điều tương tự.
Consumer
s in forEach
có thể được thực thi theo kiểu song song khi sử dụng Stream
s song song . Một cú ném được nâng lên từ việc héo người tiêu dùng sau đó sẽ truyền đến chuỗi cuộc gọi, trong đó 1) sẽ không ngăn chặn những người tiêu dùng đang chạy đồng thời khác, điều này có thể hoặc không phù hợp, và 2) nếu nhiều hơn một trong số những người tiêu dùng ném thứ gì đó, chỉ một trong những vật ném sẽ được nhìn thấy bởi luồng gọi.