首页 > 解决方案 > 这是一个多余的 NullPointerException 捕获吗?

问题描述

下面的 Spring REST 代码返回给定ticketId 的列表。

可以NullPointerException在这段代码中抛出一个吗?

NullPointerException明确陷入TicketController

    catch (NullPointerException nullPointerException) {
        throw new ResponseStatusException(
            HttpStatus.BAD_REQUEST, nullPointerException.getMessage(), nullPointerException);
    }

在检查票证 ID 是否为 null 时,可能会有这样的想法:

        if (ticketId == null) {
            throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "ticket id cannot be null");
        }

期望 aNullPointerException会被抛出,而不是 aResponseStatusException被抛出?

如果变量ticketId是路径参数,则它永远不能为空,因为在/没有ticketId我收到的情况下点击基本 url:

There was an unexpected error (type=Method Not Allowed, status=405).

全部来源:

@RestController
    public class TicketController {

        private final TicketServiceImpl ticketServiceImpl;

        public TicketController(TicketServiceImpl ticketServiceImpl) {
            this.ticketServiceImpl = ticketServiceImpl;
        }

        @GetMapping(path = "/{ticketId}")
        public ResponseEntity<List<TicketResponse>> getTicketsById(
            @PathVariable("ticketId") final Long ticketId) {
            try {
                final List<TicketResponse> ticketsById = ticketServiceImpl.getAll(ticketId);
                return new ResponseEntity<>(ticketsById, HttpStatus.OK);
            }
            catch (NullPointerException nullPointerException) {
                throw new ResponseStatusException(
                    HttpStatus.BAD_REQUEST, nullPointerException.getMessage(), nullPointerException);
            }
            catch (TicketNotFoundException ticketNotFoundException) {
                throw new ResponseStatusException(
                    HttpStatus.NOT_FOUND, "Ticket id not found",
                    ticketNotFoundException);
            }

        }

    }

@Service
public class TicketServiceImpl implements TicketService {

    private final TicketRepository ticketRepository;

    public TicketServiceImpl(TicketRepository ticketRepository) {

        this.ticketRepository = ticketRepository;

    }

    @Override
    public List<TicketResponse> getAll(Long ticketId) {

        final List<TicketResponse> ticketResponselist = ticketRepository.findData(ticketId);

            if (ticketId == null) {
                throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "ticket id cannot be null");
            }
            else if (ticketResponselist.size() == 0) {
                throw new TicketNotFoundException("ticket not found");
            }
            else {
                return ticketResponselist;
            }

    }
}

@Repository
public interface TicketRepository {

    public List<TicketResponse> findData(Long ticketId);

}

标签: javaspringspring-bootrestmodel-view-controller

解决方案


if (ticketId == null)检查应该在调用ticketRepository.findData(ticketId);之前进行。

否则,验证没有意义。

另外,作为旁注,捕捉NullPointerException是一种不好的做法。原因是抛出空指针异常主要是编码气味的标志。通过使用例如Optional或在方法级别进行适当的验证,代码应该是 null 安全的。在这种情况下,它将处于路由级别(即外部输入)。从那时起,如果设置了验证,您将处理不可为空的 id。

这也与从方法返回 null 有关,这也是一种不好的做法,因为它需要检查每个方法,然后使用返回的值。这会污染代码,引入新的抽象级别,并且通常会导致严重的错误。


推荐阅读