RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 600917
Accepted
pegoopik
pegoopik
Asked:2020-12-08 12:54:43 +0000 UTC2020-12-08 12:54:43 +0000 UTC 2020-12-08 12:54:43 +0000 UTC

嵌套很大时避免 NullPointerException 的最佳方法是什么?

  • 772

大嵌套是指以下形式的代码:

param = foo.getSomthing1().getSomthig2().getSomthing3() ...

从而在每次通话中都能起飞NullPointerException。一个很好的例子是从 XSD 架构生成的类。我需要拉出并分配一些值,如果null途中至少有一个缺失节点(在 Java 中),我需要分配null.

一种选择是以下if形式:

if (foo != null && foo.getSomthing1() != null && ....) {
    param = foo.getSomthing1().getSomthig2().getSomthing3() ...
}

这使得代码不可读。将根据 XSD 类模式生成的对象简单地转换为平面 Java 结构看起来很糟糕。

有一个选项可以放入try catch:) 但它看起来会更糟,更不用说性能了。

我听说过运算符?., ?:, ?[],但我无法让它们在本地工作,否则这将是一个有趣的解决方案:

param = foo?.getSomthing1()?.getSomthig2()?.getSomthing3() ...

UPD:选项 c?.取自非权威来源。我的意思可能是 C#。

告诉我,还有什么办法?

java
  • 8 8 个回答
  • 10 Views

8 个回答

  • Voted
  1. Best Answer
    V. Makhnutin
    2020-12-08T18:31:28Z2020-12-08T18:31:28Z

    有这样一个选项,但仅适用于 Java 8:

    private Optional<String> get(First first) {
        return Optional.ofNullable(first.getSecond())
                .map(Second::getThird)
                .map(Third::getFourth)
                .map(Fourth::getString);
    }
    

    假设我们有一个类First,它又包含一个带有类Second的字段,该类包含Third,其中包含我们需要的字段Fourth,让它成为String。

    因此,为了从Fourth获取字符串,给定First类的一个实例,我们需要以下构造String someString = first.getSecond().getThird().getFourth().getString()。

    有了上面的方法,我们做以下事情: String someString = get(first).orElse(null);

    如果其中一个嵌套类结果为null,那么我们只需 get someString = null,或者您可以指定默认值而不是null 。

    评论

    我们正在谈论使用 Java 8 中引入的特殊Optional类。对于 Java 7,您可以使用Google Guava - 也有一个类似的类Optional

    • 30
  2. Suvitruf - Andrei Apanasik
    2020-12-08T13:10:46Z2020-12-08T13:10:46Z

    Optional您还可以使用ifPresent:

    例如,如果有这样一个类:

    public class TestClass{
    
        public Optional<TestClass> getSomthing1(){
            return Optional.of(this);
        }
    
        public Optional<TestClass> getSomthing2(){
            return Optional.of(this);
        }
    }
    

    可以这样使用:

    TestClass test = new TestClass();
    test.getSomthing1().ifPresent(t -> t.getSomthing2());
    

    也就是说,我们将返回值包装在Optional.

    PS 它仅适用于 Java 8

    • 12
  3. androschuk
    2020-12-12T15:34:01Z2020-12-12T15:34:01Z

    有一种设计模式叫做Null object

    在以下情况下推荐使用此设计模式:

    • 一个对象需要与其他对象交互。空对象不建立新的交互——它使用已经建立的交互。
    • 一些交互对象必须是空闲的
    • 需要与具有 NULL 值的对象进行“通信”的抽象。

    同样关于这个主题,您可以观看来自Yegor Bugaenko (eng) 的示例视频。

    这种方法的主要缺点是创建的 Null 对象类的数量。

    • 7
  4. ygun
    2020-12-14T20:33:12Z2020-12-14T20:33:12Z

    如果你决定使用 try/catch,你可以创建一个静态辅助方法:

    public class Util {
      public static <T> T nullIfNPE(Supplier<T> f) {
          try {
              return f.get();
          } catch (NullPointerException e) {
              return null;
          }
      }
    }
    

    像这样使用:

    String param = Util.nullIfNPE(() -> foo.getSomthing1().getSomthig2());
    

    如果你静态导入这个方法,那么甚至像这样:

    String param = nullIfNPE(() -> foo.getSomthing1().getSomthig2());
    

    很简洁=)

    • 4
  5. Arch
    2020-12-12T16:03:07Z2020-12-12T16:03:07Z

    三元运算符的工作原理如下。

    ComplexityObjectRef cObj;
    
    String res = cObj.getFirst() == null ? "message for this cond" : 
    cObj.getFirst().getSecond() == null ? "message for this cond" : 
    cObj.getFirst().getSecond().getThird() == null ? "message for this cond" : 
    cObj.getFirst().getSecond().getThird().getResult();
    

    此类检查的代码很多,但可读性和可理解性很强,对于Java 7及以下版本使用三元运算符是一个完全可以接受的选择。

    • 2
  6. Artem Konovalov
    2020-01-13T21:09:13Z2020-01-13T21:09:13Z

    写了一个解决问题的小包装器NullPointerException

    public static class NPEChecker<T> {
        public final T value;
    
        public NPEChecker(T value) {
            this.value = value;
        }
    
        public <R> NPEChecker<R> invoke(Function<T, R> function) {
            if (value == null)
                return new NPEChecker<>(null);
    
            R result = function.apply(value);
            return new NPEChecker<>(result);
        }
    }
    

    在它的帮助下,表单的构建:

    AnnotatedType[] result = Solution.class
                    .getAnnotatedInterfaces()
                    .getClass()
                    .getAnnotatedInterfaces();
    

    转换为以下内容:

    AnnotatedType[] result = new NPEChecker<>(Solution.class)
                .invoke(Class::getAnnotatedInterfaces)
                .invoke(AnnotatedType[]::getClass)
                .invoke(Class::getAnnotatedInterfaces)
                .value;
    
    • 1
  7. Максим
    2020-12-15T06:20:58Z2020-12-15T06:20:58Z

    当然,我可能是错的,或者不理解问题的本质,但我找到了一个比建议的更简单的解决方案:

    public class MainClass {
    
        public static void main(String[] args) {
            String param;
            try {
                param= String.valueOf(foo.q().w().e().r().t());
            } catch (Exception ignored) { 
                param= "null"; 
            }
            System.out.println(param);
        }
    
        private MainClass q() {
            return new MainClass();
        }
    
        private MainClass w() {
            return new MainClass();
        }
    
        private MainClass e() {
            return new MainClass();
        }
    
        private MainClass r() {
            return null;
        }
    
        private MainClass t() {
            return new MainClass();
        }
    
    }
    

    很多代码,以便在必要时进行就绪检查,但实际上,解决方案是这样的:

    String param;
    try {
        param = String.valueOf(foo.q().w().e().r().t());
    } catch (Exception ignored) {
        param = "null";
    }
    
    • -2
  8. Ihor Dobrovolskyi
    2020-12-16T16:01:05Z2020-12-16T16:01:05Z

    也许是最简单和最容易理解的方法:

    try {
        param = foo.getSomething1().getSomething2()...;
    } catch (NullPointerException e) {
        param = null;
    }
    

    希望这能解决您的问题。

    • -2

