2017-10-19 34 views
0

Je vous écris quelques tests JUnit dans Android, et si je fais ceci:appel de méthode avec Ambigu Entier

public void testSetId(){ 
    Friend friend = new Friend(5); 
    assertEquals(5,friend.getId()); 
} 

je reçois une erreur d'appel de méthode ambiguë.

Appel de méthode Ambigu: Les deux assertEquals (int, int) et assertEquals (Object, Object) correspondent

Pourtant, si je fais ceci:

public void testSetId(){ 
    Integer ID = 5; 
    Friend friend = new Friend(ID); 
    assertEquals(ID, friend.getId()); 
} 

Il fonctionne. Je pense que la deuxième fonction devrait faire exactement la même chose.

Que se passe-t-il ici?

+1

Avez-vous défini le 'id' de 'Friend' être un' int' ou un 'Integer'? – GriffeyDog

+0

L'ID est un entier – user2782067

+0

Pouvez-vous confirmer que le type de retour de getId() est Integer non int? –

Répondre

2

Avant Java 5, il n'y avait aucun autoboxing ou auto-déballage. Cela signifie que si une méthode foo avait un paramètre de type Integer, ce qui suit ne compile pas

foo(5); // 5 needs to be autoboxed 

De même, si une méthode bar avait un paramètre de type int, cela ne compile pas

bar(new Integer(5)); // The Integer needs to be unboxed 

Lorsque l'autoboxing et l'auto-unboxing ont été introduits, il était essentiel que le code existant continue à fonctionner exactement de la même manière qu'avant. Par conséquent, lorsque le compilateur décide quelle méthode est appelée, il ne considère d'abord que les méthodes applicables qui ne nécessitent pas d'autoboxing ou d'auto-unboxing. Ce n'est que s'il n'y a pas de telles méthodes que le compilateur considère les méthodes nécessitant un autoboxing et/ou un auto-unboxing.

Depuis getId retourne un Integer, la méthode Object, Object peut être appelée sans autoboxing dans le cas où le premier argument est également un Integer. Cependant, la méthode int, int ne peut être appelée que par désintoxication automatique du second paramètre. Par conséquent, dans votre deuxième exemple, la surcharge Object, Object est sélectionnée lors du premier passage. Dans votre premier exemple, vous essayez de passer un int et un Integer. La méthode int, int s'applique uniquement en dés-déballant automatiquement le second argument, tandis que la méthode Object, Object s'applique uniquement en décochant automatiquement le premier argument. Par conséquent, la surcharge ne peut pas être choisie lors du premier passage, et comme aucune méthode n'est plus spécifique que l'autre (vous aurez besoin de regarder ce dernier bit), le compilateur ne peut pas choisir entre les deux méthodes.

La résolution de surcharge est extrêmement compliquée, et je l'ai simplifiée un peu (il y a aussi des règles impliquant var-args). Cependant, dans la pratique, vous n'avez pas besoin d'apprendre toutes ces règles - si jamais vous devez dire au compilateur quelle méthode vous pouvez appliquer toujours inclure un casting ou explicite des moulages:

assertEquals((Integer) id, friend.getId());