重写一个方法,使用Optional,但不更改该方法之外的任何内容。

huangapple go评论75阅读模式
英文:

Rewriting a method to use Optional without changing anything outside this method

问题

我遇到了这段代码。

public AnimalResponse getAnimal(Specie specie) {
    AnimalEntity animal = speciesRepository.findBySpecie(specie).orElseThrow(
        () -> new ResourceNotFoundException(specie)
    ).getAnimal();

    if (animal == null) {
        throw new NoAnimalException();
    }

    return getAnimal(animal.getId());
}

getAnimal() 方法可能返回 null,因此随后在该对象上调用 getId() 会导致 NPE。因此,我想避免使用空值检查。

我想知道:我如何重写这个方法以使用 Optionals 并保持相同的功能?这可行吗,会更清晰吗?

我意识到这个方法在最好的情况下令人困惑,但我不想改变该方法之外的任何内容,并且难以使 Optional 的任何内容工作。

英文:

I have came across this code.

public AnimalResponse getAnimal(Specie specie) {
    AnimalEntity animal = speciesRepository.findBySpecie(specie).orElseThrow(
        () - > new ResourceNotFoundException(specie)
    ).getAnimal();

    if (animal == null) {
        throw new NoAnimalException();
    }

    return getAnimal(animal.getId());
}

getAnimal() method may return null, so later on invoking getId() on that object leads to NPE. Hence null check is used that I want to avoid.

I was wondering: how can I re-write this method for it to use Optionals and maintain the same functionality? Is it doable, will it be cleaner?

I realize this method is confusing at best, but I don't want to change anything outside this method, and struggle to make anything out of Optional work.

答案1

得分: 4

trdanv的回答是在不改变行为的情况下达到了最佳水平。

如果您能将这两个异常合并为一个,涵盖Animal为null或未找到species,那么您就能更符合惯用法地使用Optional

return speciesRepository.findBySpecie(specie)
    .map(Species::getAnimal)
    .map(AnimalEntity::getId)
    .map(this::getAnimal)
    .orElseThrow(() -> new AnotherException(specie));
英文:

trdanv's answer is about as good as it gets without changing the behaviour.

If you are able to consolidate the two exceptions into one which covers either Animal being null or species not being found, then you are able to use Optional much more idiomatically

return speciesRepository.findBySpecie(specie)
    .map(Species::getAnimal)
    .map(AnimalEntity::getId)
    .map(this::getAnimal)
    .orElseThrow(() -> new AnotherException(specie));

答案2

得分: 3

基本上,我的理想是在我们抛出异常之前,将物种映射到动物。

AnimalEntity animal = speciesRepository.findBySpecie(specie)
        .map(spec -> spec.getAnimal())
        .orElseThrow(() -> new ResourceNotFoundException(specie));
return getAnimal(animal.getId());
英文:

Basically my ideal is we map species to animal before we throw exception

AnimalEntity animal = speciesRepository.findBySpecie(specie)
        .map(spec -> spec.getAnimal())
        .orElseThrow(() -> new ResourceNotFoundException(specie));
return getAnimal(animal.getId());

答案3

得分: 2

如果我理解正确的话,您可以像这样将其包装在 Optional.ofNullable() 中:

public AnimalResponse getAnimal(Specie specie) {
    AnimalEntity animal = Optional.ofNullable(speciesRepository
            .findBySpecie(specie)
            .orElseThrow(() ->
                new ResourceNotFoundException(specie))
            .getAnimal())
        .orElseThrow(() -> new NoAnimalException());

    return getAnimal(animal.getId());
}
英文:

If I understand correctly, you can wrap it in a Optional.ofNullable() like so:

public AnimalResponse getAnimal(Specie specie) {
    AnimalEntity animal = Optional.ofNullable(speciesRepository
            .findBySpecie(specie)
            .orElseThrow(() - >
                new ResourceNotFoundException(specie))
            .getAnimal())
        .orElseThrow(() - > new NoAnimalException());

    return getAnimal(animal.getId());
}

huangapple
  • 本文由 发表于 2020年7月24日 17:25:02
  • 转载请务必保留本文链接:https://go.coder-hub.com/63070701.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定