为什么使用 Optional 而不是 Objects.isNull 或 obj == null 给我优势?

Why does using Optional instead of Objects.isNull or obj == null give me advantage?

我想创建方法,它将使用可选功能和 return 值 NodeId
我应该从 Asset 对象中提取这个值。
在某些情况下,我已经使用了一些功能,如 ifPresent、filter、flatMap。但是现在我想清楚地了解我是否可以使用 Optional 和下面示例中的简单方法,我只需要从另一个 Object
中提取值
第一个例子应该不是很好但是我尝试使用可选的:

   public Optional<NodeId> findParentNodeIdByAsset(Asset asset) {
        Optional<Asset> tmpAsset = Optional.ofNullable(asset);
        if(tmpAsset.isEmpty()) {
            throw new NullPointerException();
        }
        return Optional.ofNullable(tmpAsset.get().getParents().iterator().next());
    }


在第二个例子中,我尝试写同样的东西但没有 Optional:

    public NodeId tmpFindParentNodeIdByAsset(Asset asset) {
        if(Objects.isNull(asset)) {
            throw new NullPointerException();
        }
        return asset.getParents().iterator().next();
    }

如果在这些情况下要抛出 NullPointerException,则没有必要检查 null asset 或空的 tmpAsset

随便写:

public NodeId tmpFindParentNodeIdByAsset(Asset asset) {
    return asset.getParents().iterator().next();
}

如果您尝试取消对空引用的引用,将抛出 NullPointerException

现在,如果您不想抛出 NullPointerException 或者如果 asset 不是唯一可能是 null 的引用,则使用 Optional 会变得很有用。

例如,假设 asset.getParents() 也可以是 null,如果 assetasset.getParents() 为 null,您希望 return一些默认值,或者一个空的 Optional.

您可以链接多个 map() 调用以将每个潜在 null 引用转换为下一个潜在 null 引用,并以 Optional 结束(如下面的示例),默认值或异常。

public Optional<NodeId> findParentNodeIdByAsset(Asset asset) {
    return Optional.ofNullable(asset)
                   .map(asset -> asset.getParents())
                   .map(parents -> parents.iterator().next());
}

此外,在尝试获取其 Iterator 的第一个元素之前检查 parents 是否为空可能更安全。

您在第一种方法中没有正确使用 Optional,在返回 Optional 的方法中抛出 NullPointerException 没有多大意义.请参阅 Eran 的回答以正确使用。

但是,如果您 想要在输入为 null 时抛出 NullPointerException,那么将使用此代替:

public NodeId tmpFindParentNodeIdByAsset(Asset asset) {
    Objects.requireNonNull(asset, "asset");
    return asset.getParents().iterator().next();
}

使用Optional可以让代码更流畅,提高可读性。 在你的情况下,我确实会使用一个可选的。例如:

public NodeId tmpFindParentNodeIdByAsset(Asset asset) {
  return Optional.ofNullable(asset)
    .map(asset -> asset.getParents().iterator().next())
    .orElseThrow(UnsupportedOperationException::new)
}

否则,如果您想 return 可选,只需删除 orElseThrow()。对于 getParents()、iterator() 或 next() 的每个方法,可能 return null,您应该创建一个不属于 NPE 的映射链。例如:

public Optional<NodeId> tmpFindParentNodeIdByAsset(Asset asset) {
  return Optional.ofNullable(asset)
    .map(asset -> asset.getParents())
    .map(parents -> parents.iterator().next());
}

通过使用 Optional,您可以确保调用者知道返回值可能为 null。