Java中的空安全解除引用如何?在Groovy中使用Maybe monad

时间:2010-05-24 20:41:08

标签: java groovy null nullpointerexception monads

我正在开发一个从Objective C移植到Java的代码库。没有nullchecks的方法链接有几种用法

dog.collar().tag().name()

我正在寻找类似于safe-dereferencing operator的东西?在Groovy而不是nullcheck

dog.collar?.tag?.name

这导致Maybe monad拥有Nothing的概念而不是Null。但是当我访问值时仍然没有解决链接问题的Nothing的所有实现都会抛出异常。我做了Nothing返回一个模拟,它的行为类似于NullObject模式。但它解决了链式问题。

Nothing的实现有什么问题吗?

public class Nothing<T> implements Maybe<T> {

    private Class<T> klass;

    public Nothing(Class<T> klass) {
        this.klass = klass;
    }

    @Override
    public T value() {
        return mock(klass, Mockito.RETURNS_DEEP_STUBS); 
    }
}

据我所知

  1. 在代码中使用模拟库感觉很奇怪
  2. 它不会在第一个空值处停止。
  3. 如何区分null结果,因为空引用或名称实际为空?如何在Groovy代码中区分?

4 个答案:

答案 0 :(得分:7)

我不建议只检查空值。实际上,我建议甚至不要返回null,而是抛出异常。

在任何一种情况下,你都不会通过这种空对象方法更快地制作代码,而且我认为你最终会因为想要复制不同编程语言的特性而混淆某人。我认为你应该适应你正在使用的语言。

答案 1 :(得分:4)

我也喜欢这个运算符,但它不适用于Java - 而且它是一个关于草率代码的止损补丁:如果dog.collar没有标记,它应该分支不同,如果是标签没有名称 - 它可能是一个错误,应该抛出异常。

当你继承你没有写的代码时,并不能解决任何说“代码更好”的问题。

我建议你首先重构你的代码 - 如果这样的代码发生在整个地方,也许它需要被转移到一个集中的函数中。如果dog.getName()委托给dog.collar()获取它的标签,最后是标签的名称,那么你只需要在一个地方修复这个bug(即使它不在领子上,狗也必须有一个名字,所以dog.getName应该能够遍历任何路径来解决你的问题 - 现在再次为了那些糟糕代码的NEXT点再做一次。

每当你看到自己在2个地方修补相同的代码时,就会出现因素问题。如果这只对每组属性发生一次(如果它已经完全分解并且是OO)那么它就不是一个严重的问题,只是几个补丁。

哎呀,这样的代码是不是违反了一些熟悉的规则?

答案 2 :(得分:1)

您可以使用闭包明确地将其实现为monad。

我在遇到你问题的同时遇到了这个问题 http://groovyconsole.appspot.com/script/205001

?对于空检查,安全解除引用显然在语法上更清晰,你可以用?:来结束链接而不是null,例如在这个上下文中的“”。

如果你想了解monad我会建议学习Haskell,然后你自然会开始看到这些概念如何在其他语言中使用。允许可变性的语言,即使功能性(例如Scala)经常展示“不纯”的解决方案而不是纯粹的功能解决方案。

答案 3 :(得分:-1)

Java中没有“安全解除引用”运算符。

我认为这是一件好事,因为“安全解除引用”通常是一种伪装的错误。你基本上有两种可能性:

  • 不应为null 。在这种情况下,null表示您的假设中存在严重错误,如果以某种方式出现null,则应该抛出NullPointerException(这是fail-fast principle
  • 可以为null 。在这种情况下,您通常应该进行一些比“不要调用此方法”更复杂的显式空值处理。您必须考虑:在这种情况下,意味着是什么意思?

就个人而言,我通常会将长方法链视为将您的代码重构为较小的,明确命名的方法(如果需要可以在内部包含正确的空值处理)的提示。在大多数情况下,这可能比引入monad更合理。