当null作为参数传递时,Groovy选择哪种重载方法?

当null作为参数传递时,Groovy选择哪种重载方法?,groovy,Groovy,此代码将生成输出“Object”。它不会选择最专门的方法版本。在这种情况下,字符串比对象更专业化,因此此规则不适用。Groovy使用距离计算方法。基本上,如果您将类和接口想象成图中的节点,并通过它们的继承关系将它们连接起来,那么我们可以查找从给定参数类型(参数的运行时类型)到参数类型(方法参数具有的静态类型)的距离。连接有不同的权重,基本上到超类意味着距离为3,到接口1,换行一个原语也是1,vargs换行也有一个权重(并且不能再在图中表示了,因此对于稍微失败的图像表示抱歉) 如果为空,这当然不能

此代码将生成输出“Object”。它不会选择最专门的方法版本。在这种情况下,字符串比对象更专业化,因此此规则不适用。

Groovy使用距离计算方法。基本上,如果您将类和接口想象成图中的节点,并通过它们的继承关系将它们连接起来,那么我们可以查找从给定参数类型(参数的运行时类型)到参数类型(方法参数具有的静态类型)的距离。连接有不同的权重,基本上到超类意味着距离为3,到接口1,换行一个原语也是1,vargs换行也有一个权重(并且不能再在图中表示了,因此对于稍微失败的图像表示抱歉)

如果为空,这当然不能工作。这里我们看的是参数类型到对象的距离。虽然none-null是最可能的特殊方法,但对于null部分,我们采用的是最通用的方法。在Java中,您通常会使用静态类型或使用强制转换来确保要选择的内容。在Groovy中,我们没有静态类型,通常无法正确确定最特殊的类型。因此,我们决定采用最通用的方法,而不是这种情况。总的来说,它工作得很好

对象则有点像回退,它允许您进行中心空处理。在未来的版本中,我们可能会允许使用显式null类型,如果存在,则会优先使用该类型

虽然您通常可以直接看到类的距离方法,但接口的距离方法要复杂一些。基本上算法是这样的:如果我当前的类直接实现了我们正在寻找的接口,那么它与距离1匹配。如果类实现的任何接口都有我们作为父接口寻找的接口,那么计算“跳数”,直到我们达到距离为止。但是我们寻找最短的距离。因此,我们也以同样的方式看待超级课堂。那里的任何搜索结果都将具有该距离+1(对于超级类跳跃)。如果超级类搜索给出的距离比实现接口上的搜索短,则将取而代之的是超级类搜索结果

至于用接口处理null。。。如果接口不延伸另一个,则到对象的距离为1。如果是,则是父接口的距离+1。如果扩展了多个接口,那么它也是最短路径

让我们看看空值的列表和整数。
列表扩展集合,集合扩展Iterable,Iterable没有父级。这使得Iterable的距离为1,Collection的距离为2,List的距离为3。
整数扩展数字,数字扩展对象。因为我们跳了两次,所以这里的距离是6(2x3),比另一种情况大得多。是的,这意味着通常我们更喜欢界面。实际上,我们这样做是出于实际原因,因为这种方式被证明最接近实际编程实践。

可能重复感谢您的回答。我从对这个问题的回答中理解了如何安全地处理可能为空的参数。然而,我只是想知道Groovy实际上是如何选择这个方法的,我认为Groovy选择了MethodForInteger和List的最不专业的版本。对于整数和字符串,它选择字符串。为什么一种类型比另一种更专业化/最少专业化?:)Jochen在这里发布了一个类似问题的答案
class SimpleTest {
    void met( Object a ) {
        println "Object"
    }

    void met( String b ) {
        println "String"
    }

    static main( args ) {
        SimpleTest i = new SimpleTest()
        i.met(null)
    }
}