面对对象的三大特性: 三、多态
多态
动态编译类型 - 同一方法可以根据发送对象的不同而采用多种不同的行为方式。
一个对象的实际类型是确定的,但可以指向对象的引用的类型有很多。
多态存在的条件
- 有继承关系
- 子类重写父类方法
- 父类引用指向子类对象
注意:多态是方法的多态,属性没有多态性
instanceof
一个对象的实际类型是确定的
new Student();
new Person();
但是,可以指向的引用类型就不确定了
子类重写了父类的方法,就执行子类的方法
多态注意事项
- 多态是方法的多态,属性无法多态
- 父类和子类,有联系,类型转换异常! ClassCastException!
- 存在条件: 有继承关系,如有需要方法需要重写,父类引用指向子类对象! Father f1 = new Son();
无法被重写的方法(修饰符):
-
static 静态方法 - 方法,属于类,而不属于实例
-
final 常量
-
private 私有方法也不能被重写
被这三个修饰符修饰的方法无法被重写,所以也无法实现多态
如果没有“重写Override”,不能重复方法/方法名
- 父类Person
package oop.Demo06;
public class Person {
public void run(){
System.out.println("run");
}
}
- 子类Student
package oop.Demo06;
public class Student extends Person {
//重写在父类Person的run方法,从此父类子类都执行此处的方法
@Override
public void run() {
System.out.println("son");
}
//父类Person没有这个方法-eat,因此在测试里,父类Person无法调用此方法
public void eat(){
System.out.println("eat");
}
}
- 测试Application
package oop;
import oop.Demo05.A;
import oop.Demo05.B;
import oop.Demo06.Person;
import oop.Demo06.Student;
public class Application {
public static void main(String[] args) {
//一个对象的实际类型是确定的
//new Student();
//new Person(); new Person/Student后就是new Person/Student
//但是,可以指向的引用类型就不确定了: 父亲的引用指向子类
// 也就是 y与x, 多个x可以得到相同的y值
//子类"Student"能执行的方法都是自己的或是继承父类的!
Student s1 = new Student(); // 子类指向的引用
//父类Person可以指向子类"Student",但是不可以调用子类独有的方法
Person s2 = new Student(); // 父类指向的引用
Object s3 = new Student(); //因为Person是student的父类,Object是默认的父类所以,可以newStudent以这三种形式
//对象能执行那些方法,主要看对象左边的类型(父类、子类),和右边关系不大
s2.run(); // 父类Person
//s2.eat(); 无法调用
s1.run(); //Student 类
s1.eat();//子类可以调用自己的方法eat
//输出结果为
//son
//son
//都变成了son,经历过Override, 子类重写了父类的方法,就执行子类的方法
}
}

instanceof 关键词
instanceof (类型转换)
通过instanceof可以判断一个对象是什么类型
通过instanceof可以判断两个类之间是否存在父子关系
总结为公式:
System.out.println(x instanceof y); 编译器能否通过取决于x与y是否有父子类关系
怎么使用instanceof判断类与类之间的关系:
package oop;
import oop.Demo05.A;
import oop.Demo05.B;
import oop.Demo06.Person;
import oop.Demo06.Student;
import oop.Demo06.Teacher;
public class Application {
public static void main(String[] args) {
//Object > Person > Student//Teacher
//Object > Person > Teacher
//Object > String
Object object = new Student(); //Object是Person的父类,Person是"Student"的父类
//使用new在object和 Student 建立了这种关系,那么使用instanceof验证一下
System.out.println(object instanceof Student); // True
System.out.println(object instanceof Person); // True
System.out.println(object instanceof Object); // True
System.out.println(object instanceof Teacher); // False
System.out.println(object instanceof String); // False
System.out.println("========================");
Person person = new Student();
System.out.println(person instanceof Student); // True
System.out.println(person instanceof Person); // True
System.out.println(person instanceof Object); // True
System.out.println(person instanceof Teacher); // False
//System.out.println(person instanceof String); // False Person和String是平行关系,同级关系 !!编译器报错!!
System.out.println("========================");
Student student = new Student();
System.out.println(student instanceof Student); // True
System.out.println(student instanceof Person); // True
System.out.println(student instanceof Object); // True
//System.out.println(student instanceof Teacher); // False Student和Teacher是同级关系 !!编译器报错!!
//System.out.println(student instanceof String); // False String和Student没有关系 !!编译器报错!!
// 总结为公式:
//System.out.println(x instanceof y); 编译器能否通过取决于x与y是否有父子类关系
}
}
类型之间的转换
- 基本类型转换
- 高-低 64 32 16 8
- 高转低会有溢出,低转高没关系
- “类”型之间的转换
- 父子之间的转换: 低转高没问题,高转低需要强制转换
- 父类引用指向子类的对象
- 子类转换为父类, 向上转型,无需强制转换
- 父类转换为子类,向下转型,需要强制转换,子类可能会丢失自己的方法
- 但是父类转换为子类,便利与方法的调用,减少重复的代码!
低转高是慢慢长大,高转低是返老还童,会失忆
//高 低
Person student = new Student(); //子类Student这个对象被new成父类Person, 低转高 OK
//student.go();
//但是此时,student无法使用"Student"de方法go
//student[父类Person]将这个对象转换为Student[子类Student],我么就可以使用"Student"类型的方法了
Student student1 = (Student) student; //高转低, Person student -- Student student1 强制转换
((Student) student).go(); //经过强制转换就可以使用 更低一层-子类 的方法了
//子类转换为父类,可能会丢失一些自己的方法
/*
栗子:
Object example = new Student(); //低转高
Student example2 = (Student) example; //
((Student) example).go();
*/

浙公网安备 33010602011771号