目录
1.多态的基本介绍
2.方法的多态
3.对象的多态(核心)
4.多态的注意事项和细节
1.多态的向上转型
2.多态的向下转型
3.属性重写问题
5.java的动态绑定机制(重点)
6.多态的应用
1.多态数组
2.多态参数
1.多态的基本介绍
方法或对象具有多种形态。是面向对象的三大特征,多态是建立在封装和继承基础之上的
Java 多态 | 菜鸟教程 (runoob.com)https://www.runoob.com/java/java-polymorphism.html
2.方法的多态
代码演示:
package com.shixin.java;
public class polymorphic {
public static void main(String[] args) {
//方法重载体现多态
A a = new A();
//这里我们传入不同的参数,就会调用不同的sum方法
System.out.println(a.sum(10,20));
System.out.println(a.sum(10,20,30));
//方法重写体现多态
B b = new B();
a.say();
b.say();
}
}
class B{//父类
public void say(){
System.out.println("B say()方法被调用");
}
}
class A extends B{//子类
public int sum(int n1,int n2){
return n1 + n2;
}
public int sum(int n1,int n2,int n3){
return n1 + n2 +n3;
}
public void say(){
System.out.println("A say()方法被调用");
}
}
3.对象的多态(核心)
重要的几句话:
(1)一个对象的编译类型和运行类型可以不一致
(2)编译类型在定义对象时,就确定了,不能改变
(3)运行类型可以变化的
(4)编译类型看定义时 =号的左边,运行时看 =号的右边
代码演示:
package com.shixin.java;
public class PloyObject {
public static void main(String[] args) {
//体验对象的多态
//animal 编译类型就是 Animal,运行类型是Dog
Animal animal = new Dog();
//因为运行时,执行到该行时,animal运行类型是Dog,所以cry方法就是Dog的cry方法
animal.cry();
}
}
class Animal{
public void cry(){
System.out.println("Animal 动物在叫 ");
}
}
class Cat extends Animal{
@Override
public void cry() {
System.out.println("Cat cry() 小猫喵喵叫");
}
}
class Dog extends Animal{
@Override
public void cry() {
System.out.println("Dog cry() 小狗汪汪叫");
}
}
4.多态的注意事项和细节
多态的前提是:两个对象(类)存在继承关系的
1.多态的向上转型
(1)本质:父类的引用指向了子类的对象
(2)语法:父类类型 引用名 = new 子类类型();
(3)特点:编译类型看左边,运行类型看右边
可以调用父类中的所有成员(需要遵守访问权限)
不能调用子类中特有成员
最终运行效果看子类的具体实现
代码演示:
package com.shixin.java;
public class Test {
public static void main(String[] args) {
//向上转型:父类引用指向子类对象
//语法:父类类型 引用名 = new 子类类型();
Animal animal = new Cat();
//可以调用父类中的所有成员(需要遵守访问权限)
//不能调用子类中特有成员
//因为在编译阶段,能调用那些成员,是由编译类型来决定的
//最终运行效果看子类的具体实现
animal.eat();//调用的是子类的eat()方法
animal.sleep();
}
}
class Animal{
public void eat(){
System.out.println("吃");
}
public void sleep(){
System.out.println("睡");
}
}
class Cat extends Animal{
@Override
public void eat() {
System.out.println("猫吃鱼");
}
public void catchMouse(){//cat特有的方法
System.out.println("猫抓老鼠");
}
}
2.多态的向下转型
(1)语法:子类类型 引用名 = (子类类型) 父类引用;
(2)只能强转父类的引用,不能强转父类的对象
(3)要求父类的引用必须指向的是当前目标类型的对象
(4)向下转型后,可以调用子类类型中所有的成员
代码演示:
package com.shixin.java;
public class PolymorphicDetail {
public static void main(String[] args) {
//父类引用指向子类对象
Animal animal01 = new Cat();
//不能调用子类中特有成员
//animal.catchMouse; 报错
//多态的向下转型
//调用子类特有的方法:catchMouse()
//语法:子类类型 引用名 = (子类类型) 父类引用;
//要求父类的引用必须指向的是当前目标类型的对象
//向下转型中,父类引用只能转换为其当前指向的子类对象
//animal01的运行类型Cat类型,所以只能转换为Cat类型
Cat cat = (Cat) animal01;
cat.catchMouse();
}
}
class Animal{
public void eat(){
System.out.println("吃");
}
public void sleep(){
System.out.println("睡");
}
}
class Cat extends Animal{
@Override
public void eat() {
System.out.println("猫吃鱼");
}
public void catchMouse(){//cat特有的方法
System.out.println("猫抓老鼠");
}
}
3.属性重写问题
属性没有重写之说!属性的值看编译类型
代码演示:
package com.shixin.java;
public class PolymorphicDetail {
public static void main(String[] args) {
//属性没有重写之说!属性的值看编译类型
Base base = new Sub();
//看编译类型
System.out.println(base.count);//10
}
}
class Base{
public int count = 10;
}
class Sub extends Base{
public int count = 20;
}
instanceOf 比较运算符,用于判断对象的运行类型是否为XX类型或XX类型的子类型
代码演示:
package com.shixin.java;
public class PolymorphicDetail02 {
public static void main(String[] args) {
BB b = new BB();
System.out.println(b instanceof BB);//true
System.out.println(b instanceof AA);//true
//a 编译类型是AA 运行类型是BB
AA a = new AA();
System.out.println(a instanceof AA);//true
System.out.println(a instanceof BB);//true
Object obj = new Object();
System.out.println(obj instanceof AA);//false
String str = "hello";
System.out.println(str instanceof Object);//true
}
}
class AA{}//父类
class BB extends AA{}//子类
5.java的动态绑定机制(重点)
1.当调用对象方法的时候,该方法会和对象的内存地址/运行类型绑定
2.当调用对象属性时,没有动态绑定机制,哪里声明,哪里使用
代码演示:
package com.shixin.java.test;
public class PolymorphicBinding {
public static void main(String[] args) {
//a的编译类型 A,运行类型 B
A a = new B();
System.out.println(a.sum());//30
System.out.println(a.sum2());//20
}
}
class A{//父类
public int i =10;
public int sum(){
return getI() + 10;
}
public int sum2(){
return i + 10;
}
public int getI(){
return i;
}
}
class B extends A{//子类
public int i = 20;
public int getI() {
return i;
}
}
6.多态的应用
1.多态数组
数组的定义为父类型,里边保存的实际元素为子类类型
代码演示:
package com.shixin.java;
public class PolymorphicArray {
public static void main(String[] args) {
//应用实例:要求创建1个Person数组
//1个Person对象,1个Student对象和1个Teacher对象,同一放到数组中,并调用每个对象的say方法
Person[] people = new Person[3];
people[0] = new Person("jack",20);
//向上转型
people[1] = new Student("tom",18,88);
people[2] = new Teacher("smith",28,4000);
for (int i = 0; i < people.length; i++) {
//person[i] 编译类型是Person,运行类型是根据实际情况由JVM来判断
System.out.println(people[i].say());//动态绑定
//调用子类特有的方法
if (people[i] instanceof Student){
//向下转型
((Student)people[i]).study();
}else if (people[i] instanceof Teacher){
((Teacher)people[i]).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 +"t"+ age;
}
}
class Student extends Person{
private double score;
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;
}
//重写父类say方法
@Override
public String say() {
return super.say() + "tscore = " + score;
}
//特有方法
public void study(){
System.out.println("学生 " + getName() + "正在学习");
}
}
class Teacher extends Person{
private double salary;
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;
}
@Override
public String say() {
return super.say() + "tsalary = "+ salary;
}
//特有方法
public void teach(){
System.out.println("老师 " + getName() + "正在讲课");
}
}
2.多态参数
方法定义的形参类型为父类类型,实参类型允许为子类型
代码演示:
package com.shixin;
public class PolymorphicParameter {
public static void main(String[] args) {
Master master = new Master();
Cat cat = new Cat("jack");
Dog dog = new Dog("tom");
master.feed(cat);
master.feed(dog);
}
}
class Master{//主人类
//给动物喂食的方法
public void feed(Animal animal){
animal.eat();
}
}
class Animal{//动物类
private String name;
public Animal(String name) {
this.name = name;
}
public void eat(){
System.out.println("动物需要进食");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
class Cat extends Animal{//小猫类
public Cat(String name) {
super(name);
}
@Override
public void eat() {
System.out.println("小猫 " + getName() +" 吃鱼");
}
}
class Dog extends Animal{//小狗类
public Dog(String name) {
super(name);
}
@Override
public void eat() {
System.out.println("小狗 " + getName() + "吃骨头");
}
}



