一.对象上转型
在说多态之前我们先说一下对象上转型:
如下,9是int数据类型,把它存放到double类型的变量中,属于自动类型转换
public class Earth {
double age=9;
}
那么如果把这一形式用到类中来呢?就像下面的代码一样,创建一个新的子类类型的对象,然后定义一个父类类型的变量来指向这个对象,则这一操作就叫做对象上转型,等号后面的就叫做上转型对象:
//父类
public class Mammal {
}
//子类
public class Whale extends Mammal{
}
public class Earth {
public static void main(String[] args) {
Mammal mammal=new Whale();//对象上转型
}
}
二.什么是多态
我们对以下代码执行会发现,对象调用的方法是子类重写后的方法,
//父类
public class Mammal {
public void move() {
System.out.println("正在移动、、、");
}
}
//子类
public class Whale extends Mammal{
public void move() {
System.out.println("鱼鳍游动、、、");
}
}
public class Earth {
public static void main(String[] args) {
Mammal mammal=new Whale();//对象上转型
mammal.move();
}
}
这一现象便叫做多态: 当上转型对象调用父类类型变量的被子类重写过的方法时,便存在两个状态:表面上是调用父类的方法,但是执行时由于mammal指向的是子类创建的对象,所以指向时执行的是子类中的方法。
三.多态的注意事项
先补充一个知识点:以下这行代码的右边是运行时类型,也就是说是在运行时创建的对象;左边叫做编译时类型,是在编译阶段就定义的变量
Mammal mammal=new Whale();
1.左右类型相同
如果编译时类型与运行时类型相同,则一定不会出现多态。
这个不难理解,用父类的变量指向父类的对象,调用方法也一定是父类的
2.多态的前提
出现多态的前提除了让编译时类型与运行时类型不同以外,还要求调用的方法一定是被子类重写过的方法。
因为一旦出现两种状态,必定是因为子类与父类的方法不一致造成的,如果调用的是子类继承父类的方法,那便只存在一种状态了。
3.子类新增的属性
上转型对象不能调用子类新增的方法和属性,我们看一段代码:
//父类
public class Mammal {
public void move() {
System.out.println("正在移动、、、");
}
}
//子类
public class Whale extends Mammal{
public void move() {
System.out.println("鱼鳍游动、、、");
}
public void breath() {
System.out.println("正在呼吸、、、");
}
}
public class Earth {
public static void main(String[] args) {
Mammal mammal=new Whale();//对象上转型
mammal.breath();
}
}
这段代码中mammal是上转型对象,调用的breath方法是子类新增的方法,所以便会报错。为什么不能调用新增的方法呢?因为在编译时编译时类型是父类类型,所以编译器便会在父类类型中去寻找调用的方法,这时编译器便找不到子类新增的方法和新增的属性。
4.属性无多态
方法存在多态,但是属性不存在多态,这是一条硬性规定,没有为什么,下面这段代码执行结果是1000.0,因为属性不存在多态,所以调用的是父类的属性:
//父类
public class Mammal {
double weight=1000;
}
//子类
public class Whale extends Mammal{
String weight="1t";
}
public class Earth {
public static void main(String[] args) {
Mammal mammal=new Whale();//对象上转型
System.out.println(mammal.weight);
}
}
四. 对象下转型
刚才说了上转型对象不能调用子类新增的方法,但是如果想要调用新增的方法怎么办?这时候就需要对上转型对象进行对象下转型。
如果理解了对象上转型,看完下面这行代码,就知道对象下转型是什么意思了:
//父类
public class Mammal {
}
//子类
public class Whale extends Mammal{
}
public class Earth {
public static void main(String[] args) {
Mammal mammal=new Whale();//对象上转型
int age=(int)9.0;//强制类型转换
Whale whale=(Whale)mammal;//对象下转型
}
}
对象下转型就是将上转型对象转型为父类的类型,它的原理是相当于把mammal指向的上转型对象的地址存放到了新创建的whale中,此时你用mammal还是无法调用子类新增的对象,但是你用whale便可以调用新增的方法
但是要注意的是,对象下转型操作只能对上转型对象使用