1

To illustrate the following example I created a litte spock test (but it's about groovy itself, not spock):

void "some spock test"() {
    given: String value = null
    expect: someMethod(value) == 3
}

int someMethod(String s) {
    return 3
}
int someMethod(Map s) {
    return 5
}

There are two methods who's signatures only differ by the type of the given parameter. I thought that when I give it a null value that is explicitly typed as a string, the string-method will be called. But that doesn't happen; the test fails, because the map-method is called! Why?

I guess groovy ignores the type and treats all nulls the same. There seems to be some kind of priority of types: When I use Object instead of Map as the parameter type of the wrong-method, its all the same, but when I for instance use Integer, the test succeeds. But than again: If groovy really ignores the type of nulls, why can the following fix the original test:

expect: someMethod((String) value) == 3
Francois Bourgeois
  • 3,650
  • 5
  • 30
  • 41
  • http://stackoverflow.com/questions/14518573/what-overloaded-method-is-chosen-by-groovy-when-null-is-passed-as-a-parameter – tim_yates Sep 01 '15 at 11:15
  • @tim_yates: thx. I know this one, but there the null has no type, so its clear why groovy doesn't know which method to call. – Francois Bourgeois Sep 01 '15 at 11:21
  • I believe the same rule applies, as the type is discarded unless you're using CompileStatic – tim_yates Sep 01 '15 at 12:16
  • 3
    eg, try: `String a = null ; println a.getClass()` You should get `class org.codehaus.groovy.runtime.NullObject`, not `java.lang.String` – tim_yates Sep 01 '15 at 12:45

1 Answers1

1

If you read my answer to the question Tim already mentioned you will see that I talk there about runtime types. The static type plays normally no role in this. I also described there how the distance calculation is used and that for null the distance to Object is used to determine the best fitting method. What I did not mention is that you can force method selection by using a cast. Internally Groovy will use a wrapper for the object, that also transports the type. Then the transported type is used instead. But you surely understand, that this means a one additional object creation per method class, which is very inefficient. Thus it is not the standard. In the future Groovy maybe change to include that static type information, but this requires a change to the MOP as well. And that is difficult

Community
  • 1
  • 1
blackdrag
  • 6,413
  • 2
  • 26
  • 38