148 votes

Surcharge de la méthode pour l'argument nul

J'ai ajouté trois méthodes avec des paramètres :

public static  void doSomething(Object obj) {
    System.out.println("Object called");
}

public static  void doSomething(char[] obj) {
    System.out.println("Array called");
}

public static  void doSomething(Integer obj) {
    System.out.println("Integer called");
}

Quand j'appelle doSomething(null) alors le compilateur envoie une erreur comme méthodes ambiguës . Il en va de même parce que Integer y char[] méthodes ou Integer y Object méthodes ?

3 votes

Il suffit de changer le Integer a int .

2 votes

@Mudassir : et qu'est-ce que cela résoudrait exactement ?

2 votes

@Joachim Sauer : Si on change Integer en int, alors null n'est pas référencé aux types primitifs en Java, donc le compilateur ne lancera pas d'erreur.

237voto

Joachim Sauer Points 133411

Java essaiera toujours d'utiliser la version applicable la plus spécifique d'une méthode qui est disponible (cf. JLS §15.12.2 ).

Object , char[] y Integer peuvent tous prendre null comme une valeur valide. Par conséquent, les 3 versions sont applicables, donc Java devra trouver la plus spécifique.

Depuis Object est le super-type de char[] la version tableau est plus spécifique que la version Object -version. Ainsi, si seules ces deux méthodes existent, la char[] sera choisie.

Lorsque les deux char[] y Integer sont disponibles, alors les deux d'entre eux sont plus spécifiques que Object mais aucune n'est plus spécifique que l'autre, donc Java ne peut pas décider laquelle appeler. Dans ce cas, vous devrez mentionner explicitement celle que vous voulez appeler en coulant l'argument dans le type approprié.

Notez qu'en pratique, ce problème se produit beaucoup plus rarement qu'on ne le pense. La raison en est qu'il ne se produit que lorsque vous appelez explicitement une méthode avec la fonction null ou avec une variable d'un type assez peu spécifique (telle que Object ).

Au contraire, l'invocation suivante serait parfaitement dépourvue d'ambiguïté :

char[] x = null;
doSomething(x);

Bien que vous passiez toujours la valeur null En effet, Java sait exactement quelle méthode appeler, puisqu'il tient compte du type de la variable.

1 votes

Ceci est indiqué pour Java 7. Est-ce que cela s'applique également aux versions précédentes de Java ? Je veux dire : Si vous avez plusieurs signatures de méthodes avec des paramètres uniquement le long d'une hiérarchie de types, alors vous êtes en sécurité avec null comme valeur réelle ? Et si vous avez construit une "hiérarchie pour" comme dans l'exemple ici, alors vous ne l'êtes pas ?

4 votes

Je suis presque sûr que ces règles sont les mêmes pour au moins tout ce qui existe depuis Java 1.1 (sauf pour l'ajout des génériques, évidemment).

1 votes

Cela signifie-t-il que si le compilateur devait choisir entre doSomething(String str) et doSomething(Object obj) pendant l'exécution avec doSomething(null), doSomething(String str) sera appelé.

47voto

jmg Points 4146

Chaque paire de ces trois méthodes est ambiguë en soi lorsqu'elle est appelée avec une méthode de type null argument. Parce que chaque type de paramètre est un type de référence.

Voici les trois façons d'appeler une de vos méthodes spécifiques avec null.

doSomething( (Object) null);
doSomething( (Integer) null);
doSomething( (char[]) null);

Je me permets de suggérer de lever cette ambiguïté si vous prévoyez d'appeler ces méthodes à l'aide de null arguments. Une telle conception invite à commettre des erreurs à l'avenir.

1 votes

Seulement Integer - char[] est ambiguë, car dans les deux autres cas, le compilateur Java peut choisir le choix le plus spécifique, comme @JoachimSauer l'a décrit.

2 votes

@kajacx : La question originale de l'OP concernait l'appel de ces méthodes avec null comme paramètre. Sous cette condition préalable, les trois paires sont ambiguës. Pour le cas général, je suis d'accord que seul Integer - char[] est ambiguë.

0 votes

Qu'en est-il doSomething(null) pour public static void doSomething(String str) { System.out.println("String called"); } Cela renverra la chaîne appelée.

6voto

Lars Noschinski Points 2619

null est une valeur valide pour l'un des trois types ; le compilateur ne peut donc pas décider de la fonction à utiliser. Utilisez quelque chose comme doSomething((Object)null) o doSomething((Integer)null) à la place.

0 votes

J'ai supprimé la méthode avec le paramètre Integer, elle invoque la fonction et renvoie la sortie sous la forme suivante "Array Called" alors quel est le contrat entre Tableau et objet ?

3 votes

Les tableaux Java sont également des objets.

2voto

Ankit Points 1523

Toutes les classes de Java étendent la classe Object, même la classe Integer étend aussi Object. Par conséquent, les deux classes Object et Integer sont considérées comme des instances Object. Ainsi, lorsque vous passez null comme paramètre, le compilateur ne sait pas quelle méthode objet appeler, c'est-à-dire avec le paramètre Object ou le paramètre Integer, car ils sont tous deux des objets et leur référence peut être nulle. Mais les primitives en Java n'étendent pas Object.

1voto

Jafar Ali Points 86

J'ai essayé cela et lorsqu'il y a exactement une paire de méthodes surchargées et que l'une d'entre elles a un paramètre de type Object, le compilateur sélectionne toujours la méthode avec le type le plus spécifique. Mais quand il y a plus d'un type spécifique, alors le compilateur lance une erreur de méthode ambiguë.

Puisqu'il s'agit d'un événement de compilation, cela ne peut se produire que si l'on passe intentionnellement null à cette méthode. Si cela est fait intentionnellement, il est préférable de surcharger à nouveau cette méthode sans paramètre ou de créer une autre méthode.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X