不能在Java中使用orElseThrow抛出自定义异常



我正在尝试使用三元操作和orElseThrow抛出一个自定义异常,如下所示:

public static MainProviderType getMainProviderType(ProviderType providerType) {
return Optional.ofNullable(MainProviderType.valueOf(providerType.name()))
.orElseThrow(() -> new ProviderTypeNotFoundException(providerType.name()));
}

但是,当providerType为null时,此方法返回NullPointerException而不是ProviderTypeNotFoundException。我认为问题与此有关;它不能求MainProviderType.valueOf(providerType.name()),因为providerType.name()。这是真的吗?我应该如何使用它并解决问题?

public static MainProviderType getMainProviderType(ProviderType providerType) {
return Optional.ofNullable(providerType)
.map(ProviderType::name)
.map(MainProviderType::valueOf)
.orElseThrow(() -> new ProviderTypeNotFoundException("some message"));
}

带有测试用例的完整示例

private enum ProviderType {
ONE,
TWO
}
private enum MainProviderType {
ONE,
TWO,
THREE
}
public MainProviderType getMainProviderType(ProviderType providerType) {
return Optional.ofNullable(providerType)
.map(ProviderType::name)
.map(MainProviderType::valueOf)
.orElseThrow();
}
@Test
void selectMainProviderType() {
var mainProviderType = getMainProviderType(ProviderType.ONE);
assertEquals(MainProviderType.ONE, mainProviderType);
}

您的问题与providerType.name()有关。如果providerTypenull,那么代码将像这样工作:null.name()。这是没有意义的,当providerTypenull时,总是会抛出NullPointerException

您可以检查providerType是否为空,然后再继续执行其他操作:

if(providerType == null)
{
throw ProviderTypeNotFoundException(..);
}

orElseThrow()只作用于Optional的值。您的代码可能会在尝试创建可选实例时失败,或者在通过在潜在的null对象上调用.name()来构造异常时失败。可以通过将每个表达式分离成一个语句来重写它,它给出了等价的形式:

var name = providerType.name(); // nullpointer! providerType can be null
var type = MainProviderType.valueOf(name); // nullpointer! name can be null
var optional = Optional.ofNullable(type);
return optional.orElseThrow(() -> new ProviderTypeNotFoundException(providerType.name())); // nullpointer! providerType can still be null

检查providerType及其名称是否为空,或者更早地创建Optional,然后通过map应用每个转换:

public static MainProviderType getMainProviderType(ProviderType providerType) {
return Optional.ofNullable(providerType)
.map(ProviderType::name)
.map(MainProviderType::valueOf)
.orElseThrow(() -> new ProviderTypeNotFoundException(providerType != null ? providerType.name() : "no name"));
}

最新更新