英文:
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<String> 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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论