Comportamiento inesperado con métodos sobrecargados.

Estoy un poco confundido sobre el comportamiento de la sobrecarga del método Groovys: dada la clase y las pruebas a continuación, estoy bastante bien contestAStringNull ytestBStringNull lanzar excepciones de llamada de método ambiguas, pero ¿por qué no es el caso paratestANull ytestBNull ¿entonces?

Y, mucho más importante: ¿por quétestBNull(null) llamadaString foo(A arg)? Supongo que el objeto no sabe sobre el tipo de variable a la que está vinculado, pero ¿por qué esa llamada no es ambigua a groovy mientras que las otras lo son?

(Espero haberlo explicado lo suficiente, me duele la cabeza al generar este ejemplo mínimo).

class Foo {
    static class A {}
    static class B {}

    String foo(A arg) { return 'a' }

    String foo(String s, A a) { return 'a' }

    String foo(B arg) { return 'b' }

    String foo(String s, B b) { return 'b' }
}

Pruebas:

import org.junit.Test
import Foo.A
import Foo.B

class FooTest {
    Foo foo = new Foo()

    @Test
    void testA() {
        A a = new A()
        assert foo.foo(a) == 'a'
    }

    @Test
    void testAString() {
        A a = new A()
        assert foo.foo('foo', a) == 'a'
    }

    @Test()
    void testANull() {
        A a = null
        assert foo.foo(a) == 'a'
    }

    @Test
    void testAStringNull() {
        A a = null
        assert foo.foo('foo', a) == 'a'
    }

    @Test
    void testB() {
        B b = new B()
        assert foo.foo(b) == 'b'
    }

    @Test
    void testBString() {
        B b = new B()
        assert foo.foo('foo', b) == 'b'
    }

    @Test
    void testBNull() {
        B b = null
        assert foo.foo(b) == 'b'
    }

    @Test
    void testBStringNull() {
        B b = null
        assert foo.foo('foo', b) == 'b'
    }

}

Respuestas a la pregunta(1)

Su respuesta a la pregunta