如何在Optional.map的Lambda中传递抛出的异常并避免try/catch循环?
解决Optional映射中传递检查型异常的问题
核心问题在于Optional.map()接收的Function接口不允许抛出检查型异常,因此IDE会强制要求你在Lambda中捕获createFieldHivesResponse抛出的FieldNotOwnedException。以下是几种无需使用isPresent()/get()的解决方案:
方案1:将检查型异常转为非检查型异常
如果业务允许,直接修改FieldNotOwnedException继承RuntimeException,这样Lambda中无需额外处理,异常会自动向上传递:
// 修改异常类 public class FieldNotOwnedException extends RuntimeException { public FieldNotOwnedException(String message) { super(message); } } // 原方法无需改动,IDE不再报错 public List<HiveResponse> getFieldHives(String token, Long id) throws UserNotFoundException, FieldNotFoundException { Optional<FieldDAO> optionalFieldDAO = fieldRepository.findById(id); return optionalFieldDAO .map(fieldDAO -> createFieldHivesResponse(fieldDAO, user)) .orElseThrow(() -> new FieldNotFoundException("Field not found!")); } private List<HiveResponse> createFieldHivesResponse(FieldDAO fieldDAO, UserDAO user) { if(!user.getFieldDAOList().contains(fieldDAO)) throw new FieldNotOwnedException("Field not owned!"); // rest of code }
若不想修改异常类,可在Lambda中手动包装成RuntimeException,再在上层方法中还原原异常:
public List<HiveResponse> getFieldHives(String token, Long id) throws UserNotFoundException, FieldNotFoundException, FieldNotOwnedException { Optional<FieldDAO> optionalFieldDAO = fieldRepository.findById(id); try { return optionalFieldDAO .map(fieldDAO -> { try { return createFieldHivesResponse(fieldDAO, user); } catch (FieldNotOwnedException e) { throw new RuntimeException(e); // 包装为非检查异常 } }) .orElseThrow(() -> new FieldNotFoundException("Field not found!")); } catch (RuntimeException e) { // 还原原检查异常 if (e.getCause() instanceof FieldNotOwnedException) { throw (FieldNotOwnedException) e.getCause(); } throw e; // 其他异常正常抛出 } }
方案2:自定义函数接口包装检查型异常
定义支持抛出检查异常的函数接口,再封装工具方法转为普通Function,避免在Lambda中重复写try/catch:
// 自定义支持检查异常的函数接口 @FunctionalInterface public interface ThrowingFunction<T, R, E extends Exception> { R apply(T t) throws E; } // 工具方法:将ThrowingFunction转为普通Function public static <T, R, E extends Exception> Function<T, R> unchecked(ThrowingFunction<T, R, E> function) { return t -> { try { return function.apply(t); } catch (Exception e) { throw new RuntimeException(e); } }; } // 业务方法中使用 public List<HiveResponse> getFieldHives(String token, Long id) throws UserNotFoundException, FieldNotFoundException, FieldNotOwnedException { Optional<FieldDAO> optionalFieldDAO = fieldRepository.findById(id); try { return optionalFieldDAO .map(unchecked(fieldDAO -> createFieldHivesResponse(fieldDAO, user))) .orElseThrow(() -> new FieldNotFoundException("Field not found!")); } catch (RuntimeException e) { if (e.getCause() instanceof FieldNotOwnedException) { throw (FieldNotOwnedException) e.getCause(); } throw e; } }
方案3:借助Stream简化异常处理
将Optional转为Stream,利用Stream的map操作处理逻辑,写法更简洁:
public List<HiveResponse> getFieldHives(String token, Long id) throws UserNotFoundException, FieldNotFoundException, FieldNotOwnedException { Optional<FieldDAO> optionalFieldDAO = fieldRepository.findById(id); try { return optionalFieldDAO.stream() .map(fieldDAO -> { try { return createFieldHivesResponse(fieldDAO, user); } catch (FieldNotOwnedException e) { throw new RuntimeException(e); } }) .findFirst() .orElseThrow(() -> new FieldNotFoundException("Field not found!")); } catch (RuntimeException e) { if (e.getCause() instanceof FieldNotOwnedException) { throw (FieldNotOwnedException) e.getCause(); } throw e; } }
内容的提问来源于stack exchange,提问作者Adrian
相关产品推荐
相关产品推荐

