Conversion de type d'objets polymorphes Java
La conversion de type d'objet mentionnée ici fait référence à des objets avec des relations d'héritage, et non à des objets d'aucun type. Lors de la conversion d'un objet qui n'a pas de relation d'héritage, le moteur d'exécution Java lèvera une exception java.lang.ClassCastException.
Dans la chaîne d'héritage, nous appelons la conversion d'une sous-classe en classe parent "upcasting", et la conversion d'une classe parent en classe enfant est appelée "downcasting".
Souvent, nous définirons les variables comme le type de la classe parent, mais nous nous référerons à l'objet de la sous-classe. Ce processus est une transformation vers le haut. Lorsque le programme est en cours d'exécution, l'appel des méthodes de sous-classe est implémenté via une liaison dynamique, qui est le polymorphisme.
Cependant, parfois, afin de compléter certaines fonctions que la classe parent n'a pas, nous devons convertir l'objet de sous-classe après transformation ascendante en sous-classe et appeler la méthode de la sous-classe.
Remarque : vous ne pouvez pas forcer directement l'objet de la classe parent au type de sous-classe. Vous pouvez uniquement reconvertir l'objet de sous-classe upcast en type de sous-classe. En d’autres termes, les objets de sous-classe doivent être transformés vers le haut avant de pouvoir être transformés vers le bas. Veuillez regarder le code suivant :
public class Demo { public static void main(String args[]) { SuperClass superObj = new SuperClass(); SonClass sonObj = new SonClass(); // 下面的代码运行时会抛出异常,不能将父类对象直接转换为子类类型 // SonClass sonObj2 = (SonClass)superObj; // 先向上转型,再向下转型 superObj = sonObj; SonClass sonObj1 = (SonClass)superObj; } } class SuperClass{ } class SonClass extends SuperClass{ }
Supprimez le commentaire sur la ligne 7. Une exception sera levée lors de l'exécution, mais la compilation peut réussir.
Comme il existe des risques lors du downcasting, lorsque vous recevez une référence de la classe parent, assurez-vous d'utiliser l'opérateur instanceof pour déterminer si l'objet est la sous-classe souhaitée. Veuillez consulter le code suivant :
<. 🎜>public class Demo { public static void main(String args[]) { SuperClass superObj = new SuperClass(); SonClass sonObj = new SonClass(); // superObj 不是 SonClass 类的实例 if(superObj instanceof SonClass){ SonClass sonObj1 = (SonClass)superObj; }else{ System.out.println("①不能转换"); } superObj = sonObj; // superObj 是 SonClass 类的实例 if(superObj instanceof SonClass){ SonClass sonObj2 = (SonClass)superObj; }else{ System.out.println("②不能转换"); } } } class SuperClass{ } class SonClass extends SuperClass{ }
①不能转换
En Java, les variables d'une classe parent peuvent référencer des instances de la classe parent ou des instances de la sous-classe.
public class Demo { public static void main(String[] args){ Animal obj = new Animal(); obj.cry(); obj = new Cat(); obj.cry(); obj = new Dog(); obj.cry(); } } class Animal{ // 动物的叫声 public void cry(){ System.out.println("不知道怎么叫"); } } class Cat extends Animal{ // 猫的叫声 public void cry(){ System.out.println("喵喵~"); } } class Dog extends Animal{ // 狗的叫声 public void cry(){ System.out.println("汪汪~"); } }
不知道怎么叫 喵喵~ 汪汪~
Vérifiez d'abord si la méthode existe dans la classe parent. Sinon, une erreur de compilation se produit si c'est le cas, vérifiez si la sous-classe remplace la méthode.
Si la sous-classe remplace cette méthode, appelez la méthode de la sous-classe, sinon appelez la méthode de la classe parent.
public class Demo { public static void main(String[] args){ // 借助多态,主人可以给很多动物喂食 Master ma = new Master(); ma.feed(new Animal(), new Food()); ma.feed(new Cat(), new Fish()); ma.feed(new Dog(), new Bone()); } } // Animal类及其子类 class Animal{ public void eat(Food f){ System.out.println("我是一个小动物,正在吃" + f.getFood()); } } class Cat extends Animal{ public void eat(Food f){ System.out.println("我是一只小猫咪,正在吃" + f.getFood()); } } class Dog extends Animal{ public void eat(Food f){ System.out.println("我是一只狗狗,正在吃" + f.getFood()); } } // Food及其子类 class Food{ public String getFood(){ return "事物"; } } class Fish extends Food{ public String getFood(){ return "鱼"; } } class Bone extends Food{ public String getFood(){ return "骨头"; } } // Master类 class Master{ public void feed(Animal an, Food f){ an.eat(f); } }
我是一个小动物,正在吃事物 我是一只小猫咪,正在吃鱼 我是一只狗狗,正在吃骨头
Liaison dynamique
3) Si le modificateur de la méthode est private, static, final (static et final seront expliqués plus tard), ou une méthode constructeur, alors le compilateur saura exactement quelle méthode doit être appelée. Nous appellerons cette méthode C'est. appelée liaison statique.
En conséquence, la méthode appelée dépend du type réel de l'objet et est liée dynamiquement au moment de l'exécution. Par exemple, lorsque func("hello") est appelé, l'éditeur utilisera une liaison dynamique pour générer une instruction permettant d'appeler func(String).
4) Lorsque le programme est en cours d'exécution et qu'une méthode est appelée à l'aide d'une liaison dynamique, la JVM appellera certainement la méthode de la classe la plus adaptée au type réel de l'objet référencé par obj. Nous avons supposé que le type réel d'obj est Cat, qui est une sous-classe d'Animal, et si func(String) est défini dans Cat, il sera appelé, sinon il sera recherché dans la classe Animal et sa classe parent.
Chaque fois qu'une méthode est appelée, une recherche est requise, ce qui prend beaucoup de temps. Par conséquent, la JVM pré-crée une table de méthodes (étiquette de méthode) pour chaque classe, qui répertorie les noms et les signatures des paramètres. et La classe à laquelle il appartient. De cette façon, lorsque la méthode est réellement appelée, la machine virtuelle n’a qu’à consulter cette table. Dans l'exemple ci-dessus, la JVM recherche dans la table des méthodes de la classe Cat une méthode qui correspond à un appel à func("hello"). Cette méthode peut être Cat.func(String) ou Animal.func(String). Notez que si vous appelez super.func("hello"), le compilateur recherchera la table des méthodes de la classe parent.
Supposons que la classe Animal contienne trois méthodes : cry(), getName() et getAge(), alors sa table de méthodes est la suivante :
cry() ->
getName () -> Animal.getName()
getAge() -> Animal.getAge()
En fait, Animal a également une classe parent par défaut Object (cela sera expliqué plus tard ), qui héritera des méthodes Object, les méthodes répertoriées ci-dessus ne sont donc pas complètes.
Supposons que la classe Cat couvre la méthode cry() dans la classe Animal et ajoute une nouvelle méthode GrimTree(), alors sa liste de paramètres est :
cry() ->
getName() -> Animal.getName()
getAge() -> Animal.getAge()
climbTree() -> en cours d'exécution, le processus d'appel de la méthode obj.cry() est le suivant :
La JVM recherche une méthode correspondant à cry() dans la table des méthodes. Une fois trouvée, elle sait à quelle classe elle appartient.
JVM appelle cette méthode.
Pour des articles plus détaillés sur la conversion de type et la liaison dynamique des objets polymorphes Java, veuillez faire attention au site Web PHP chinois !