20220727-Java中多态总结
目录
格言:我亦无他,唯手熟尔!
多态polymorphism:方法或者对象具有多种形态
1.方法的多态
1) 方法的重载可以体现多态
代码示例
// 通过方法重载,展现同一种方法的不同形态 public class PolyMethod { public static void main(String[] args) { AA aa = new AA(); aa.f(); aa.f(1); aa.f(1, 2); } } class AA { public void f() { System.out.println("f()"); } public void f(int i) { System.out.println("f(i)"); } public void f(int i, int j) { System.out.println("f(i,j)"); } }
2) 方法的重写可以体现多态
代码示例
// 通过子类继承父类并重写父类中的方法,体现同一个方法的不同形态 public class PolyMethod02 { public static void main(String[] args) { BB bb = new BB(); bb.f(); BBB bbb = new BBB(); bbb.f(); } } class BB { public void f() { System.out.println("BB f()"); } } class BBB extends BB { @Override public void f() { System.out.println("BBB f()"); } }
2.对象的多态
- 对象的编译类型与运行类型可以不同
- 对象的编译类型在定义对象的时候就确定了不能更改
- 对象的运行类型可以改变
- 对象的编译类型看创建对象时=的左边,运行类型看=的右边
- Animal animal = new Dog();
- animal = new Cat();
代码示例
public class PolyObject { public static void main(String[] args) { People people = new Student(); //people编译类型为People,运行类型为Student //System.out.println(people.id); //people.f2(); System.out.println("name=" + people.name); System.out.println(people.show()); } } class People { String name = "jack"; int age = 18; public void f1() { System.out.println("People f1()"); } public String show() { return "name=" + name + ",age=" + age; } } class Student extends People { int id = 1; double score = 100; @Override public String show() { return super.show() + ",id=" + id + ",score=" + score; } public void f2() { System.out.println("Student f2()"); } }
3.多态的注意事项和细节
- 使用父类对象引用可以调用父类中的所有成员(遵守访问权限)
- 使用父类对象引用不能调用子类的特有成员(编译阶段,只能按编译类型访问)
- 最终的运行效果,看运行类型
- !!!属性没有多态之说,属性的值直接看编译类型
- instanceof比较操作符,用于判断对象的运行类型是否为XX类型或者XX类型的子类型
代码示例
public class PolyDetail02 { public static void main(String[] args) { A a = new B(); System.out.println(a.count); //System.out.println(a.x); } } class A{ int count = 10; } class B extends A{ int count = 20; int x = 100; }
代码示例
public class PolyDetail03 { public static void main(String[] args) { C c = new D(); System.out.println(c instanceof C); System.out.println(c instanceof D); System.out.println(c instanceof Object); D d = new D(); System.out.println(d instanceof C); System.out.println(d instanceof D); C cc = new C(); System.out.println(cc instanceof C); System.out.println(cc instanceof D); } } class C {} class D extends C {}
4.向下转型
- 语法:子类类型 变量=(子类类型)父类引用;
- 只能强转父类的引用,而不能强转父类的对象
- 要求父类的引用必须指向当前目标类型的对象
- 当向下转型后,可以调用子类类型中所有的成员
5.Java动态绑定机制
- 当调用对象方法的时候,该方法会和该对象的内存地址/运行类型绑定
- 当调用对象属性时,没有动态绑定机制,哪里声明,哪里使用
代码示例
public class DynamicBinding { public static void main(String[] args) { A a = new B(); System.out.println(a.sum()); System.out.println(a.sum1()); } } class A { public int i = 10; public int sum() { return getI() + 10; } public int sum1() { return i + 10; } public int getI() { return i; } } class B extends A { public int i = 20; @Override public int sum() { return getI() + 20; } @Override public int sum1() { return i + 10; } @Override public int getI() { return i; } }
6.动态数组
- 数组类型为父类类型,实际存放的数组元素为父类类型或者子类类型对象
代码示例
public class PolyArray { public static void main(String[] args) { // 创建Person类型的数组 // 数组中存放Person类对象和其子类对象 // 数组p的编译类型为Peron,运行类型动态绑定 Person[] p = new Person[5]; p[0] = new Person("A", 1); p[1] = new Student("B", 2, 100); p[2] = new Student("C", 3, 200); p[3] = new Teacher("D", 4, 20000); p[4] = new Teacher("E", 5, 30000); for (Person pp : p) { System.out.println(pp.say()); //当调用子类的特有方法时,使用instanceof if (pp instanceof Student) { ((Student) pp).study(); } if (pp instanceof Teacher) { ((Teacher) pp).teach(); } } } } class Person { private String name; private int age; public Person(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String say() { return "name=" + name + " age=" + age; } } class Student extends Person { private int score; public Student(String name, int age, int score) { super(name, age); this.score = score; } public int getScore() { return score; } public void setScore(int score) { this.score = score; } @Override public String say() { return super.say() + " score=" + score; } public void study() { System.out.println("学生 " + getName() + " 正在上课"); } } class Teacher extends Person { private int salary; public Teacher(String name, int age, int salary) { super(name, age); this.salary = salary; } public int getSalary() { return salary; } public void setSalary(int salary) { this.salary = salary; } @Override public String say() { return super.say() + " salary=" + salary; } public void teach() { System.out.println("老师 " + getName() + "正在授课"); } }
7.动态参数
- 方法定义的形参类型为父类类型,实参类型允许为子类类型
代码示例
public class PolyParameter { public static void main(String[] args) { PolyParameter p = new PolyParameter(); Employee[] e = new Employee[3]; e[0] = new Employee("A", 100); e[1] = new Worker("B", 1000); e[2] = new Manager("C", 10000, 5000); for (Employee ee : e) { p.showEmpAnnual(ee); p.testWork(ee); } } public void showEmpAnnual(Employee e) { System.out.println(e.getName() + "的工资为:" + e.getAnnual()); } public void testWork(Employee e) { if (e instanceof Worker) { ((Worker) e).work(); } else if (e instanceof Manager) { ((Manager) e).manage(); } else if (e instanceof Employee) { } else { System.out.println("类型有误"); } } } class Employee { private String name; private double salary; public Employee(String name, double salary) { this.name = name; this.salary = salary; } public String getName() { return name; } public void setName(String name) { this.name = name; } public double getSalary() { return salary; } public void setSalary(double salary) { this.salary = salary; } public double getAnnual() { return getSalary(); } } class Worker extends Employee { public Worker(String name, double salary) { super(name, salary); } public void work() { System.out.println("普通员工 " + getName() + " 正在工作"); } @Override public double getAnnual() { return super.getAnnual(); } } class Manager extends Employee { private double bonus; public Manager(String name, double salary, double bonus) { super(name, salary); this.bonus = bonus; } public double getBonus() { return bonus; } public void setBonus(double bonus) { this.bonus = bonus; } public void manage() { System.out.println("经理 " + getName() + " 正在进行管理"); } @Override public double getAnnual() { return super.getAnnual() + getBonus(); } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)