【问题标题】:What is a better way to handle a RuntimeException in a method?在方法中处理 RuntimeException 的更好方法是什么?
【发布时间】:2017-11-05 20:31:43
【问题描述】:

我听说处理运行时异常并不总是一个好习惯。我已经实现了一个将产品评级作为参数的方法,如果当前产品对象有这个评级,它会返回一个 ProductDTO 对象。我发现使该方法按预期工作的唯一方法是使用运行时异常。但是根据 Joshua Bloch 的说法,将异常用于控制流是一个非常糟糕的主意。

有没有办法改进方法的逻辑?

public ProductDTO findByRating(int productRating) {
    ProductDTO productDTO = new ProductDTO();
    if (productRating == this.avgRating()) {
        productDTO.setProductName(productName);
        productDTO.setProductsLeftForSale(productsLeftForSale());
        productDTO.setAvgRating(avgRating());
        productDTO.setTotalVotes(reviews.size());
        return productDTO;
    } else {
        throw new RuntimeException(String.format("No Product found with the rating: %s", productRating));
    }
}

.

List<ProductDTO> productDTOList = new ArrayList<>();    
        int rating = 5;
        for (BaseProduct product : products) {
            try {
                ProductDTO productDTO = product.findByRating(rating);
                if (productDTO != null) {
                    productDTOList.add(productDTO);
                }
            } catch (RuntimeException e) {
                e.printStackTrace();
            }
        }

【问题讨论】:

  • 返回null有什么问题?
  • 如果要抛出异常,请抛出NoSuchElementException,而不是更一般的RuntimeException
  • 您可以返回Optional&lt;ProductDTO&gt;
  • @samba 但你已经有productDTO != null check....
  • 在你们使用null 向其他人求婚之前,请务必阅读 Tony Hoare 的道歉。 en.wikipedia.org/wiki/Tony_Hoare#Apologies_and_retractions

标签: java exception runtimeexception


【解决方案1】:

也许它看起来更好一点:

import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

...

public Optional<ProductDTO> findByRating(int rating) {
    return this.avgRating() == rating ? Optional.of(createDTO()) : Optional.empty();
}

private ProductDTO createDTO() {
    ProductDTO productDTO = new ProductDTO();
    productDTO.setProductName(productName);
    productDTO.setProductsLeftForSale(productsLeftForSale());
    productDTO.setAvgRating(avgRating());
    productDTO.setTotalVotes(reviews.size());
    return productDTO;
}

public List<ProductDTO> findProductsByRating(int rating) {
    return products.stream()
            .map(product -> product.findByRating(rating))
            .filter(Optional::isPresent)
            .map(Optional::get)
            .collect(Collectors.toList());
}

【讨论】:

  • 感谢您的清晰解释。如果输入了不存在的评级值,我想抛出一个运行时异常怎么办?orElseThrow(() -&gt; new MyException(someArgument))。在这个例子中如何正确使用它?
  • 我认为在这种情况下抛出异常是一种不好的做法。如果产品有另一个评级,这是您程序中的正常情况。通常,如果出现任何问题,您应该抛出异常:例如,您调用 getById(long id) 并且找不到具有此类 id 的产品。
  • 您也可以先过滤我们的产品列表products.stream().filter(p -&gt; p.getRating() == rating),然后将产品映射到您的 DTO 对象。之后,您使用 findFirst() 返回一个 Optional。
猜你喜欢
  • 2016-06-12
  • 1970-01-01
  • 2020-06-02
  • 1970-01-01
  • 2014-05-03
  • 1970-01-01
  • 2021-10-28
  • 2019-03-25
  • 2019-06-17
相关资源
最近更新 更多