我正在尝试使用三元操作和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()
有关。如果providerType
是null
,那么代码将像这样工作:null.name()
。这是没有意义的,当providerType
是null
时,总是会抛出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"));
}