De façon analogue aux constructeurs, il est fréquent que plusieurs méthodes d'une classe portent le même nom, chacune ayant soit un nombre d'arguments distinct, soit le même nombre d'arguments, mais des types distincts : on dit que ces méthodes n'ont pas le même profil . On parle dans ce cas de surcharge du nom. Par exemple, le nom translater est surchargé dans l'exemple suivant, où deux méthodes portent le même nom :
class Point { // ... void translater(double dx, double dy) { x = x + dx; // this.x = this.x + dx y = y + dy; } void translater(double d) { translater(d, d); } }
Les profils de ces deux méthodes sont respectivement :
Le compilateur est capable de déterminer laquelle de ces méthodes homonymes doit être invoquée, en se basant uniquement sur le nombre et le type des expressions arguments : c'est ce que l'on appelle la résolution de la surcharge. Quand il y a plusieurs méthodes candidates, c'est la plus spécifique qui est sélectionnée. Dans l'exemple suivant,
class Test { static void p(int x) { System.out.println("int"); } static void p(long x) { System.out.println("long"); } public static void main(String[] args) { p(1); // --> "int" p(1L); // --> "long" } }les deux méthodes p(int) et p(long) sont candidates pour l'expression p(1), parce que 1 est de type int et que int est un sous-type de long. Cependant, la méthode p(int) est plus spécifique que p(long) puisque tout argument accepté par la première est accepté par la seconde, mais pas réciproquement (ce qui provient du fait que int est un sous-type de long mais que long n'est pas un sous-type de int). C'est donc p(int) qui est sélectionnée. Dans le cas de l'expression p(2L), l'argument est un long, donc seule la méthode p(long) est candidate.
Un programme pour lequel cette résolution ne serait pas possible est incorrect : cette erreur est détectée par le compilateur. Dans l'exemple suivant, l'expression p(1, 2) a deux arguments de type int et il y a deux méthodes candidates : p(int, long) et p(long, int).
class Test { static void p(int x, long y) { System.out.println("IL"); } static void p(long x, int y) { System.out.println("LI"); } public static void main(String[] args) { p(1, 2); // ERREUR : AMBIGU } }
Chacune pourrait être invoquée puisque int est un sous-type de long, mais aucune n'est plus spécifique que l'autre.
Notons que le type de retour de la méthode n'est pas pris en considération dans la résolution de la surcharge. Enfin, deux méthodes de même nom ne peuvent pas être définies avec le même profil et des types de retour différents. Ce n'est pas une surcharge, c'est une erreur :
void f(int x) { ... } // ERREUR int f(int x) { ... } // ERREUR
C'est également une erreur de redéfinir une méthode avec le même profil en changeant simplement le nom des paramètres, car le nom des paramètres n'est pertinent que dans le corps de la méthode :
void f(int x) { ... } // ERREUR void f(int y) { ... } // ERREUR
Toutes ces erreurs sont détectées par le compilateur.