使用Java的Optional重构空指针检查

huangapple go评论62阅读模式
英文:

Use Java Optional to refactor null check

问题

我想要实现的目标:

使用 Java 的 Optional 重构空值检查。

背景:

我有一个简单的 POJO 类:

public record MyPojo(String someField, String someOtherField)

还有这个方法:

private static String question(final MyPojo mypojo) {
    if (null == mypojo) {
        return null;
    } else if (null == mypojo.someField()) {
        return null;
    } else {
        return mypojo.someField().toLowerCase();
    }
}

问题:

如你所见,尽管很容易理解,但这段代码非常冗长。
MyPojo 可能为空,MyPojo.someField 也可能为空。
在应用我的业务逻辑之前,我需要检查这两个前提条件(这里只是举例使用小写)。

问题:

是否有更智能的方法,可以使用 Optional 或其他更智能的方式重构这段代码?

英文:

What I am trying to achieve:

Use Java Optional to refactor null check.

Background:

I have a straightforward POJO class:

public record MyPojo(String someField, String someOtherField)

And this method:

    private static String question(final MyPojo mypojo) {
        if (null == mypojo) {
            return null;
        } else if (null == mypojo.someField()) {
            return null;
        } else {
            return mypojo.someField().toLowerCase();
        }
    }

Issue:

As you can see, while super easy to understand, this code is very verbose and lengthy.
MyPojo can be bull, and so can MyPojo.someField.
I need to check those two preconditions before applying my business logic (here lower case just for example)

Question:

Is there a smarter way, either using Optional, or something smarter, to refactor this?

答案1

得分: 3

你可以使用.map()方法链式调用可选项,这种方法的优点是可以将操作以可读性良好的方式链接在一起,消除了需要显式空值检查的需要:

private static String question(final MyPojo mypojo) {
    return Optional.ofNullable(mypojo)
              .map(MyPojo::someField)
              .map(String::toLowerCase)
              .orElse(null);
}
英文:

You can chain your optional with .map() calls, the advantage of this approach is that it chains the operations together in a readable way and eliminates the need for explicit null checks:

private static String question(final MyPojo mypojo) {
    return Optional.ofNullable(mypojo)
              .map(MyPojo::someField)
              .map(String::toLowerCase)
              .orElse(null);
}

答案2

得分: 1

老式的方法是使用 ? : 运算符:

private static String question(final MyPojo mypojo) {
    return (null == mypojo) ? null
        : (null == mypojo.someField()) ? null
        : mypojo.someField().toLowerCase();
}
英文:

The old fashioned way is with the ? : operators:

    private static String question(final MyPojo mypojo) {
        return (null == mypojo) ? null
            : (null == mypojo.someField()) ? null
            : mypojo.someField().toLowerCase();
    }

答案3

得分: 1

Here are the translated parts from your provided content:

首先更改记录:

public record MyPojo( String someField, String someOtherField )
{
    public MyPojo
    {
        Objects.requireNonNull( someField );
        Objects.requireNonNull( someOtherField );
    }
}

这确保了属性永远不会是 null

然后 question() 可以如下所示:

private static String question( final MyPojo mypojo ) 
{
    return Objects.nonNull( myPojo ) 
        ? myPojo.someField().toLowerCase() 
        : null;
}

如果允许 null 并且坚持使用 Optional,您需要修改 Pojo 如下所示:

public final class MyPojo
{
    private final String m_SomeField;
    private final String m_SomeOtherField;
    public MyPojo( String someField, String someOtherField )
    {
        m_SomeField = someField;
        m_SomeOtherField = someOtherField;
    }

    public final Optional<String> someField() {return Optional.ofNullable( m_SomeField ); }
    
}

之后 question() 将如下所示:

private static String question( final MyPojo mypojo ) 
{
    return Objects.nonNull( myPojo ) 
        ? myPojo.someField().map( String::toLowerCase() ).orElse( null ) 
        : null;
}

1 中建议的方法是可行的,但强烈不建议滥用 Optional 以替代 if-then-else?-:。请参阅 2 作为一个参考:

另一个错误是滥用 Optional 并将其视为条件语句的替代品。虽然 Optional 提供了方便的方法,如 orElse()orElseGet() 来处理值的缺失,但过度使用它们可能导致代码不够可读。重要的是要记住,Optional 并不是用来替代传统的 if-else 语句的。相反,应在值的缺失是有效且预期的结果时使用它。

英文:

First change the record:

public record MyPojo( String someField, String someOtherField )
{
    public MyPojo
    {
        Objects.requireNonNull( someField );
        Objects.requireNonNull( someOtherField );
    }
}

This ensures that the attributes are never null.

Then question() can look like this:

private static String question( final MyPojo mypojo ) 
{
    return Objects.nonNull( myPojo ) 
        ? myPojo.someField().toLowerCase() 
        : null;
}

If null should be allowed and you insist to use Optional, you need to modify the Pojo like this:

public final class MyPojo
{
    private final String m_SomeField;
    private final String m_SomeOtherField;
    public MyPojo( String someField, String someOtherField )
    {
        m_SomeField = someField;
        m_SomeOtherField = someOtherField;
    }

    public final Optional&lt;String&gt; someField() {return Optional.ofNullable( m_SomeField ); }
    …
}

question() would look like this afterwards:

private static String question( final MyPojo mypojo ) 
{
    return Objects.nonNull( myPojo ) 
        ? myPojo.someField().map( String::toLowerCase() ).orElse( null ) 
        : null;
}

The approach suggested in this answer works, but it is strongly discouraged to abuse Optional in this way as a replacement for if-then-else or ?-:. See here as one reference:

> Another mistake is misusing Optional and treating it as a replacement for conditional statements. Although Optional provides convenient methods like orElse() and orElseGet() to handle the absence of a value, using them excessively can lead to less readable code. It is important to remember that Optional is not intended to replace traditional if-else statements. Instead, it should be used when the absence of a value is a valid and expected outcome.
>
> […]
>
> […] Adhering to best practices such as preferring Optional as a method return type […] will enhance the readability and maintainability of your code.

huangapple
  • 本文由 发表于 2023年6月9日 01:12:27
  • 转载请务必保留本文链接:https://go.coder-hub.com/76434242.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定