Puisque vous comprenez déjà le cas 1, 3 et 4, attaquons-nous à la boîte 2.
(S'il vous plaît note - Je ne suis pas un expert sur le fonctionnement interne de la machine virtuelle Java ou compilateurs, mais voici comment Je comprends que si quelqu'un lisant ceci est un expert de la JVM, n'hésitez pas à modifier cette réponse pour toute divergence que vous pourriez trouver.)
Une méthode dans une sous-classe qui a le même nom mais une signature différente est connue sous le nom de surcharge de méthode. . La surcharge de méthode utilise une liaison statique, ce qui signifie que la méthode appropriée sera forcée à être "choisie" (c'est-à-dire liée) au moment de la compilation. Le compilateur n'a aucune idée sur le type d'exécution (aka le type réel) de vos objets.Donc, quand vous écrivez:
// Reference Type // Actual Type
Sub sub = new Sub(); // Sub Sub
Top top = sub; // Top Sub
le compilateur "sait" que le sommet est de type Top (alias le type de référence). Alors, quand vous écrivez plus tard:
System.out.println(top.f(str)); // Prints "subobj"
le compilateur « voit » l'appel « top.f » comme se référant à la méthode f de classe. Il "sait" que str est de type String qui étend Object. Donc puisque 1) l'appel 'top.f' fait référence à la méthode f de Top class, 2) il n'y a pas de méthode f dans la classe Top qui prend un paramètre String, et 3) puisque str est une sous-classe d'Object, la méthode f de Top est le seul choix valide au moment de la compilation. Ainsi, le compilateur lance implicitement str vers son type parent, Object, de sorte qu'il peut être passé à la méthode f de Top. (Ceci est contraire à la liaison dynamique, où la résolution de type de la ligne de code ci-dessus serait différée jusqu'à l'exécution, pour être résolue par la JVM plutôt que par le compilateur.)
Puis à l'exécution, dans la ligne de code ci-dessus , top est downcast par la JVM à son type réel, sub. Cependant, l'argument str a été mis à jour par le compilateur pour taper Object. Alors maintenant, la JVM doit appeler une méthode f dans la classe sub qui prend un paramètre de type Object. Par conséquent, la ligne de code ci-dessus imprime "subobj" plutôt que "sub".
Pour un autre exemple similaire, s'il vous plaît voir: Java dynamic binding and method overriding
Mise à jour: Nous avons trouvé cet article détaillé sur le fonctionnement interne de la machine virtuelle Java:
http://www.artima.com/underthehood/invocationP.html
Je commentais votre code pour le rendre plus clair ce qui se passe:
class Top {
public String f(Object o) {return "Top";}
}
class Sub extends Top {
public String f(String s) {return "Sub";} // Overloading = No dynamic binding
public String f(Object o) {return "SubObj";} // Overriding = Dynamic binding
}
public class Test {
public static void main(String[] args) {
// Reference Type Actual Type
Sub sub = new Sub(); // Sub Sub
Top top = sub; // Top Sub
String str = "Something"; // String String
Object obj = str; // Object String
// At Compile-Time: At Run-Time:
// Dynamic Binding
System.out.println(top.f(obj)); // Top.f (Object) --> Sub.f (Object)
// Dynamic Binding
System.out.println(top.f(str)); // Top.f (Object) --> Sub.f (Object)
// Static Binding
System.out.println(sub.f(obj)); // Sub.f (Object) Sub.f (Object)
// Static Binding
System.out.println(sub.f(str)); // Sub.f (String) Sub.f (String)
}
}
Maintenant, j'ai comment fonctionne la première ligne, mais comment se fait la deuxième ligne imprime SubObj, même si le dans L'appel put était top.f (str) où str est un type de String? – user482594
J'ai posté une réponse, avez-vous regardé. Cela devrait résoudre vos doutes. Pour résumer penser à partir du point de "Type Check" pour l'argument passé. Veuillez accepter la réponse si vous le trouvez utile. –