25 votes

Surcharge des méthodes et choix du type le plus spécifique

L'exemple de code est le suivant :

    public class OverloadingTest {

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

       public static void test(String obj){
           System.out.println("String called");
       }

       public static void main(String[] args){
           test(null);
           System.out.println("10%2==0 is "+(10%2==0));
           test((10%2==0)?null:new Object());
           test((10%2==0)?null:null);
   }

Et la sortie est :

Chaîne appelée
10%2==0 est vrai
Objet appelé
Chaîne appelée

Le premier appel à test(null) invoque la méthode avec String argument, ce qui est compréhensible d'après The Java Language Specification .

1) Quelqu'un peut-il m'expliquer sur quelle base test() est invoqué dans les appels précédents ?

2) De nouveau, lorsque nous mettons , disons a if condition :

    if(10%2==0){
        test(null);
    }
    else
    {
        test(new Object());
    }

Il invoque toujours la méthode avec String argument .

Le compilateur calculera-t-il l'expression (10%2) lors de la compilation ? Je veux savoir si les expressions sont calculées à la compilation ou à l'exécution. Merci de votre compréhension.

24voto

Hauke Ingmar Schmidt Points 7884

Java utilise la liaison anticipée. La méthode la plus spécifique est choisie au moment de la compilation. La méthode la plus spécifique est choisie en fonction du nombre et du type de paramètres. Le nombre de paramètres n'est pas pertinent dans ce cas. Il nous reste donc le type de paramètres.

Quel est le type des paramètres ? Les deux paramètres sont des expressions, utilisant l'opérateur conditionnel ternaire. La question se réduit à : Quel type l'opérateur ternaire conditionnel renvoie-t-il ? Le type est calculé au moment de la compilation.

Les deux expressions sont données :

(10%2==0)? null : new Object(); // A
(10%2==0)? null : null; // B

Les règles d'évaluation des types sont énumérées aquí . En B c'est facile, les deux termes sont exactement les mêmes : null sera renvoyée ( quel qu'en soit le type ) (JLS : "Si les deuxième et troisième opérandes ont le même type (qui peut être le type null), alors c'est le type de l'expression conditionnelle"). Dans A le second terme est issu d'une classe spécifique. Comme il s'agit d'un terme plus spécifique et plus null peut être remplacé par un objet de la classe Object le type de l'expression entière est Object (JLS : "Si l'un des deuxième et troisième opérandes est de type null et que le type de l'autre est un type de référence, alors le type de l'expression conditionnelle est ce type de référence").

Après l'évaluation du type des expressions, la sélection de la méthode est conforme aux attentes.

L'exemple avec if que vous donnez est différente : vous appelez les méthodes avec des objets de deux différents types. L'opérateur conditionnel ternaire est toujours évalué à un type à temps de compilation qui correspond aux deux termes.

3voto

assylias Points 102015

JLS 15.25 :

Le type d'une expression conditionnelle est déterminé comme suit :

[...]

  • Si l'un des deuxième et troisième opérandes est du type null est un type de référence, alors le type de l'expression conditionnelle est cette référence type.

[...]

Le type de

10 % 2 == 0 ? null : new Object();

est un objet.

2voto

Banthar Points 9141
test((10%2==0)?null:new Object());

Est identique à :

Object o;

if(10%2==0)
    o=null;
else
    o=new Object();

test(o);

Étant donné que le type de o es Object (tout comme le type de (10%2==0)?null:new Object() ) test(Object) sera toujours appelé. La valeur de o n'a pas d'importance.

1voto

MJM Points 1962

Votre réponse est : Temps d'exécution parce que dans le runtime, le paramètre spécifié est une instance de String ou non, donc dans le compile-time ne peut pas trouver cela.

1voto

C'est une question très intéressante.

Permettez-moi d'essayer de clarifier le code que vous avez écrit ci-dessus.

  • Dans votre premier appel de méthode

test(null) ;

Dans ce cadre, le null sera converti en chaîne de caractères, de sorte que l'appel à la fonction test(String obj) Selon JLS, vous êtes convaincu de l'utilité de l'appel.

  • Dans le deuxième appel de méthode

test((10%2==0)?null:new Object()) ;

qui va retourner la valeur booléenne "true". La première valeur booléenne "true" va donc être auto-calculée dans l'objet de la classe Boolean Wrapper. L'objet Boolean Wrapper trouve la meilleure correspondance avec votre objet new Object() dans l'opérateur ternaire. La méthode est appelée avec Object en tant que paramètre, ce qui permet d'appeler la méthode suivante

public static void test(Object obj)

À titre expérimental, vous pouvez essayer les combinaisons suivantes, qui vous permettront d'obtenir une meilleure clarté.

test((10 % 2 == 0) ? new Object() : "stringObj" ) ;

test((10 % 2 == 0) ? new Object() : null ) ;

test((10 % 2 == 0) ? "stringObj" : null ) ;

  • Enfin, dans la dernière partie, vous appelez avec le code suivant.

test((10%2==0)?null:null) ;

Cette fois encore, il renvoie une valeur booléenne "true", et il suivra les mêmes transformations que celles expliquées ci-dessus. Mais cette fois, il n'y a pas de new Object() est présent dans votre opérateur ternaire. Il sera donc converti automatiquement en null Objet. L'appel de méthode est le même que celui de votre premier appel de méthode.

  • La dernière fois que vous avez demandé un code, si vous avez mis en if .. else déclaration. C'est également le compilateur qui prend la bonne décision avec le code.

i test(null) ; }

Ici, tout le temps que votre condition if est vraie et que vous appelez ce code test(null) . Donc tout le temps il appelle le premier test(String obj) avec une chaîne de caractères comme paramètre, comme expliqué ci-dessus.

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