【问题标题】:How to convert a possible null-value to a default value using Guava?如何使用 Guava 将可能的空值转换为默认值?
【发布时间】:2011-12-23 18:44:38
【问题描述】:

如果传递的对象引用是null,Guava 是否提供获取默认值的方法?我正在寻找类似 @​​987654322@ 的东西,如果 objnull,则返回 default .

在 stackoverflow 上我什么也没找到。我只是在寻找纯番石榴解决方案(如果有的话)!

我在 Gauva 10 API 中没有发现任何东西,只有 com.google.common.base.Objects 看起来很有希望,但缺少类似的东西。

【问题讨论】:

    标签: java guava


    【解决方案1】:

    除了Objects.firstNonNull,Guava 10.0 添加了Optional 类作为此类问题的更通用解决方案。

    Optional 可能包含也可能不包含值。有多种方法可以创建 Optional 实例,但对于您的情况,工厂方法 Optional.fromNullable(T) 是合适的。

    拥有Optional 后,您可以使用or 方法之一来获取Optional 包含的值(如果它包含值)或其他值(如果它不包含)。

    综合起来,您的简单示例如下所示:

    T value = Optional.fromNullable(obj).or(defaultValue);
    

    如果您想使用 Supplier 作为默认值(因此除非必要,否则您不会进行计算来获取它)或者如果您想将多个可选值链接在一起,Optional 的额外灵活性就会出现获取出现的第一个值,例如:

    T value = someOptional.or(someOtherOptional).or(someDefault);
    

    【讨论】:

    • 有趣!它可以用于具有不同类型参数的Optional 实例的空安全操作吗?我猜不是,因为它都绑定到 T 的类型?我们必须等待java 8+中的elvis-operator
    • 你是说你想要像Pet pet = Optional.fromNullable(cat).or(Optional.fromNullable(dog)).orNull() 这样的东西,其中CatDog 都扩展了Pet。看起来你必须先将第一个可选参数转换为 Pet,然后你就可以了。
    • 我认为这是一种性能反模式,考虑到它会创建至少一个对象(如果默认值是空数组,可能会创建两个)
    • @DavidBurström:如果您使用的是 Android,那很重要……否则,它很可能不会,或者至少不足以担心。
    • 更新:在 Android 22 上运行表明,如果对象为空,使用 Optional 所花费的时间是执行简单条件的 4 倍。如果对象不为空,则需要 14 倍的时间。如果您还不必要地创建了默认值,则会根据课程类型进一步受到惩罚。
    【解决方案2】:

    怎么样

    MoreObjects.firstNonNull(obj, default)
    

    请参阅JavaDoc

    (历史记录:MoreObjects 类曾经被称为 Objects,但为了避免与 Java 7 中引入的 java.util.Objects 类混淆而对其进行了重命名。Guava Objects 类现在已被有效弃用。)

    【讨论】:

    • 方法名称在我的用例中有点混乱。我想我必须阅读 2 次才能记住我打算获得默认值!但是,嘿,它有效!
    • 现在已弃用,guava doc 建议使用 MoreObjects.firstNonNull(obj, default)
    • @antogerva 谢谢 - 我已经更新了我的答案以推荐更多对象。
    • 请记住,此方法要求任何参数不为空,并且不适合默认可以为空的情况
    【解决方案3】:

    如前所述,Guava 解决方案是正确的。

    然而,Java 8 有一个纯 JDK 解决方案:

    Optional.ofNullable( var ).orElse( defaultValue );
    

    查看java.util.Optional的文档

    【讨论】:

      【解决方案4】:

      这应该可以解决问题:Objects.firstNonNull(o, default)
      guava API doc

      【讨论】:

        【解决方案5】:

        如果你只是在谈论字符串,还有 Apache Commons 的 defaultString 和 defaultIfEmpty 方法

        defaultString 只会为您提供 true null 的默认值,而 defaultIfEmpty 将为您提供 null 或空字符串的默认值。

        还有 defaultIfBlank 即使是空白字符串也会为您提供默认值。

        例如

        String description = "";
        description = StringUtils.defaultIfBlank(description, "Theodore"); 
        

        description 现在将等于“Theodore”

        编辑: Apache Commons 还有一个 ObjectUtils 类,它为完全烘焙的对象执行 null 默认值...

        【讨论】:

          【解决方案6】:

          如果您的对象还不是 Optional,那么 Optional/firstNotNull 建议会使简单的 Java 功能(三元运算符)复杂化:

          T myVal = (val != null) ? val : defaultVal;
          

          包含依赖项和多个方法调用会引入与三元运算符一样多的读取复杂性。我什至会争辩说,使用Optional 与其“我的方法可能会或可能不会返回对象”语义相反,这是一个危险信号,表明您做错了(就像在其他情况下滥用与该事物的语义相反的东西一样意思)。

          有关三元运算符的更多讨论,请参阅http://alvinalexander.com/java/edu/pj/pj010018

          【讨论】:

          • 我认为你说得有道理。但是,如果你想测试一个昂贵的方法返回,可选的解决方案会更好:Optional.ofNullable( superExpensiveMethod() ).orElse( defaultValue ); 使用三元,你必须先把它放在一个变量中。
          【解决方案7】:

          仅供参考,Java 9 有两种方法可以完全满足您的需求:

          public static <T> T requireNonNullElse(T obj, T defaultObj);
          

          还有一个懒惰的版本:

          public static <T> T requireNonNullElseGet(T obj, Supplier<? extends T> supplier)
          

          【讨论】:

            【解决方案8】:

            java.util.Objects 和 Guava 的 optional 确实提供了将 null 覆盖为默认值的好方法……经常使用它们

            但这里有一些更重要的东西:

            public static <T> T firstNotNuLL(T...args){
                for (T arg : args)
                    if ( arg != null) return arg;
                throw new NullPointerException();  
            }
            

            【讨论】:

              【解决方案9】:

              您可以使用来自org.apache.commons.lang3 库的ObjectUtils.defaultIfNull()

              public static <T> T defaultIfNull(T object, T defaultValue)
              

              【讨论】:

                【解决方案10】:

                考虑使用 Guava 10 中内置的 Optional。您可以将多个选项串在一起,例如 Optional.fromNullable(var).orNull()Optional.fromNullable(var).or(Optional.of(var2)).orNull()

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 2013-01-02
                  • 2016-09-29
                  • 1970-01-01
                  • 2021-11-08
                  • 2021-09-09
                  • 1970-01-01
                  • 2019-05-08
                  • 2018-10-04
                  相关资源
                  最近更新 更多