Como mencionado antes, a resolução de sobrecarga é executada em tempo de compilação.
Java Puzzlers tem um bom exemplo para isso:
Quebra-cabeça 46: O Caso do Construtor Confuso
Este quebra-cabeça apresenta dois construtores confusos. O método principal invoca um construtor, mas qual? A saída do programa depende da resposta. O que o programa imprime ou é mesmo legal?
public class Confusing {
private Confusing(Object o) {
System.out.println("Object");
}
private Confusing(double[] dArray) {
System.out.println("double array");
}
public static void main(String[] args) {
new Confusing(null);
}
}
Solução 46: Caso do Construtor Confuso
... O processo de resolução de sobrecarga do Java opera em duas fases. A primeira fase seleciona todos os métodos ou construtores que são acessíveis e aplicáveis. A segunda fase seleciona o mais específico dos métodos ou construtores selecionados na primeira fase. Um método ou construtor é menos específico do que outro se pode aceitar quaisquer parâmetros passados para o outro [JLS 15.12.2.5].
Em nosso programa, ambos os construtores são acessíveis e aplicáveis. O construtor
Confusing (Object) aceita qualquer parâmetro passado para Confusing (double []) , portanto,
Confusing (Object) é menos específico. (Cada matriz dupla é um objeto , mas nem todo objeto é uma matriz dupla .) O construtor mais específico é, portanto, Confuso (double []) , o que explica a saída do programa.
Este comportamento faz sentido se você passar um valor do tipo double [] ; é contra-intuitivo se você passar null . A chave para entender este quebra-cabeça é que o teste para qual método ou construtor é mais específico não usa os parâmetros reais : os parâmetros que aparecem na invocação. Eles são usados apenas para determinar quais sobrecargas são aplicáveis. Uma vez que o compilador determina quais sobrecargas são aplicáveis e acessíveis, ele seleciona a sobrecarga mais específica, usando apenas os parâmetros formais: os parâmetros que aparecem na declaração.
Para invocar o construtor Confusing (Object) com um parâmetro nulo , escreva novo Confusing ((Object) null) . Isso garante que apenas Confuso (Objeto) seja aplicável. Mais geralmente, para forçar o compilador a selecionar uma sobrecarga específica, lance os parâmetros reais para os tipos declarados dos parâmetros formais.