相关问题

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    如何停止编写糟糕的代码?

    • 3 个回答
  • Marko Smith

    onCreateView 方法重构

    • 1 个回答
  • Marko Smith

    通用还是非通用

    • 2 个回答
  • Marko Smith

    如何访问 jQuery 中的列

    • 1 个回答
  • Marko Smith

    *.tga 文件的组重命名(3620 个)

    • 1 个回答
  • Marko Smith

    内存分配列表C#

    • 1 个回答
  • Marko Smith

    常规赛适度贪婪

    • 1 个回答
  • Marko Smith

    如何制作自己的自动完成/自动更正?

    • 1 个回答
  • Marko Smith

    选择斐波那契数列

    • 2 个回答
  • Marko Smith

    所有 API 版本中的通用权限代码

    • 2 个回答
  • Martin Hope
    jfs *(星号)和 ** 双星号在 Python 中是什么意思? 2020-11-23 05:07:40 +0000 UTC
  • Martin Hope
    hwak 哪个孩子调用了父母的静态方法?还是不可能完成的任务? 2020-11-18 16:30:55 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    user207618 Codegolf——组合选择算法的实现 2020-10-23 18:46:29 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    Arch ArrayList 与 LinkedList 的区别? 2020-09-20 02:42:49 +0000 UTC
  • Martin Hope
    iluxa1810 哪个更正确使用:if () 或 try-catch? 2020-08-23 18:56:13 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5