Java引用变量有两个类型:编译时类型和运行时类型。编译时类型由声明该变量时使用的类型决定,运行时类型由实际赋给该变量的对象决定。spa
若编译时类型和运行时类型不一致,就出现多态code
正常的方法调用(本态调用)对象
Person e = new Person(); e.say(); Student e = new Student(); e.say;
虚拟方法调用(多态状况下)blog
Person e = new Student(); e.say(); // 调用Student类的say()方法
编译时类型和运行时类型编译
编译时e为Person类型,而方法的调用是在运行时肯定的,因此调用的是Student类的say()方法。——动态绑定class
在虚拟方法调用状况下,方法看重写后的,但属性没有重写一说,e.name为Person中的name。变量
引用类型之间的类型转换(对象的多态)cli
前提:父子关系语法
1、向上转型引用
本质:父类的引用指向了子类的对象
语法:
父类类型 引用名 = new 子类类型();
特色:
编译看左边,运行看右边
能够调用父类类型中的全部成员,不能调用子类类型中特有成员;最终运行效果看子类的具体实现!
2、向下转型
语法:
子类类型 引用名 = (子类类型)父类引用;
特色:
① 只能强转父类的引用,不能强转父类的对象
② 要求父类的引用必须指向的是当前目标类型的对象(已经指向子类类型的)
③ 能够调用子类类型中全部的成员
示例:
public class TestPoly { public static void main(String[] args) { //子类——>父类 // 向上转型(自动类型转换):小——>大 Animal a =new Cat(); //能够调用哪些成员 a.eat(); a.run(); a.age=10; a.name=""; a.method(); // a.climb(); // 向下转型(强制类型转换) Cat c = (Cat) a; // Cat c2 = (Cat)(new Animal()); // 报错,必须是父类的引用 // Animal b = new Pig(); // Cat c3 = (Cat)b; // 可能不报错,但实际应用内部不是Pig
//能够调用哪些成员? c.run(); c.eat(); c.climb(); c.method(); c.name=""; c.age=1; c.color=""; } } class Animal{ String name; int age; public void eat(){ System.out.println("动物的吃"); } public void run(){ System.out.println("动物的跑"); } public void method(){ System.out.println("method"); } } class Pig extends Animal{ } class Cat extends Animal{ String color; public void run(){ System.out.println("猫飞快的跑"); } public void climb(){ System.out.println("猫爬树"); } }
instanceof 判断对象所属类
x instanceof A:检验x是否为类A的对象,返回值为boolean型。
要求x所属的类与类A必须是子类和父类的关系,不然编译错误。
若是x属于类A的子类B,x instanceof A值也为true。
public class Person extends Object {…} public class Student extends Person {…} public class Graduate extends Person {…} ------------------------------------------------------------------- public void method1(Person e) { if (e instanceof Person) // 处理Person类及其子类对象 if (e instanceof Student) //处理Student类及其子类对象 if (e instanceof Graduate) //处理Graduate类及其子类对象 }