1、认识多态
- 面向对象三大特征:封装、继承、多态
什么是多态?
- 同类型的对象,表现出不同的 形态 。(对象的多种形态。)
- 同类型的对象,执行同一个行为,会表现出不同的行为 特征 。
- 同一个对象,在不同时刻表现出来的不同形态
多态的表现形式?
父类类型 对象名称 = 子类对象;(父类类型 对象名称 = new 子类构造器) 接口 对象名称 = new 实现类构造器; 多态的前提?
- 有 继承 / 实现 关系;
- 有父类引用指向子类对象
- 有方法重写
多态的好处?
- 使用父类型作为参数,可以接收所有子类对象,体现多态的扩展性与便利。
@Data @AllArgsConstructor @NoArgsConstructor public class Person { private String name; private int age; public void show() { System.out.println(name + "," + age); } } class Student extends Person { @Override public void show() { System.out.println("学生的信息位:" + getName() + ", " + getAge()); } } class Teacher extends Person { @Override public void show() { System.out.println("老师的信息为:" + getName() + ", " + getAge()); } } class Administrator extends Person { @Override public void show() { System.out.println("管理员的信息为:" + getName() + ", " + getAge()); } } class Test { public static void main(String[] args) { // 创建三个对象,并调用register方法 Student s = new Student(); s.setName("张三"); s.setAge(18); Teacher t = new Teacher(); t.setName("王建国"); t.setAge(20); Administrator admin = new Administrator(); admin.setName("管理员"); admin.setAge(35); register(s); register(t); register(admin); } // 这个方法既能接收老师,又能接收学生,还能接收管理员 // 只能把参数写成这三个类型的父类 public static void register(Person p) { p.show(); } } D:\Java\jdk-17\bin\java.exe 学生的信息位:张三, 18 老师的信息为:王建国, 20 管理员的信息为:管理员, 35 Process finished with exit code 0
2、多态调用成员的特点
变量调用:编译看左边,运行也看左边。 编译看左边:javac编译代码的时候,会看左边的父类中有没有这个变量,如果有,编译成功,如果没有编译失败。
运行看左边:java运行代码的时候,实际获取的就是左边父类中成员变量的值
方法调用:编译看左边,运行看右边。
编译看左边:javac编译代码的时候,会看左边的父类中有没有这个方法,如果有,编译成功,如果没有编译失败。
运行看右边:java运行代码的时候,实际上运行的是子类中的方法
Animal a = new Dog();
现在用 a 去调用变量和方法的呀?是的
而a是Animal类型的,所以默认都会从Animal这个类中去找
//成员变量:在子类的对象中,会把父类的成员变量也继承下的的。父:name 子:name
//成员方法:如果子类对方法进行了重写,那么在虚方法表中是会把父类的方法进行覆盖的。
3、为什么成员变量和成员方法的访问不一样呢?
- 因为成员方法有重写,而成员变量没有
4、多态调用成员的内存图解
首先第一步测试类的字节码文件先加载到方法区当中,然后虚拟机会自动的去调用main方法,然后会先加载父类的字节码文件,然后会再加载子类的字节码文件。
5、多态的优势和弊端
多态的优势
- 在多态形式下,右边对象可以实现解耦合,便于扩展和维护。
- 定义方法的时候,使用 父类型 作为参数,可以接收所有子类对象(该方法就可以接收这父类的一切子类对象),体现多态的扩展性与便利。
多态的劣势
- 多态下不能使用子类的独有功能
文章来源:https://www.toymoban.com/news/detail-627888.html
6、引用数据类型的类型转换,有几种方式?
- 自动类型转换、(从子到父):子类对象赋值给父类类型的变量指向。
- 强制类型转换、(从父到子):
- 此时必须进行强制类型转换:子类 对象变量 = (子类)父类类型的变量
- 作用:可以解决多态下的劣势,可以实现调用子类独有的功能。
- 注意:如果 转型后的类型 和对象真实类型 不是同一种类型 ,那么在转换的时候就会出现 ClassCastException 。
- Java建议强制转换前使用instanceof判断当前对象的真实类型,再进行强制转换
7、强制类型转换能解决什么问题?
- 可以转换成真正的子类类型,从而调用 子类独有功能 。
- 有 继承关系 / 实现 的2个类型就可以进行强制转换,编译无问题。
- 转换类型与真实对象类型不一致会报错。(运行时,如果发现强制转换后的类型不是对象真实类型则报错。类型转换异常:ClassCastException)
- 转换的时候用instanceof关键字进行判断
8、instanceof 在 jdk14,语言等级16中的新特性
文章来源地址https://www.toymoban.com/news/detail-627888.html
public class Test { public static void main(String[] args) { Animal a = new Dog(); a.eat(); // ((Dog) a).lookHome(); /*if (a instanceof Dog) { Dog d = (Dog) a; d.lookHome(); } else if (a instanceof Cat) { Cat c = (Cat) a; c.catchMouse(); } else { System.out.println("没有这个类型,无法转换"); }*/ //jdk14新特性,语言等级16 if (a instanceof Dog d) { d.lookHome(); } else if (a instanceof Cat c) { c.catchMouse(); } else { System.out.println("没有这个类型,无法转换"); } } } class Animal { public void eat() { System.out.println("动物在吃东西"); } } class Dog extends Animal { @Override public void eat() { System.out.println("狗吃骨头"); } public void lookHome() { System.out.println("狗看家"); } } class Cat extends Animal { @Override public void eat() { System.out.println("猫吃小鱼干"); } public void catchMouse() { System.out.println("猫抓老鼠"); } }
9、多态的综合练习
不使用多态完成练习
@Data @AllArgsConstructor @NoArgsConstructor public class Person { private String name; private int age; public void keepPet(Dog dog, String something) { System.out.println("年龄为" + age + "岁的" + name + "养了一只" + dog.getColor() + "颜色的" + dog.getAge() + "岁的狗"); dog.eat(something); } public void keepPet(Cat cat, String something) { System.out.println("年龄为" + age + "岁的" + name + "养了一只" + cat.getColor() + "颜色的" + cat.getAge() + "岁的猫"); cat.eat(something); } } @Data @AllArgsConstructor @NoArgsConstructor class Animal { private int age; private String color; public void eat(String something) { System.out.println("动物在吃" + something); } } class Dog extends Animal { int age; String color; public Dog() { } public Dog(int age, String color) { super(age, color); } @Override public void eat(String something) { System.out.println(getAge() + "岁的" + getColor() + "颜色的狗两只前腿死死的抱住" + something + "猛吃"); } public void lookHome() { System.out.println("狗看家"); } } class Cat extends Animal { public Cat() { } public Cat(int age, String color) { super(age, color); } @Override public void eat(String something) { System.out.println(getAge() + "岁的" + getColor() + "颜色的猫咪着眼睛侧着吃" + something); } public void catchMouse(String something) { System.out.println("猫抓老鼠"); } } class Test { public static void main(String[] args) { Person person = new Person("老王", 30); Dog dog = new Dog(2, "黑"); person.keepPet(dog, "骨头"); Person person1 = new Person("老李",25); Cat cat = new Cat(3, "灰"); person1.keepPet(cat,"鱼"); } } D:\Java\jdk-17\bin\java.exe 年龄为30岁的老王养了一只黑颜色的2岁的狗 2岁的黑颜色的狗两只前腿死死的抱住骨头猛吃 年龄为25岁的老李养了一只灰颜色的3岁的猫 3岁的灰颜色的猫咪着眼睛侧着吃鱼 Process finished with exit code 0
使用继承关系完成多态练习
@Data @AllArgsConstructor @NoArgsConstructor public class Person { private String name; private int age; public void keepPet(Animal a, String something) { if (a instanceof Dog d) { System.out.println("年龄为" + age + "岁的" + name + "养了一只" + d.getColor() + "颜色的" + d.getAge() + "岁的狗"); d.eat(something); } else if (a instanceof Cat c) { System.out.println("年龄为" + age + "岁的" + name + "养了一只" + c.getColor() + "颜色的" + c.getAge() + "岁的猫"); c.eat(something); } else { System.out.println("没有这种动物"); } } } @Data @AllArgsConstructor @NoArgsConstructor class Animal { private int age; private String color; public void eat(String something) { System.out.println("动物在吃" + something); } } @Data @AllArgsConstructor @NoArgsConstructor class Dog extends Animal { int age; String color; @Override public void eat(String something) { System.out.println(getAge() + "岁的" + getColor() + "颜色的狗两只前腿死死的抱住" + something + "猛吃"); } public void lookHome() { System.out.println("狗看家"); } } @Data @AllArgsConstructor @NoArgsConstructor class Cat extends Animal { @Override public void eat(String something) { System.out.println(getAge() + "岁的" + getColor() + "颜色的猫咪着眼睛侧着吃" + something); } public void catchMouse() { System.out.println("猫抓老鼠"); } } class Test { public static void main(String[] args) { Person p = new Person("老王", 30); Person p2 = new Person("老王", 25); Dog d = new Dog(2, "黑"); Cat c = new Cat(3, "灰"); p.keepPet(d, "骨头"); p2.keepPet(c, "鱼"); } } D:\Java\jdk-17\bin\java.exe 年龄为30岁的老王养了一只黑颜色的2岁的狗 2岁的黑颜色的狗两只前腿死死的抱住骨头猛吃 年龄为25岁的老王养了一只灰颜色的3岁的猫 3岁的灰颜色的猫咪着眼睛侧着吃鱼 Process finished with exit code 0
使用实现关系(接口)完成多态练习
public interface USB { void connect(); void unconnect(); } @Data @AllArgsConstructor @NoArgsConstructor class Mouse implements USB { private String name; @Override public void connect() { System.out.println(name + "成功的接入了设备~~~"); } @Override public void unconnect() { System.out.println(name + "成功的从设备弹出~~~"); } public void click() { System.out.println(name + "双击点亮小红心~~~"); } } @Data @AllArgsConstructor @NoArgsConstructor class KeyBoard implements USB { private String name; @Override public void connect() { System.out.println(name + "成功的接入了设备~~~"); } @Override public void unconnect() { System.out.println(name + "成功的从设备弹出~~~"); } public void keyDown() { System.out.println(name + "写下了:老铁,6666,下次再来哦,老弟~~~~"); } } class Computer { public void installUSB(USB u) { u.connect(); if (u instanceof Mouse m) { m.click(); } else if (u instanceof KeyBoard k) { k.keyDown(); } else { System.out.println("不符合"); } u.unconnect(); } } class Test1 { public static void main(String[] args) { Computer c = new Computer(); USB u = new Mouse("罗技鼠标"); c.installUSB(u); USB k = new KeyBoard("双飞燕键盘"); c.installUSB(k); } } D:\Java\jdk-17\bin\java.exe 罗技鼠标成功的接入了设备~~~ 罗技鼠标双击点亮小红心~~~ 罗技鼠标成功的从设备弹出~~~ 双飞燕键盘成功的接入了设备~~~ 双飞燕键盘写下了:老铁,6666,下次再来哦,老弟~~~~ 双飞燕键盘成功的从设备弹出~~~ Process finished with exit code 0
到了这里,关于多态的使用的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!