JAVA 多态
多态
好处:可以解决代码复用性不高,并且不利于代码维护的问题
一、基本介绍
方法或对象具有多种形态。是面向对象的第三大特征,多态是建立在封装和继承基础之上的。
二、对象的多态
以下几个规则要记住,非常重要
-
一个对象的编译类型和运行类型可以不一致
Animal animal = new Dog();//Animal 是编译类型,运行类型是dog animal = new Cat(); //animal 的运行类型变成了Cat,编译类型仍然是Animal
-
编译类型在定义对象时,就确定了,不能改变
-
运行类型是可以变化的
-
编译类型看定义时 = 号 的左边,运行类型 看 = 号的右边
三、注意事项
多态的前提是:两个对象(类)存在继承关系
-
属性没有重写之说!属性的值看编译类型
package com.hspedu.poly_.detail_; public class PolyDetail02 { public static void main(String[] args) { //属性没有重写之说!属性的值看编译类型 Base base= new Sub(); System.out.println(base.count);//10 Sub sub = new Sub(); System.out.println(sub.count);//20 } } class Base{ //父类 int count = 10; } class Sub extends Base{ int count = 20;//属性 }
-
instanceOf
比较运算符,用于判断对象的类型是否是XXX类型或者XXX类型的子类型package com.hspedu.poly_.detail_; public class PolyDetail03 { public static void main(String[] args) { BB bb = new BB(); System.out.println(bb instanceof BB); System.out.println(bb instanceof AA);//true //bb是AA嘛或者AA的类型的子类 //编译类型:AA //运行类型:BB AA aa = new BB(); System.out.println(aa instanceof BB);//true //这里看的是运行类型而不是编译类型 System.out.println(aa instanceof AA);//true Object obj = new Object(); System.out.println(obj instanceof AA);//false String str = "hello"; // System.out.println(str instanceof AA); System.out.println(str instanceof Object);//true } } class AA{//父类 } class BB extends AA{ }
1.多态的向上转型
-
本质:父类的引用指向了子类的对象
-
语法:
父类类型 引用名 = new 子类类型();
-
特点:编译类型看左边,运行类型看右边。可以调用父类中的所有成员(需遵守访问权限),不能调用子类的特有成员,最终效果要看子类的具体实现(方法会重写)
- 因为在编译阶段,能调用哪些成员,是由编译类型来决定的
- 即调用方法时,按照从运行类型(子类)开始查找方法然后调用
Animal
package com.hspedu.poly_.detail_; public class Animal { String name = "动物"; int age = 10; public void sleep(){ System.out.println("睡"); } public void run(){ System.out.println("跑"); } public void eat(){ System.out.println("吃"); } private void show(){ System.out.println("hello,你好"); } }
cat
package com.hspedu.poly_.detail_; public class Cat extends Animal{ @Override public void eat() { System.out.println("猫吃鱼"); } public void catchMouse(){//Cat特有的方法 System.out.println("猫抓老鼠"); } }
main
package com.hspedu.poly_.detail_; public class PolyDetail { public static void main(String[] args) { //本质:(向上转型)父类的引用指向子类的对象 //格式:父类类型 引用名 = new 子类类型(); Animal animal= new Cat(); Object obj = new Cat(); //可以调用父类中的所有成员(需遵守访问权限),但是不能调用子类的特有成员 //animal.catchMouse;不能调用 //因为在编译阶段,能调用哪些成员,是由编译类型来决定的 animal.eat(); } }
2.多态的向下转型
- 语法:
子类类型 引用名 = (子类类型) 父类引用;
- 只能强转父类的引用,不能强转父类的对象
- 要求父类的引用必须指向的是当前目标类型的对象
- 当向下转型后,就可以调用子类类型中的所有成员
四、JAVA的动态绑定机制
注意:非常非常重要
- 当调用对象方法的时候,该方法会和该对象的内存地址/运行类型绑定
- 当调用对象属性的时候,没有动态绑定机制,哪里声明,哪里使用,遵循作用域的原则
package com.hspedu.poly_.dynamic_;
public class DynamicBinding {
public static void main(String[] args) {
//编译类型:A,运行类型:B
A a = new B();
System.out.println(a.sum());//40 -> 30
System.out.println(a.sum1());//30 -> 20
}
}
class A {
public int i = 10;
//动态绑定机制:
//1.当调用
public int sum() {
return getI() + 10;//调用子类的getI(),20+10
}
public int sum1() {
return i + 10;//10+10
}
public int getI() {
return i;
}
}
class B extends A {
public int i = 20;
/* public int sum(){
return i+20;
}*/
public int getI() {
return i;
}
/* public int sum1() {
return i + 10;
}*/
}
五、多态的应用
1.多态数组
数组的定义类型为父类类型,里面保存的实际元素类型为子类类型
Person:父类
package com.hspedu.poly_.polyarr_;
public class Person {
private String name;
private int age;
public String say(){
return "name="+name + "\nage="+age;
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public void person(){
System.out.println("群众"+name);
}
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;
}
}
Student
package com.hspedu.poly_.polyarr_;
public class Student extends Person{
private double score;
//重写say方法
@Override
public String say() {
return "学生\n"+super.say() + "\nscore=" + score;
}
public void study(){
System.out.println("学生" + getName() + "正在学JAVA课程");
}
public Student(String name, int age, double score) {
super(name, age);
this.score = score;
}
public double getScore() {
return score;
}
public void setScore(double score) {
this.score = score;
}
}
Teacher
package com.hspedu.poly_.polyarr_;
public class Teacher extends Person{
private double salary;
@Override
public String say() {
return "老师\n"+super.say()+"\nsalary="+salary;
}
public void teach(){
System.out.println("老师" + getName() + "正在讲JAVA课程");
}
public Teacher(String name, int age, double salary) {
super(name, age);
this.salary = salary;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
}
2.多态参数
方法定义的形参类型为父类类型,实参类型允许为子类类型