无法在 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() 有关。如果 providerTypenull,那么您的代码将像这样工作:null.name()。这是没有意义的,当 providerTypenull

时,总是会抛出 NullPointerException

您可以在继续其他所有操作之前检查 providerType 是否为空:

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