当null作为参数传递时,Groovy选择了什么重载方法?

时间:2013-01-25 09:09:26

标签: groovy

class SimpleTest {
    void met( Object a ) {
        println "Object"
    }

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

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

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

1 个答案:

答案 0 :(得分:8)

Groovy使用距离计算方法。基本上,如果您将类和接口想象为图中的节点并且它们通过它们的继承关系连接,那么我们可以查找从给定参数类型(参数的运行时类型)到参数类型(静态)的距离输入方法参数has)。连接有不同的权重,基本上去超级意味着我想3的距离,到一个接口1,包裹一个原语也是1,vargs包装也有一个权重(并且不能真正在图中表示,所以对不起失败的图片感到抱歉)

如果为null,则无法正常工作。这里我们看一下参数类型与Object的距离。虽然非空情况是最可能的特殊方法,但我们对null部分采用最常规的方法。在Java中,您通常会使用静态类型或使用强制转换来确保要选择的内容。在Groovy中,我们没有静态类型,并且通常无法正确地确定最特殊的类型。因此,我们决定采用最通用的方法来代替那种情况。它总的来说效果很好。

然后,对象有点像后备,允许您集中空处理。在将来的版本中,我们可能允许使用显式null类型,如果存在,那么它将优先于Object。

虽然您经常可以直接看到类的距离方法,但接口更复杂一些。基本上算法是这样的:如果我当前的类直接实现了我们正在寻找的接口,那么它与距离1匹配。如果该类实现的任何接口具有我们寻找的接口作为父接口,那么计算“跳“直到我们在那里作为距离。但我们寻找最短的距离。所以我们在超级课上也看起来一样。来自那里的任何搜索结果将具有该距离+1(对于超类跳)。如果超类搜索提供的距离比实现接口上的搜索距离短,则将采用超类搜索结果。

至于使用接口处理null ...如果接口没有扩展另一个,则到Object的距离为1。如果是,则是父接口+1的距离。如果扩展了多个接口,则它是最短的路径。

让我们看看List和Integer为null List extends Collection,Collection extend Iterable,Iterable没有父级。这使得Iterable的距离为1,Collection的距离为1,最后是List的距离为3。 整数扩展Number,Number extends Object。由于我们跳了两次,我们这里的距离为6(2x3),比其他情况大得多。是的,这意味着我们通常更喜欢接口。我们实际上是出于实际原因这样做,因为这种方式证明是最接近实际的编程实践。