英文:
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());
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论