2015-01-12 15 views
6

Với đoạn mã sau,Làm thế nào tôi có thể ném lại một ngoại lệ trong khối lambda như từ khối ngoài?

void key(Key) throws SomeCheckedException { 
} 

void supplier(Supplier<Key> s) throws SomeCheckedException { 
    ofNullable(s).ifPresent(s -> {     // | 
     try {          // | 
      key(s.get());       // | 
     } catch (final SomeCheckedException sce) { // | 
      // sce is coming from key() method  // | 
      // How can I throw sce for outer method? // --/ 
     } 
    }); 
} 

Làm thế nào tôi có thể ném sce như nếu phương pháp (supplier) phương pháp là ném nó?

Xin lưu ý rằng mã trên chỉ là một ví dụ. Tôi cần key(s.get()) để được bên trong một biểu thức lambda.

void supplier(Supplier<Key> s) throws SomeCheckException { 
    key(s.get()); 
} 
+2

Ah, tôi không nghĩ rằng 'khóa (…)' có thể ném ngoại lệ đã kiểm tra. Tuy nhiên [câu trả lời của tôi] (http://stackoverflow.com/a/27900544/2711488) cũng xử lý trường hợp đó. – Holger

Trả lời

2

Nếu bạn muốn xử lý ngoại lệ đã kiểm tra một cách an toàn, bạn cần có phương pháp trợ giúp cung cấp cơ sở bao gồm ngoại lệ thành loại phụ RuntimeException. Dưới đây là ví dụ một hàm helper trong đó sử dụng an toàn kiểu Generic để đảm bảo rằng chỉ tuyên bố trường hợp ngoại lệ sẽ được tái ném (trừ khi bạn sử dụng một hoạt động không an toàn):

public static <E extends Throwable> void attempt(
    Consumer<Function<E,RuntimeException>> action) throws E { 

    final class CarryException extends RuntimeException { 
     final E carried; 
     CarryException(E cause) { 
      super(cause); 
      carried=cause; 
     } 
    } 

    try { action.accept(CarryException::new); } 
    catch(CarryException ex) { throw ex.carried; } 
} 

Nó hỗ trợ một tùy action đó sẽ nhận được một chức năng mà không gói tạm thời của loại ngoại lệ đã kiểm tra vào RuntimeException. Gói này sẽ được minh bạch, phương pháp attempt sẽ hoàn thành bình thường hoặc ném ngoại lệ đã kiểm tra ban đầu E (hoặc một ngoại lệ không được kiểm soát không liên quan nếu xảy ra).

Vì vậy, bạn có thể sử dụng nó như thế này:

public static void processIterm(Supplier<Key> s) 
    throws SomeCheckedException { 

    attempt((Function<SomeCheckedException, RuntimeException> thrower) -> 
     Optional.ofNullable(s).ifPresent(nonNull -> { 
      try { key(nonNull.get()); } // assuming key may throw SomeCheckedException 
      catch(SomeCheckedException e) { throw thrower.apply(e); } 
     })); 
} 

Do các hoạt động lồng trình biên dịch không thể suy ra các ngoại lệ gõ tự động. Đoạn mã trên sử dụng khai báo rõ ràng loại thông số thrower. Hoặc bạn có thể sử dụng lời gọi kiểu của phương thức trợ giúp như

ContainingClass.<SomeCheckedException>attempt(thrower -> 
    Optional.ofNullable(s).ifPresent(nonNull -> { 
     try { key(nonNull.get()); } 
     catch(SomeCheckedException e) { throw thrower.apply(e); } 
    })); 
7

Bạn không thể. Supplier#get() không khai báo để ném bất kỳ ngoại lệ (đã kiểm tra) nào. Hãy nhớ rằng một biểu thức lambda chỉ đơn giản là tạo ra một cá thể, nó không thực sự gọi phương thức giao diện hàm đích.

Nếu bạn muốn, bạn có thể bao gồm ngoại lệ đã chọn trong trường hợp ngoại lệ không được chọn và ném ngoại lệ đó.

Các vấn đề liên quan