Sobrecarga de métodos Java: parámetros genéricos y parámetros dentro del mismo árbol de herencia

Supongamos que tengo el siguiente código:

// Method acception generic parameter
public static <T> T foo(T para) {
    return para;
}

// Method accepting Integer parameter
public static Integer foo(Integer para) {
    return para + 1;
}

// Method accepting Number parameter
public static Number foo(Number para) {
    return para.intValue() + 2;
}

public static void main(String[] args) {
    Float f = new Float(1.0f);
    Integer i = new Integer(1);
    Number n = new Integer(1);
    String s = "Test";

    Number fooedFloat = foo(f);     // Uses foo(Number para)
    Number fooedInteger = foo(i);   // Uses foo(Integer para)
    Number fooedNumber = foo(n);    // Uses foo(Number para)
    String fooedString = foo(s);    // Uses foo(T para)

    System.out.println("foo(f): " + fooedFloat);
    System.out.println("foo(i): " + fooedInteger);
    System.out.println("foo(n): " + fooedNumber);
    System.out.println("foo(s): " + fooedString);
}

La salida tiene el siguiente aspecto:

foo(f): 3
foo(i): 2
foo(n): 3
foo(s): Test

Ahora la (s) pregunta (s):

foo(n) llamadasfoo(Number para), muy probablemente porquen Se define comoNumber, a pesar de que tiene unInteger asignado a ella. Entonces, ¿estoy en lo cierto al suponer que la decisión, cuál de los métodos sobrecargados se toma ocurre en tiempo de compilación, sin enlace dinámico? (Pregunta sobreestático ydinámica Unión)foo(f) usosfoo(Number para), mientrasfoo(i) usosfoo(Integer para). Solamentefoo(s) usa la versión genérica. ¿Entonces el compilador siempre busca si hay una implementación no genérica para los tipos dados, y solo si no, recurre a la versión genérica? (Pregunta sobregenéricos)De nuevo,foo(f) usosfoo(Number para), mientrasfoo(i) usosfoo(Integer para). Todavía,Integer i también sería unNumber. Entonces, ¿se toma siempre el método con el tipo "más externo" dentro del árbol de herencia? (Pregunta sobreherencia)

Sé que estas son muchas preguntas, y el ejemplo no está tomado de un código productivo, pero me gustaría saber qué "sucede detrás" y por qué suceden las cosas.

También cualquier enlace a la documentación de Java o la especificación de Java son realmente apreciados, no pude encontrarlos yo mismo.

Respuestas a la pregunta(3)

Su respuesta a la pregunta