无法在 Java 中使用 orElseThrow 抛出自定义异常
Cannot throw custom exception using orElseThrow in Java
我正在尝试使用三元运算和 orElseThrow
抛出自定义异常,如下所示:
public static MainProviderType getMainProviderType(ProviderType providerType) {
return Optional.ofNullable(MainProviderType.valueOf(providerType.name()))
.orElseThrow(() -> new ProviderTypeNotFoundException(providerType.name()));
}
但是,当 providerType
为 null 时,此方法 returns 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);
}
orElseThrow()
仅适用于 Optional 的值。您的代码可能会尝试创建 Optional 实例失败,或者在通过对潜在的空对象调用 .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,然后通过映射应用每个转换:
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"));
}
您的问题与 providerType.name()
有关。如果 providerType
是 null
,那么您的代码将像这样工作:null.name()
。这是没有意义的,当 providerType
是 null
时,总是会抛出 NullPointerException
您可以在继续其他所有操作之前检查 providerType
是否为空:
if(providerType == null)
{
throw ProviderTypeNotFoundException(..);
}
我正在尝试使用三元运算和 orElseThrow
抛出自定义异常,如下所示:
public static MainProviderType getMainProviderType(ProviderType providerType) {
return Optional.ofNullable(MainProviderType.valueOf(providerType.name()))
.orElseThrow(() -> new ProviderTypeNotFoundException(providerType.name()));
}
但是,当 providerType
为 null 时,此方法 returns 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);
}
orElseThrow()
仅适用于 Optional 的值。您的代码可能会尝试创建 Optional 实例失败,或者在通过对潜在的空对象调用 .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,然后通过映射应用每个转换:
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"));
}
您的问题与 providerType.name()
有关。如果 providerType
是 null
,那么您的代码将像这样工作:null.name()
。这是没有意义的,当 providerType
是 null
NullPointerException
您可以在继续其他所有操作之前检查 providerType
是否为空:
if(providerType == null)
{
throw ProviderTypeNotFoundException(..);
}