Comme mentionné précédemment, la résolution de surcharge est effectuée au moment de la compilation.
Java Puzzlers a un bel exemple pour cela:
Puzzle 46: Le cas du constructeur déroutant
Ce puzzle vous présente deux constructeurs déroutants. La méthode main invoque un constructeur, mais lequel? La sortie du programme dépend de la réponse. Qu'est-ce que le programme imprime, ou est-il même légal?
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);
}
}
Solution 46: Cas du constructeur déroutant
... Le processus de résolution de surcharge de Java fonctionne en deux phases. La première phase sélectionne toutes les méthodes ou constructeurs accessibles et applicables. La deuxième phase sélectionne le plus spécifique des méthodes ou des constructeurs sélectionnés dans la première phase. Une méthode ou un constructeur est moins spécifique qu'un autre s'il peut accepter des paramètres passés à l'autre [JLS 15.12.2.5].
Dans notre programme, les deux constructeurs sont accessibles et applicables. Le constructeur
Confusing (Object) accepte tout paramètre passé à Confusing (double []) , donc
Confusing (Object) est moins spécifique. (Chaque double tableau est un objet , mais tous les objets ne sont pas un double tableau .) Le constructeur le plus spécifique est donc Confus (double []) , ce qui explique la sortie du programme.
Ce comportement est logique si vous transmettez une valeur de type double [] ; il est contre-intuitif si vous passez null . La clé pour comprendre ce puzzle est que le test pour lequel la méthode ou le constructeur est le plus spécifique n'utilise pas les paramètres réels : les paramètres apparaissant lors de l'invocation. Ils ne sont utilisés que pour déterminer les surcharges applicables. Une fois que le compilateur a déterminé quelles surcharges sont applicables et accessibles, il sélectionne la surcharge la plus spécifique, en utilisant uniquement les paramètres formels: les paramètres apparaissant dans la déclaration.
Pour appeler le constructeur Confusing (Object) avec un paramètre null , écrivez new Confusing ((Object) null) . Cela garantit que seul Confusing (Object) est applicable. Plus généralement, pour forcer le compilateur à sélectionner une surcharge spécifique, transtypez les paramètres réels en types déclarés des paramètres formels.