Java引用变量有两个类型:编译时类型和运行时类型。编译时类型由声明该变量时使用的类型决定,运行时类型由实际赋给该变量的对象决定。
若编译时类型和运行时类型不一致,就出现多态
正常的方法调用(本态调用)
Person e = newPerson();
e.say();
Student e= newStudent();
e.say;
虚拟方法调用(多态情况下)
Person e = newStudent();
e.say();//调用Student类的say()方法
编译时类型和运行时类型
编译时e为Person类型,而方法的调用是在运行时确定的,所以调用的是Student类的say()方法。——动态绑定
在虚拟方法调用情况下,方法看重写后的,但属性没有重写一说,e.name为Person中的name。
引用类型之间的类型转换(对象的多态)
前提:父子关系
一、向上转型
本质:父类的引用指向了子类的对象
语法:
父类类型 引用名 = new 子类类型();
特点:
编译看左边,运行看右边
可以调用父类类型中的所有成员,不能调用子类类型中特有成员;最终运行效果看子类的具体实现!
二、向下转型
语法:
子类类型 引用名 = (子类类型)父类引用;
特点:
① 只能强转父类的引用,不能强转父类的对象
② 要求父类的引用必须指向的是当前目标类型的对象(已经指向子类类型的)
③ 可以调用子类类型中所有的成员
示例:
public classTestPoly {public static voidmain(String[] args) {//子类——>父类//向上转型(自动类型转换):小——>大
Animal a =newCat();//可以调用哪些成员
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="";
}
}classAnimal{
String name;intage;public voideat(){
System.out.println("动物的吃");
}public voidrun(){
System.out.println("动物的跑");
}public voidmethod(){
System.out.println("method");
}
}class Pig extendsAnimal{
}class Cat extendsAnimal{
String color;public voidrun(){
System.out.println("猫飞快的跑");
}public voidclimb(){
System.out.println("猫爬树");
}
}
instanceof 判断对象所属类
x instanceof A:检验x是否为类A的对象,返回值为boolean型。
要求x所属的类与类A必须是子类和父类的关系,否则编译错误。
如果x属于类A的子类B,x instanceof A值也为true。
public class Person extendsObject {…}public class Student extendsPerson {…}public class Graduate extendsPerson {…}-------------------------------------------------------------------
public voidmethod1(Person e) {if (e instanceofPerson)//处理Person类及其子类对象
if (e instanceofStudent)//处理Student类及其子类对象
if (e instanceofGraduate)//处理Graduate类及其子类对象
}